diff --git a/bchain/bitcoinrpc.go b/bchain/bitcoinrpc.go index 09929fd5..93ac5ef1 100644 --- a/bchain/bitcoinrpc.go +++ b/bchain/bitcoinrpc.go @@ -245,6 +245,18 @@ type resSendRawTransaction struct { Result string `json:"result"` } +// getmempoolentry + +type cmdGetMempoolEntry struct { + Method string `json:"method"` + Params []string `json:"params"` +} + +type resGetMempoolEntry struct { + Error *RPCError `json:"error"` + Result *MempoolEntry `json:"result"` +} + // GetBestBlockHash returns hash of the tip of the best-block-chain. func (b *BitcoinRPC) GetBestBlockHash() (string, error) { @@ -538,6 +550,25 @@ func (b *BitcoinRPC) SendRawTransaction(tx string) (string, error) { return res.Result, nil } +func (b *BitcoinRPC) GetMempoolEntry(txid string) (*MempoolEntry, error) { + glog.V(1).Info("rpc: getmempoolentry") + + res := resGetMempoolEntry{} + req := cmdGetMempoolEntry{ + Method: "getmempoolentry", + Params: []string{txid}, + } + err := b.call(&req, &res) + + if err != nil { + return nil, err + } + if res.Error != nil { + return nil, res.Error + } + return res.Result, nil +} + func (b *BitcoinRPC) call(req interface{}, res interface{}) error { httpData, err := json.Marshal(req) if err != nil { diff --git a/bchain/types.go b/bchain/types.go index 0e1d9947..bdf73b2e 100644 --- a/bchain/types.go +++ b/bchain/types.go @@ -59,6 +59,21 @@ type BlockHeader struct { Confirmations int `json:"confirmations"` } +type MempoolEntry struct { + Size uint32 `json:"size"` + Fee float64 `json:"fee"` + ModifiedFee float64 `json:"modifiedfee"` + Time float64 `json:"time"` + Height uint32 `json:"height"` + DescendantCount uint32 `json:"descendantcount"` + DescendantSize uint32 `json:"descendantsize"` + DescendantFees uint32 `json:"descendantfees"` + AncestorCount uint32 `json:"ancestorcount"` + AncestorSize uint32 `json:"ancestorsize"` + AncestorFees uint32 `json:"ancestorfees"` + Depends []string `json:"depends"` +} + type RPCError struct { Code int `json:"code"` Message string `json:"message"` @@ -83,6 +98,7 @@ type BlockChain interface { ResyncMempool(onNewTxAddr func(txid string, addr string)) error GetMempoolTransactions(outputScript []byte) ([]string, error) GetMempoolSpentOutput(outputTxid string, vout uint32) string + GetMempoolEntry(txid string) (*MempoolEntry, error) // parser GetChainParser() BlockChainParser } diff --git a/docker/Dockerfile b/docker/Dockerfile index 3502204e..f75caff3 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,13 +3,16 @@ FROM debian:9 RUN apt-get update && apt-get install -y \ - build-essential git wget pkg-config lxc-dev libzmq3-dev libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev + build-essential git wget pkg-config lxc-dev libzmq3-dev libgflags-dev \ + libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev graphviz ENV GOLANG_VERSION=go1.9.2.linux-amd64 ENV GOPATH=/go +ENV PATH=$PATH:$GOPATH/bin # install and configure go -RUN cd /opt && wget https://storage.googleapis.com/golang/$GOLANG_VERSION.tar.gz && tar xf $GOLANG_VERSION.tar.gz +RUN cd /opt && wget https://storage.googleapis.com/golang/$GOLANG_VERSION.tar.gz && \ + tar xf $GOLANG_VERSION.tar.gz RUN ln -s /opt/go/bin/go /usr/bin/go RUN mkdir -p $GOPATH RUN echo -n "GO version: " && go version @@ -19,18 +22,19 @@ RUN echo -n "GOPATH: " && echo $GOPATH RUN cd /opt && git clone https://github.com/facebook/rocksdb.git RUN cd /opt/rocksdb && CFLAGS=-fPIC CXXFLAGS=-fPIC make static_lib -# install gorocksdb -RUN CGO_CFLAGS="-I/opt/rocksdb/include" CGO_LDFLAGS="-L/opt/rocksdb -lrocksdb -lstdc++ -lm -lz -lbz2 -lsnappy -llz4" go get github.com/tecbot/gorocksdb - -RUN go get github.com/golang/glog -RUN go get github.com/martinboehm/golang-socketio -RUN go get github.com/btcsuite/btcd -RUN go get github.com/gorilla/handlers -RUN go get github.com/bsm/go-vlq -RUN go get github.com/gorilla/handlers -RUN go get github.com/gorilla/mux -RUN go get github.com/pebbe/zmq4 -RUN go get github.com/pkg/profile +RUN go get github.com/golang/dep/cmd/dep +# clone repo and ensure dependencies RUN cd $GOPATH/src && git clone https://github.com/jpochyla/blockbook.git -RUN cd $GOPATH/src/blockbook && go build +RUN cd $GOPATH/src/blockbook && dep ensure + +# install gorocksdb +RUN cd $GOPATH/src/blockbook/vendor/github.com/tecbot/gorocksdb && \ + CGO_CFLAGS="-I/opt/rocksdb/include" \ + CGO_LDFLAGS="-L/opt/rocksdb -lrocksdb -lstdc++ -lm -lz -lbz2 -lsnappy -llz4" \ + go install . + + +WORKDIR $GOPATH/src/blockbook + +CMD go build -o /out/blockbook diff --git a/docker/build.sh b/docker/build.sh index 1f9e0a4f..106f3bef 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -3,7 +3,14 @@ set -e cd `dirname $0` +# prepare build image docker build -t blockbook-build . -docker run -t -v $(pwd):/out blockbook-build /bin/cp /go/src/blockbook/blockbook /out/ + +if [ "$1" == "local" ]; then + SRC_BIND="-v $(pwd)/..:/go/src/blockbook" +fi + +# build binary +docker run -t --rm -v $(pwd):/out $SRC_BIND blockbook-build strip blockbook diff --git a/server/socketio.go b/server/socketio.go index 6d93cc6a..7db45fbe 100644 --- a/server/socketio.go +++ b/server/socketio.go @@ -160,19 +160,26 @@ var onMessageHandlers = map[string]func(*SocketIoServer, json.RawMessage) (inter return s.getInfo() }, "\"getDetailedTransaction\"": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) { - txid, err := unmarshalGetDetailedTransaction(params) + txid, err := unmarshalStringParameter(params) if err == nil { rv, err = s.getDetailedTransaction(txid) } return }, "\"sendTransaction\"": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) { - tx, err := unmarshalSendTransaction(params) + tx, err := unmarshalStringParameter(params) if err == nil { rv, err = s.sendTransaction(tx) } return }, + "\"getMempoolEntry\"": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) { + txid, err := unmarshalStringParameter(params) + if err == nil { + rv, err = s.getMempoolEntry(txid) + } + return + }, } type resultError struct { @@ -585,12 +592,12 @@ func (s *SocketIoServer) getInfo() (res resultGetInfo, err error) { return } -func unmarshalGetDetailedTransaction(params []byte) (hash string, err error) { +func unmarshalStringParameter(params []byte) (s string, err error) { p, err := unmarshalArray(params, 1) if err != nil { return } - hash, ok := p[0].(string) + s, ok := p[0].(string) if ok { return } @@ -655,19 +662,6 @@ func (s *SocketIoServer) getDetailedTransaction(txid string) (res resultGetDetai return } -func unmarshalSendTransaction(params []byte) (tx string, err error) { - p, err := unmarshalArray(params, 1) - if err != nil { - return - } - tx, ok := p[0].(string) - if ok { - return - } - err = errors.New("incorrect parameter") - return -} - type resultSendTransaction struct { Result string `json:"result"` } @@ -681,6 +675,19 @@ func (s *SocketIoServer) sendTransaction(tx string) (res resultSendTransaction, return } +type resultGetMempoolEntry struct { + Result *bchain.MempoolEntry `json:"result"` +} + +func (s *SocketIoServer) getMempoolEntry(txid string) (res resultGetMempoolEntry, err error) { + entry, err := s.chain.GetMempoolEntry(txid) + if err != nil { + return res, err + } + res.Result = entry + return +} + // onSubscribe expects two event subscriptions based on the req parameter (including the doublequotes): // "bitcoind/hashblock" // "bitcoind/addresstxid",["2MzTmvPJLZaLzD9XdN3jMtQA5NexC3rAPww","2NAZRJKr63tSdcTxTN3WaE9ZNDyXy6PgGuv"] diff --git a/server/static/test.html b/server/static/test.html index 4f8bcc97..4eb7a4ba 100644 --- a/server/static/test.html +++ b/server/static/test.html @@ -204,6 +204,23 @@ document.getElementById('subscribeAddressTxidResult').innerText += JSON.stringify(result).replace(/,/g, ", ") + "\n"; }); } + + function getMempoolEntry() { + var hash = document.getElementById('getMempoolEntryHash').value; + lookupMempoolEntry(hash, function (result) { + console.log('getMempoolEntry sent successfully'); + console.log(result); + document.getElementById('getMempoolEntryResult').innerText = JSON.stringify(result).replace(/,/g, ", "); + }); + } + + function lookupMempoolEntry(hash, f) { + const method = 'getMempoolEntry'; + const params = [ + hash, + ]; + return socket.send({ method, params }, f); + } @@ -343,10 +360,24 @@
+
+
+ +
+
+ +
+
+
+
+
+
+
+
- \ No newline at end of file +