Implement Bitcore socket.io method getBlockHeader

pull/1/head
Martin Boehm 2018-02-07 18:35:34 +01:00
parent d50392b0d0
commit 8c9dfc3ef4
3 changed files with 125 additions and 14 deletions

View File

@ -156,7 +156,7 @@ func main() {
var socketIoServer *server.SocketIoServer
if *socketIoBinding != "" {
socketIoServer, err = server.NewSocketIoServer(*socketIoBinding, index, mempool)
socketIoServer, err = server.NewSocketIoServer(*socketIoBinding, index, mempool, chain)
if err != nil {
glog.Fatal("socketio: ", err)
}

View File

@ -21,10 +21,11 @@ type SocketIoServer struct {
https *http.Server
db *db.RocksDB
mempool *bchain.Mempool
chain *bchain.BitcoinRPC
}
// NewSocketIoServer creates new SocketIo interface to blockbook and returns its handle
func NewSocketIoServer(binding string, db *db.RocksDB, mempool *bchain.Mempool) (*SocketIoServer, error) {
func NewSocketIoServer(binding string, db *db.RocksDB, mempool *bchain.Mempool, chain *bchain.BitcoinRPC) (*SocketIoServer, error) {
server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport())
server.On(gosocketio.OnConnection, func(c *gosocketio.Channel) {
@ -58,9 +59,11 @@ func NewSocketIoServer(binding string, db *db.RocksDB, mempool *bchain.Mempool)
server: server,
db: db,
mempool: mempool,
chain: chain,
}
server.On("message", s.onMessage)
server.On("subscribe", s.onSubscribe)
return s, nil
}
@ -110,14 +113,19 @@ func (s *SocketIoServer) onMessage(c *gosocketio.Channel, req map[string]json.Ra
if err == nil {
rv, err = s.getAddressTxids(addr, &rr)
}
} else if method == "\"getBlockHeader\"" {
height, hash, err := unmarshalGetBlockHeader(params)
if err == nil {
rv, err = s.getBlockHeader(height, hash)
}
} else {
err = errors.New("unknown method")
}
if err == nil {
glog.Info(c.Id(), " ", method, " success")
glog.Info(c.Id(), " onMessage ", method, " success")
return rv
}
glog.Error(c.Id(), " ", method, ": ", err)
glog.Error(c.Id(), " onMessage ", method, ": ", err)
return ""
}
@ -127,6 +135,10 @@ func unmarshalGetAddressTxids(params []byte) (addr []string, rr reqRange, err er
if err != nil {
return
}
if len(p) != 2 {
err = errors.New("incorrect number of parameters")
return
}
err = json.Unmarshal(p[0], &addr)
if err != nil {
return
@ -171,3 +183,72 @@ func (s *SocketIoServer) getAddressTxids(addr []string, rr *reqRange) ([]string,
}
return txids, nil
}
func unmarshalGetBlockHeader(params []byte) (height uint32, hash string, err error) {
var p []interface{}
err = json.Unmarshal(params, &p)
if err != nil {
return
}
if len(p) != 1 {
err = errors.New("incorrect number of parameters")
return
}
fheight, ok := p[0].(float64)
if ok {
return uint32(fheight), "", nil
}
hash, ok = p[0].(string)
if ok {
return
}
err = errors.New("incorrect parameter")
return
}
type resultGetBlockHeader struct {
Result struct {
Hash string `json:"hash"`
Version int `json:"version"`
Confirmations int `json:"confirmations"`
Height int `json:"height"`
ChainWork string `json:"chainWork"`
NextHash string `json:"nextHash"`
MerkleRoot string `json:"merkleRoot"`
Time int `json:"time"`
MedianTime int `json:"medianTime"`
Nonce int `json:"nonce"`
Bits string `json:"bits"`
Difficulty int `json:"difficulty"`
} `json:"result"`
}
func (s *SocketIoServer) getBlockHeader(height uint32, hash string) (res resultGetBlockHeader, err error) {
if hash == "" {
if height == 0 {
height, hash, err = s.db.GetBestBlock()
if err != nil {
return
}
} else {
hash, err = s.db.GetBlockHash(height)
if err != nil {
return
}
}
}
bh, err := s.chain.GetBlockHeader(hash)
if err != nil {
return
}
res.Result.Hash = bh.Hash
res.Result.Confirmations = bh.Confirmations
res.Result.Height = int(bh.Height)
res.Result.NextHash = bh.Next
return
}
func (s *SocketIoServer) onSubscribe(c *gosocketio.Channel, req map[string]json.RawMessage) interface{} {
glog.Info(c.Id(), " onSubscribe ", req)
return nil
}

View File

@ -23,13 +23,13 @@
});
}
function lookupTransactionIds() {
var addresses = document.getElementById('addresses').value.split(",");
var mempool = document.getElementById("addressesMempool").checked;
function getAddressTxids() {
var addresses = document.getElementById('getAddressTxidsAddresses').value.split(",");
var mempool = document.getElementById("getAddressTxidsMempool").checked;
lookupTransactionsIdsMempool(addresses, mempool, 2000000, 0, function (result) {
console.log('sent successfully');
console.log('getAddressTxids sent successfully');
console.log(result);
document.getElementById('lookupTransactionIdsResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
document.getElementById('getAddressTxidsResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
});
}
@ -49,7 +49,23 @@
rangeParam,
];
return socket.send({ method, params }, f);
}
}
function getBlockHeader() {
var height = document.getElementById('getBlockHeaderHeight').value;
lookupBlockHash(parseInt(height), function (result) {
console.log('getBlockHeader sent successfully');
console.log(result);
document.getElementById('getBlockHeaderResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
});
}
function lookupBlockHash(height, f) {
const method = 'getBlockHeader';
const params = [height];
return socket.send({ method, params }, f);
}
</script>
</head>
@ -71,18 +87,32 @@
</div>
<div class="row">
<div class="col">
<input class="btn btn-secondary" type="button" value="getAddressTxids" onclick="lookupTransactionIds()">
<input class="btn btn-secondary" type="button" value="getAddressTxids" onclick="getAddressTxids()">
</div>
<div class="col-8">
<input type="text" class="form-control" id="addresses" value="2MxvKTW83yhVsGCr4BSRqmhca7r8TB2dgW8,bc1qrsf2l34jvqnq0lduyz0j5pfu2nkd93nnq0qggn">
<input type="text" class="form-control" id="getAddressTxidsAddresses" value="2MxvKTW83yhVsGCr4BSRqmhca7r8TB2dgW8,bc1qrsf2l34jvqnq0lduyz0j5pfu2nkd93nnq0qggn">
</div>
<div class="col form-inline">
<input type="checkbox" id="addressesMempool">&nbsp;
<input type="checkbox" id="getAddressTxidsMempool">&nbsp;
<label>only mempool</label>
</div>
</div>
<div class="row">
<div class="col" id="lookupTransactionIdsResult">
<div class="col" id="getAddressTxidsResult">
</div>
</div>
<div class="row">
<div class="col">
<input class="btn btn-secondary" type="button" value="getBlockHeader" onclick="getBlockHeader()">
</div>
<div class="col-8">
<input type="text" class="form-control" id="getBlockHeaderHeight" value="0">
</div>
<div class="col">
</div>
</div>
<div class="row">
<div class="col" id="getBlockHeaderResult">
</div>
</div>
</div>