Skip to content
Permalink
Browse files

api: add /block/.../raw endpoints

Also add api/types.BlockRaw.

use strings.Builder to avoid copying a long string
  • Loading branch information...
chappjc committed Feb 19, 2019
1 parent 0be15e3 commit faf775e171d4458959a6b6e4737dd9d1091afbc4
Showing with 55 additions and 1 deletion.
  1. +3 −0 api/apirouter.go
  2. +35 −1 api/apiroutes.go
  3. +7 −0 api/types/apitypes.go
  4. +10 −0 db/dcrsqlite/apisource.go
@@ -39,6 +39,7 @@ func NewAPIRouter(app *appContext, useRealIP bool) apiMux {
rd.Get("/height", app.currentHeight)
rd.Get("/hash", app.getBlockHash)
rd.Get("/header", app.getBlockHeader)
rd.Get("/raw", app.getBlockRaw)
rd.Get("/size", app.getBlockSize)
rd.Get("/subsidy", app.blockSubsidies)
rd.With((middleware.Compress(1))).Get("/verbose", app.getBlockVerbose)
@@ -54,6 +55,7 @@ func NewAPIRouter(app *appContext, useRealIP bool) apiMux {
rd.Get("/", app.getBlockSummary)
rd.Get("/height", app.getBlockHeight)
rd.Get("/header", app.getBlockHeader)
rd.Get("/raw", app.getBlockRaw)
rd.Get("/size", app.getBlockSize)
rd.Get("/subsidy", app.blockSubsidies)
rd.With((middleware.Compress(1))).Get("/verbose", app.getBlockVerbose)
@@ -69,6 +71,7 @@ func NewAPIRouter(app *appContext, useRealIP bool) apiMux {
rd.Get("/", app.getBlockSummary)
rd.Get("/header", app.getBlockHeader)
rd.Get("/hash", app.getBlockHash)
rd.Get("/raw", app.getBlockRaw)
rd.Get("/size", app.getBlockSize)
rd.Get("/subsidy", app.blockSubsidies)
rd.With((middleware.Compress(1))).Get("/verbose", app.getBlockVerbose)
@@ -9,6 +9,7 @@ import (
"context"
"database/sql"
"encoding/csv"
"encoding/hex"
"encoding/json"
"fmt"
"io"
@@ -23,6 +24,7 @@ import (
"github.com/decred/dcrd/chaincfg"
"github.com/decred/dcrd/dcrjson/v2"
"github.com/decred/dcrd/rpcclient/v2"
"github.com/decred/dcrd/wire"
apitypes "github.com/decred/dcrdata/v4/api/types"
"github.com/decred/dcrdata/v4/db/agendadb"
"github.com/decred/dcrdata/v4/db/dbtypes"
@@ -42,7 +44,7 @@ type DataSourceLite interface {
GetBestBlockHash() (string, error)
GetBlockHash(idx int64) (string, error)
GetBlockHeight(hash string) (int64, error)
//Get(idx int) *blockdata.BlockData
GetBlockByHash(string) (*wire.MsgBlock, error)
GetHeader(idx int) *dcrjson.GetBlockHeaderVerboseResult
GetBlockVerbose(idx int, verboseTx bool) *dcrjson.GetBlockVerboseResult
GetBlockVerboseByHash(hash string, verboseTx bool) *dcrjson.GetBlockVerboseResult
@@ -441,6 +443,38 @@ func (c *appContext) getBlockHeader(w http.ResponseWriter, r *http.Request) {
writeJSON(w, blockHeader, c.getIndentQuery(r))
}

func (c *appContext) getBlockRaw(w http.ResponseWriter, r *http.Request) {
hash := c.getBlockHashCtx(r)
if hash == "" {
http.Error(w, http.StatusText(422), 422)
return
}

msgBlock, err := c.BlockData.GetBlockByHash(hash)
if err != nil {
apiLog.Errorf("Unable to get block %s: %v", hash, err)
http.Error(w, http.StatusText(422), 422)
return
}

var hexString strings.Builder
hexString.Grow(msgBlock.SerializeSize())
err = msgBlock.Serialize(hex.NewEncoder(&hexString))
if err != nil {
apiLog.Errorf("Unable to serialize block %s: %v", hash, err)
http.Error(w, http.StatusText(422), 422)
return
}

blockRaw := &apitypes.BlockRaw{
Height: msgBlock.Header.Height,
Hash: hash,
Hex: hexString.String(),
}

writeJSON(w, blockRaw, c.getIndentQuery(r))
}

func (c *appContext) getBlockVerbose(w http.ResponseWriter, r *http.Request) {
hash := c.getBlockHashCtx(r)
if hash == "" {
@@ -118,6 +118,13 @@ type BlockID struct {
BlockTime int64 `json:"blocktime"`
}

// BlockRaw contains the hexadecimal encoded bytes of a serialized block.
type BlockRaw struct {
Height uint32 `json:"height"`
Hash string `json:"hash"`
Hex string `json:"hex"`
}

// VoutMined appends a best block hash, number of confimations and if a
// transaction is a coinbase to a transaction output
type VoutMined struct {
@@ -491,6 +491,16 @@ func (db *WiredDB) GetBlockVerbose(idx int, verboseTx bool) *dcrjson.GetBlockVer
func (db *WiredDB) GetBlockVerboseByHash(hash string, verboseTx bool) *dcrjson.GetBlockVerboseResult {
return rpcutils.GetBlockVerboseByHash(db.client, hash, verboseTx)
}

func (db *WiredDB) GetBlockByHash(hash string) (*wire.MsgBlock, error) {
blockHash, err := chainhash.NewHashFromStr(hash)
if err != nil {
log.Errorf("Invalid block hash %s", hash)
return nil, err
}
return db.client.GetBlock(blockHash)
}

func (db *WiredDB) CoinSupply() (supply *apitypes.CoinSupply) {
coinSupply, err := db.client.GetCoinSupply()
if err != nil {

0 comments on commit faf775e

Please sign in to comment.
You can’t perform that action at this time.