Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ build-filrewardsd: $(GOVVV)
$(TXTL_BUILD_FLAGS) go build -ldflags="${GOVVV_FLAGS}" ./api/filrewardsd
.PHONY: build-filrewardsd

build-sendfild: $(GOVVV)
$(TXTL_BUILD_FLAGS) go build -ldflags="${GOVVV_FLAGS}" ./api/sendfild
.PHONY: build-sendfild

install: $(GOVVV)
$(TXTL_BUILD_FLAGS) go install -ldflags="${GOVVV_FLAGS}" ./...
.PHONY: install
Expand Down Expand Up @@ -70,6 +74,10 @@ install-filrewardsd: $(GOVVV)
$(TXTL_BUILD_FLAGS) go install -ldflags="${GOVVV_FLAGS}" ./api/filrewardsd
.PHONY: install-filrewardsd

install-sendfild: $(GOVVV)
$(TXTL_BUILD_FLAGS) go install -ldflags="${GOVVV_FLAGS}" ./api/sendfild
.PHONY: install-sendfild

define gen_release_files
$(GOX) -osarch=$(3) -output="build/$(2)/$(2)_${TXTL_VERSION}_{{.OS}}-{{.Arch}}/$(2)" -ldflags="${GOVVV_FLAGS}" $(1)
mkdir -p build/dist; \
Expand Down
74 changes: 74 additions & 0 deletions api/sendfild/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
FROM golang:1.15.5-buster
MAINTAINER Textile <contact@textile.io>

# This is (in large part) copied (with love) from
# https://hub.docker.com/r/ipfs/go-ipfs/dockerfile

# Install deps
RUN apt-get update && apt-get install -y \
libssl-dev \
ca-certificates

ENV SRC_DIR /textile

# Download packages first so they can be cached.
COPY go.mod go.sum $SRC_DIR/
RUN cd $SRC_DIR \
&& go mod download

COPY . $SRC_DIR

# Build the thing.
RUN cd $SRC_DIR \
&& TXTL_BUILD_FLAGS="CGO_ENABLED=0 GOOS=linux" make build-sendfild

# Get su-exec, a very minimal tool for dropping privileges,
# and tini, a very minimal init daemon for containers
ENV SUEXEC_VERSION v0.2
ENV TINI_VERSION v0.19.0
RUN set -eux; \
dpkgArch="$(dpkg --print-architecture)"; \
case "${dpkgArch##*-}" in \
"amd64" | "armhf" | "arm64") tiniArch="tini-static-$dpkgArch" ;;\
*) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \
esac; \
cd /tmp \
&& git clone https://github.com/ncopa/su-exec.git \
&& cd su-exec \
&& git checkout -q $SUEXEC_VERSION \
&& make su-exec-static \
&& cd /tmp \
&& wget -q -O tini https://github.com/krallin/tini/releases/download/$TINI_VERSION/$tiniArch \
&& chmod +x tini

# Now comes the actual target image, which aims to be as small as possible.
FROM busybox:1.31.1-glibc
LABEL maintainer="Textile <contact@textile.io>"

# Get the textile binary, entrypoint script, and TLS CAs from the build container.
ENV SRC_DIR /textile
COPY --from=0 $SRC_DIR/sendfild /usr/local/bin/sendfild
COPY --from=0 /tmp/su-exec/su-exec-static /sbin/su-exec
COPY --from=0 /tmp/tini /sbin/tini
COPY --from=0 /etc/ssl/certs /etc/ssl/certs

# This shared lib (part of glibc) doesn't seem to be included with busybox.
COPY --from=0 /lib/*-linux-gnu*/libdl.so.2 /lib/

# Copy over SSL libraries.
COPY --from=0 /usr/lib/*-linux-gnu*/libssl.so* /usr/lib/
COPY --from=0 /usr/lib/*-linux-gnu*/libcrypto.so* /usr/lib/

# listenAddrs
EXPOSE 7006

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be 5000 considering new standards?


# Create the repo directory.
ENV SENDFIL_PATH /data/sendfil
RUN mkdir -p $SENDFIL_PATH \
&& adduser -D -h $SENDFIL_PATH -u 1000 -G users sendfil \
&& chown sendfil:users $SENDFIL_PATH

# Switch to a non-privileged user.
USER sendfil

ENTRYPOINT ["/sbin/tini", "--", "sendfild"]
36 changes: 36 additions & 0 deletions api/sendfild/Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
FROM golang:1.15.5-buster

RUN apt-get update && apt-get install -y \
libssl-dev \
ca-certificates

RUN go get github.com/go-delve/delve/cmd/dlv

ENV SRC_DIR /textile

COPY go.mod go.sum $SRC_DIR/
RUN cd $SRC_DIR \
&& go mod download

COPY . $SRC_DIR

RUN cd $SRC_DIR \
&& CGO_ENABLED=0 GOOS=linux go build -gcflags "all=-N -l" -o sendfild api/sendfild/main.go

FROM debian:buster
LABEL maintainer="Textile <contact@textile.io>"

ENV SRC_DIR /textile
COPY --from=0 /go/bin/dlv /usr/local/bin/dlv
COPY --from=0 /etc/ssl/certs /etc/ssl/certs
COPY --from=0 $SRC_DIR/sendfild /usr/local/bin/sendfild

EXPOSE 10006
EXPOSE 8010

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same about 1006?
Not sure about 8010 should be changed.


ENV SENDFIL_PATH /data/sendfil
RUN adduser --home $SENDFIL_PATH --disabled-login --gecos "" --ingroup users sendfil

USER sendfil

ENTRYPOINT ["dlv", "--listen=0.0.0.0:40000", "--headless=true", "--accept-multiclient", "--continue", "--api-version=2", "exec", "/usr/local/bin/sendfild"]
199 changes: 199 additions & 0 deletions api/sendfild/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package client

import (
"context"
"fmt"
"time"

"github.com/textileio/textile/v2/api/sendfild/pb"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/timestamppb"
)

type Client struct {
c pb.SendFilServiceClient
conn *grpc.ClientConn
}
Comment thread
asutula marked this conversation as resolved.

func New(target string, opts ...grpc.DialOption) (*Client, error) {
conn, err := grpc.Dial(target, opts...)
if err != nil {
return nil, fmt.Errorf("creating gRPC client conn: %v", err)
}

c := pb.NewSendFilServiceClient(conn)

return &Client{
c: c,
conn: conn,
}, nil
}

type SendFilOption = func(*pb.SendFilRequest)

func SendFilWait() SendFilOption {
return func(req *pb.SendFilRequest) {
req.Wait = true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Early in review so I'm not entirely sure, but I can imagine that Wait blocks until confirmation.

Open question: should the "Wait" thing be encouraged if there's risk that the API timeouts and somehow the "send fil" continues after the API call errored? Maybe safer to discourage this use? (assuming my guess now of what "wait" means)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good point. I think it is normal and fine to want to wait here, and there is a chance that the underlying lotus call to StateMsgWait will timeout. This doesn't meant the transaction failed or timed out, just that our monitoring of it timed out. We need to make that clear to the caller. I think providing a proper error message in this case is the key.

}
}

func (c *Client) SendFil(ctx context.Context, from, to string, amountNanoFil int64, opts ...SendFilOption) (*pb.Txn, error) {
req := &pb.SendFilRequest{
From: from,
To: to,
AmountNanoFil: amountNanoFil,
}
for _, opt := range opts {
opt(req)
}
res, err := c.c.SendFil(ctx, req)
if err != nil {
return nil, err
}
return res.Txn, nil
}

type TxnOption = func(*pb.TxnRequest)

func TxnWait() TxnOption {
return func(req *pb.TxnRequest) {
req.Wait = true
}
}

func (c *Client) Txn(ctx context.Context, messageCid string, opts ...TxnOption) (*pb.Txn, error) {
Comment thread
asutula marked this conversation as resolved.
Outdated
req := &pb.TxnRequest{
MessageCid: messageCid,
}
for _, opt := range opts {
opt(req)
}
res, err := c.c.Txn(ctx, req)
if err != nil {
return nil, err
}
return res.Txn, nil
}

type ListTxnsOption = func(*pb.ListTxnsRequest)

func ListTxnsFrom(from string) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.FromFilter = from
}
}

func ListTxnsTo(to string) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.ToFilter = to
}
}

func ListTxnsInvolving(involving string) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.InvolvingFilter = involving
}
}

func ListTxnsAmountNanoFilLt(amountNanoFil int64) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.AmountNanoFilLtFilter = amountNanoFil
}
}

func ListTxnsAmountNanoFilGt(amountNanoFil int64) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.AmountNanoFilGtFilter = amountNanoFil
}
}

func ListTxnsAmountNanoFilLteq(amountNanoFil int64) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.AmountNanoFilLteqFilter = amountNanoFil
}
}

func ListTxnsAmountNanoFilGteq(amountNanoFil int64) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.AmountNanoFilGteqFilter = amountNanoFil
}
}

func ListTxnsAmountNanoFilEq(amountNanoFil int64) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.AmountNanoFilEqFilter = amountNanoFil
}
}

func ListTxnsMessageState(messageState pb.MessageState) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.MessageStateFilter = messageState
}
}

func ListTxnsWaiting(waitingFilter pb.WaitingFilter) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.WaitingFilter = waitingFilter
}
}

func ListTxnsCreatedAfter(time time.Time) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.CreatedAfter = timestamppb.New(time)
}
}

func ListTxnsCreatedBefore(time time.Time) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.CreatedBefore = timestamppb.New(time)
}
}

func ListTxnsUpdatedAfter(time time.Time) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.UpdatedAfter = timestamppb.New(time)
}
}

func ListTxnsUpdatedBefore(time time.Time) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.UpdatedBefore = timestamppb.New(time)
}
}

func ListTxnsAscending() ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.Ascending = true
}
}

func ListTxnsMoreToken(moreToken int64) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.MoreToken = moreToken
}
}

func ListTxnsLimit(limit int64) ListTxnsOption {
return func(req *pb.ListTxnsRequest) {
req.Limit = limit
}
}

func (c *Client) ListTxns(ctx context.Context, opts ...ListTxnsOption) ([]*pb.Txn, bool, int64, error) {
req := &pb.ListTxnsRequest{}
for _, opt := range opts {
opt(req)
}
res, err := c.c.ListTxns(ctx, req)
if err != nil {
return nil, false, 0, err
}
return res.Txns, res.More, res.MoreToken, nil
}

func (c *Client) Close() error {
if c == nil {
return nil
}
return c.conn.Close()
}
Loading