Read sapling activation height from RPC

This commit is contained in:
Aditya Kulkarni
2019-09-18 20:38:59 -07:00
parent b2389b6c12
commit 7bf4a8407b
2 changed files with 76 additions and 37 deletions

View File

@@ -8,13 +8,13 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"time"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/pkg/errors"
"github.com/adityapk00/btcd/rpcclient" "github.com/adityapk00/btcd/rpcclient"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/adityapk00/lightwalletd/frontend" "github.com/adityapk00/lightwalletd/frontend"
@@ -26,10 +26,11 @@ var log *logrus.Entry
var logger = logrus.New() var logger = logrus.New()
var db *sql.DB var db *sql.DB
// Options is a struct holding command line options
type Options struct { type Options struct {
dbPath string dbPath string
logLevel uint64 logLevel uint64
logPath string logPath string
zcashConfPath string zcashConfPath string
} }
@@ -115,26 +116,35 @@ func main() {
if err != nil { if err != nil {
log.WithFields(logrus.Fields{ log.WithFields(logrus.Fields{
"error": err, "error": err,
}).Warn("unable to get current height from local db storage") }).Warn("Unable to get current height from local db storage. This is OK if you're starting this for the first time.")
} }
//ingest from Sapling testnet height // Get the sapling activation height from the RPC
if height < 280000 { saplingHeight, err := getSaplingActivationHeight(rpcClient)
height = 280000 if err != nil {
log.WithFields(logrus.Fields{ log.WithFields(logrus.Fields{
"error": err, "error": err,
}).Warn("invalid current height read from local db storage") }).Warn("Unable to get sapling activation height")
} }
timeout_count := 0 log.WithField("saplingHeight", saplingHeight).Info("Got sapling height ", saplingHeight)
reorg_count := -1
//ingest from Sapling testnet height
if height < saplingHeight {
height = saplingHeight
log.WithFields(logrus.Fields{
"error": err,
}).Warn("invalid current height read from local db storage")
}
timeoutCount := 0
reorgCount := -1
hash := "" hash := ""
phash := "" phash := ""
// Start listening for new blocks // Start listening for new blocks
for { for {
if reorg_count > 0 { if reorgCount > 0 {
reorg_count = -1 reorgCount = -1
height -= 10 height -= 10
} }
block, err := getBlock(rpcClient, height) block, err := getBlock(rpcClient, height)
@@ -144,35 +154,35 @@ func main() {
"height": height, "height": height,
"error": err, "error": err,
}).Warn("error with getblock") }).Warn("error with getblock")
timeout_count++ timeoutCount++
if timeout_count == 3 { if timeoutCount == 3 {
log.WithFields(logrus.Fields{ log.WithFields(logrus.Fields{
"timeouts": timeout_count, "timeouts": timeoutCount,
}).Warn("unable to issue RPC call to zcashd node 3 times") }).Warn("unable to issue RPC call to zcashd node 3 times")
break break
} }
} }
if block != nil { if block != nil {
handleBlock(db, block) handleBlock(db, block)
if timeout_count > 0 { if timeoutCount > 0 {
timeout_count-- timeoutCount--
} }
phash = hex.EncodeToString(block.GetPrevHash()) phash = hex.EncodeToString(block.GetPrevHash())
//check for reorgs once we have inital block hash from startup //check for reorgs once we have inital block hash from startup
if hash != phash && reorg_count != -1 { if hash != phash && reorgCount != -1 {
reorg_count++ reorgCount++
log.WithFields(logrus.Fields{ log.WithFields(logrus.Fields{
"height": height, "height": height,
"hash": hash, "hash": hash,
"phash": phash, "phash": phash,
"reorg": reorg_count, "reorg": reorgCount,
}).Warn("REORG") }).Warn("REORG")
} else { } else {
hash = hex.EncodeToString(block.GetDisplayHash())
}
if reorg_count == -1 {
hash = hex.EncodeToString(block.GetDisplayHash()) hash = hex.EncodeToString(block.GetDisplayHash())
reorg_count =0 }
if reorgCount == -1 {
hash = hex.EncodeToString(block.GetDisplayHash())
reorgCount = 0
} }
height++ height++
} else { } else {
@@ -182,6 +192,36 @@ func main() {
} }
} }
func getSaplingActivationHeight(rpcClient *rpcclient.Client) (int, error) {
result, rpcErr := rpcClient.RawRequest("getblockchaininfo", make([]json.RawMessage, 0))
var err error
var errCode int64
// For some reason, the error responses are not JSON
if rpcErr != nil {
errParts := strings.SplitN(rpcErr.Error(), ":", 2)
errCode, err = strconv.ParseInt(errParts[0], 10, 32)
//Check to see if we are requesting a height the zcashd doesn't have yet
if err == nil && errCode == -8 {
return -1, nil
}
return -1, errors.Wrap(rpcErr, "error requesting block")
}
var f interface{}
err = json.Unmarshal(result, &f)
if err != nil {
return -1, errors.Wrap(err, "error reading JSON response")
}
upgradeJSON := f.(map[string]interface{})["upgrades"]
saplingJSON := upgradeJSON.(map[string]interface{})["76b809bb"] // Sapling ID
saplingHeight := saplingJSON.(map[string]interface{})["activationheight"].(float64)
return int(saplingHeight), nil
}
func getBlock(rpcClient *rpcclient.Client, height int) (*parser.Block, error) { func getBlock(rpcClient *rpcclient.Client, height int) (*parser.Block, error) {
params := make([]json.RawMessage, 2) params := make([]json.RawMessage, 2)
params[0] = json.RawMessage("\"" + strconv.Itoa(height) + "\"") params[0] = json.RawMessage("\"" + strconv.Itoa(height) + "\"")
@@ -204,7 +244,7 @@ func getBlock(rpcClient *rpcclient.Client, height int) (*parser.Block, error) {
var blockDataHex string var blockDataHex string
err = json.Unmarshal(result, &blockDataHex) err = json.Unmarshal(result, &blockDataHex)
if err != nil{ if err != nil {
return nil, errors.Wrap(err, "error reading JSON response") return nil, errors.Wrap(err, "error reading JSON response")
} }
@@ -224,7 +264,6 @@ func getBlock(rpcClient *rpcclient.Client, height int) (*parser.Block, error) {
return block, nil return block, nil
} }
func handleBlock(db *sql.DB, block *parser.Block) { func handleBlock(db *sql.DB, block *parser.Block) {
prevBlockHash := hex.EncodeToString(block.GetPrevHash()) prevBlockHash := hex.EncodeToString(block.GetPrevHash())
blockHash := hex.EncodeToString(block.GetEncodableHash()) blockHash := hex.EncodeToString(block.GetEncodableHash())

View File

@@ -58,7 +58,7 @@ func CreateTables(conn *sql.DB) error {
// TODO consider max/count queries instead of state table. bit of a coupling assumption though. // TODO consider max/count queries instead of state table. bit of a coupling assumption though.
func GetCurrentHeight(ctx context.Context, db *sql.DB) (int, error) { func GetCurrentHeight(ctx context.Context, db *sql.DB) (int, error) {
var height int var height int = -1
query := "SELECT current_height FROM state WHERE rowid = 1" query := "SELECT current_height FROM state WHERE rowid = 1"
err := db.QueryRowContext(ctx, query).Scan(&height) err := db.QueryRowContext(ctx, query).Scan(&height)
return height, err return height, err