mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 11:26:44 +01:00
Extend statedb and use prefixes, add debugapi
In statedb:
- Store all values using prefixes for keys to allow iteration
- Add methods MTGetRoot, GetAccounts
Implement debugapi, an http server with debugging endpoints:
- debugAPI.GET("sdb/batchnum", a.handleCurrentBatch)
- debugAPI.GET("sdb/mtroot", a.handleMTRoot)
- debugAPI.GET("sdb/accounts", a.handleAccounts)
- debugAPI.GET("sdb/accounts/:Idx", a.handleAccount)
This commit is contained in:
@@ -3,6 +3,7 @@ package statedb
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -29,7 +30,18 @@ var (
|
|||||||
ErrToIdxNotFound = errors.New("ToIdx can not be found")
|
ErrToIdxNotFound = errors.New("ToIdx can not be found")
|
||||||
|
|
||||||
// KeyCurrentBatch is used as key in the db to store the current BatchNum
|
// KeyCurrentBatch is used as key in the db to store the current BatchNum
|
||||||
KeyCurrentBatch = []byte("currentbatch")
|
KeyCurrentBatch = []byte("k:currentbatch")
|
||||||
|
|
||||||
|
// PrefixKeyIdx is the key prefix for idx in the db
|
||||||
|
PrefixKeyIdx = []byte("i:")
|
||||||
|
// PrefixKeyAccHash is the key prefix for account hash in the db
|
||||||
|
PrefixKeyAccHash = []byte("h:")
|
||||||
|
// PrefixKeyMT is the key prefix for merkle tree in the db
|
||||||
|
PrefixKeyMT = []byte("m:")
|
||||||
|
// PrefixKeyAddr is the key prefix for address in the db
|
||||||
|
PrefixKeyAddr = []byte("a:")
|
||||||
|
// PrefixKeyAddrBJJ is the key prefix for address-babyjubjub in the db
|
||||||
|
PrefixKeyAddrBJJ = []byte("ab:")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -80,7 +92,7 @@ func NewStateDB(path string, typ TypeStateDB, nLevels int) (*StateDB, error) {
|
|||||||
|
|
||||||
var mt *merkletree.MerkleTree = nil
|
var mt *merkletree.MerkleTree = nil
|
||||||
if typ == TypeSynchronizer || typ == TypeBatchBuilder {
|
if typ == TypeSynchronizer || typ == TypeBatchBuilder {
|
||||||
mt, err = merkletree.NewMerkleTree(sto, nLevels)
|
mt, err = merkletree.NewMerkleTree(sto.WithPrefix(PrefixKeyMT), nLevels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -236,7 +248,7 @@ func (s *StateDB) Reset(batchNum common.BatchNum) error {
|
|||||||
|
|
||||||
if s.mt != nil {
|
if s.mt != nil {
|
||||||
// open the MT for the current s.db
|
// open the MT for the current s.db
|
||||||
mt, err := merkletree.NewMerkleTree(s.db, s.mt.MaxLevels())
|
mt, err := merkletree.NewMerkleTree(s.db.WithPrefix(PrefixKeyMT), s.mt.MaxLevels())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -251,6 +263,35 @@ func (s *StateDB) GetAccount(idx common.Idx) (*common.Account, error) {
|
|||||||
return getAccountInTreeDB(s.db, idx)
|
return getAccountInTreeDB(s.db, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAccounts returns all the accounts in the db. Use for debugging pruposes
|
||||||
|
// only.
|
||||||
|
func (s *StateDB) GetAccounts() ([]common.Account, error) {
|
||||||
|
idxDB := s.db.WithPrefix(PrefixKeyIdx)
|
||||||
|
idxs := []common.Idx{}
|
||||||
|
// NOTE: Current implementation of Iterate in the pebble interface is
|
||||||
|
// not efficient, as it iterates over all keys. Improve it following
|
||||||
|
// this example: https://github.com/cockroachdb/pebble/pull/923/files
|
||||||
|
if err := idxDB.Iterate(func(k []byte, v []byte) (bool, error) {
|
||||||
|
idx, err := common.IdxFromBytes(k)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
idxs = append(idxs, idx)
|
||||||
|
return true, nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
accs := []common.Account{}
|
||||||
|
for i := range idxs {
|
||||||
|
acc, err := s.GetAccount(idxs[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
accs = append(accs, *acc)
|
||||||
|
}
|
||||||
|
return accs, nil
|
||||||
|
}
|
||||||
|
|
||||||
// getAccountInTreeDB is abstracted from StateDB to be used from StateDB and
|
// getAccountInTreeDB is abstracted from StateDB to be used from StateDB and
|
||||||
// from ExitTree. GetAccount returns the account for the given Idx
|
// from ExitTree. GetAccount returns the account for the given Idx
|
||||||
func getAccountInTreeDB(sto db.Storage, idx common.Idx) (*common.Account, error) {
|
func getAccountInTreeDB(sto db.Storage, idx common.Idx) (*common.Account, error) {
|
||||||
@@ -258,17 +299,22 @@ func getAccountInTreeDB(sto db.Storage, idx common.Idx) (*common.Account, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
vBytes, err := sto.Get(idxBytes[:])
|
vBytes, err := sto.Get(append(PrefixKeyIdx, idxBytes[:]...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
accBytes, err := sto.Get(vBytes)
|
accBytes, err := sto.Get(append(PrefixKeyAccHash, vBytes...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var b [32 * common.NLeafElems]byte
|
var b [32 * common.NLeafElems]byte
|
||||||
copy(b[:], accBytes)
|
copy(b[:], accBytes)
|
||||||
return common.AccountFromBytes(b)
|
account, err := common.AccountFromBytes(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
account.Idx = idx
|
||||||
|
return account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateAccount creates a new Account in the StateDB for the given Idx. If
|
// CreateAccount creates a new Account in the StateDB for the given Idx. If
|
||||||
@@ -309,16 +355,16 @@ func createAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx common
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
_, err = tx.Get(idxBytes[:])
|
_, err = tx.Get(append(PrefixKeyIdx, idxBytes[:]...))
|
||||||
if err != db.ErrNotFound {
|
if err != db.ErrNotFound {
|
||||||
return nil, ErrAccountAlreadyExists
|
return nil, ErrAccountAlreadyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tx.Put(v.Bytes(), accountBytes[:])
|
err = tx.Put(append(PrefixKeyAccHash, v.Bytes()...), accountBytes[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = tx.Put(idxBytes[:], v.Bytes())
|
err = tx.Put(append(PrefixKeyIdx, idxBytes[:]...), v.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -360,7 +406,7 @@ func updateAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx common
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = tx.Put(v.Bytes(), accountBytes[:])
|
err = tx.Put(append(PrefixKeyAccHash, v.Bytes()...), accountBytes[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -368,7 +414,7 @@ func updateAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx common
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = tx.Put(idxBytes[:], v.Bytes())
|
err = tx.Put(append(PrefixKeyIdx, idxBytes[:]...), v.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -391,6 +437,11 @@ func (s *StateDB) MTGetProof(idx common.Idx) (*merkletree.CircomVerifierProof, e
|
|||||||
return s.mt.GenerateCircomVerifierProof(idx.BigInt(), s.mt.Root())
|
return s.mt.GenerateCircomVerifierProof(idx.BigInt(), s.mt.Root())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MTGetRoot returns the current root of the underlying Merkle Tree
|
||||||
|
func (s *StateDB) MTGetRoot() *big.Int {
|
||||||
|
return s.mt.Root().BigInt()
|
||||||
|
}
|
||||||
|
|
||||||
// LocalStateDB represents the local StateDB which allows to make copies from
|
// LocalStateDB represents the local StateDB which allows to make copies from
|
||||||
// the synchronizer StateDB, and is used by the tx-selector and the
|
// the synchronizer StateDB, and is used by the tx-selector and the
|
||||||
// batch-builder. LocalStateDB is an in-memory storage.
|
// batch-builder. LocalStateDB is an in-memory storage.
|
||||||
@@ -462,7 +513,7 @@ func (l *LocalStateDB) Reset(batchNum common.BatchNum, fromSynchronizer bool) er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// open the MT for the current s.db
|
// open the MT for the current s.db
|
||||||
mt, err := merkletree.NewMerkleTree(l.db, l.mt.MaxLevels())
|
mt, err := merkletree.NewMerkleTree(l.db.WithPrefix(PrefixKeyMT), l.mt.MaxLevels())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ func newAccount(t *testing.T, i int) *common.Account {
|
|||||||
address := ethCrypto.PubkeyToAddress(key.PublicKey)
|
address := ethCrypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
||||||
return &common.Account{
|
return &common.Account{
|
||||||
|
Idx: common.Idx(256 + i),
|
||||||
TokenID: common.TokenID(i),
|
TokenID: common.TokenID(i),
|
||||||
Nonce: common.Nonce(i),
|
Nonce: common.Nonce(i),
|
||||||
Balance: big.NewInt(1000),
|
Balance: big.NewInt(1000),
|
||||||
@@ -124,7 +125,7 @@ func TestStateDBWithoutMT(t *testing.T) {
|
|||||||
|
|
||||||
// create test accounts
|
// create test accounts
|
||||||
var accounts []*common.Account
|
var accounts []*common.Account
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
accounts = append(accounts, newAccount(t, i))
|
accounts = append(accounts, newAccount(t, i))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,22 +137,22 @@ func TestStateDBWithoutMT(t *testing.T) {
|
|||||||
|
|
||||||
// add test accounts
|
// add test accounts
|
||||||
for i := 0; i < len(accounts); i++ {
|
for i := 0; i < len(accounts); i++ {
|
||||||
_, err = sdb.CreateAccount(common.Idx(i), accounts[i])
|
_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(accounts); i++ {
|
for i := 0; i < len(accounts); i++ {
|
||||||
existingAccount := common.Idx(i)
|
existingAccount := accounts[i].Idx
|
||||||
accGetted, err := sdb.GetAccount(existingAccount)
|
accGetted, err := sdb.GetAccount(existingAccount)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, accounts[i], accGetted)
|
assert.Equal(t, accounts[i], accGetted)
|
||||||
}
|
}
|
||||||
|
|
||||||
// try already existing idx and get error
|
// try already existing idx and get error
|
||||||
existingAccount := common.Idx(1)
|
existingAccount := common.Idx(256)
|
||||||
_, err = sdb.GetAccount(existingAccount) // check that exist
|
_, err = sdb.GetAccount(existingAccount) // check that exist
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
_, err = sdb.CreateAccount(common.Idx(1), accounts[1]) // check that can not be created twice
|
_, err = sdb.CreateAccount(common.Idx(256), accounts[1]) // check that can not be created twice
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
assert.Equal(t, ErrAccountAlreadyExists, err)
|
assert.Equal(t, ErrAccountAlreadyExists, err)
|
||||||
|
|
||||||
@@ -188,35 +189,35 @@ func TestStateDBWithMT(t *testing.T) {
|
|||||||
|
|
||||||
// add test accounts
|
// add test accounts
|
||||||
for i := 0; i < len(accounts); i++ {
|
for i := 0; i < len(accounts); i++ {
|
||||||
_, err = sdb.CreateAccount(common.Idx(i), accounts[i])
|
_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(accounts); i++ {
|
for i := 0; i < len(accounts); i++ {
|
||||||
accGetted, err := sdb.GetAccount(common.Idx(i))
|
accGetted, err := sdb.GetAccount(accounts[i].Idx)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, accounts[i], accGetted)
|
assert.Equal(t, accounts[i], accGetted)
|
||||||
}
|
}
|
||||||
|
|
||||||
// try already existing idx and get error
|
// try already existing idx and get error
|
||||||
_, err = sdb.GetAccount(common.Idx(1)) // check that exist
|
_, err = sdb.GetAccount(common.Idx(256)) // check that exist
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
_, err = sdb.CreateAccount(common.Idx(1), accounts[1]) // check that can not be created twice
|
_, err = sdb.CreateAccount(common.Idx(256), accounts[1]) // check that can not be created twice
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
assert.Equal(t, ErrAccountAlreadyExists, err)
|
assert.Equal(t, ErrAccountAlreadyExists, err)
|
||||||
|
|
||||||
_, err = sdb.MTGetProof(common.Idx(1))
|
_, err = sdb.MTGetProof(common.Idx(256))
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
// update accounts
|
// update accounts
|
||||||
for i := 0; i < len(accounts); i++ {
|
for i := 0; i < len(accounts); i++ {
|
||||||
accounts[i].Nonce = accounts[i].Nonce + 1
|
accounts[i].Nonce = accounts[i].Nonce + 1
|
||||||
_, err = sdb.UpdateAccount(common.Idx(i), accounts[i])
|
_, err = sdb.UpdateAccount(accounts[i].Idx, accounts[i])
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
a, err := sdb.GetAccount(common.Idx(1)) // check that account value has been updated
|
a, err := sdb.GetAccount(common.Idx(256)) // check that account value has been updated
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, accounts[1].Nonce, a.Nonce)
|
assert.Equal(t, accounts[0].Nonce, a.Nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckpoints(t *testing.T) {
|
func TestCheckpoints(t *testing.T) {
|
||||||
@@ -234,7 +235,7 @@ func TestCheckpoints(t *testing.T) {
|
|||||||
|
|
||||||
// add test accounts
|
// add test accounts
|
||||||
for i := 0; i < len(accounts); i++ {
|
for i := 0; i < len(accounts); i++ {
|
||||||
_, err = sdb.CreateAccount(common.Idx(i), accounts[i])
|
_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,6 +335,31 @@ func TestCheckpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStateDBGetAccounts(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("", "tmpdb")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
sdb, err := NewStateDB(dir, TypeTxSelector, 0)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// create test accounts
|
||||||
|
var accounts []common.Account
|
||||||
|
for i := 0; i < 16; i++ {
|
||||||
|
account := newAccount(t, i)
|
||||||
|
accounts = append(accounts, *account)
|
||||||
|
}
|
||||||
|
|
||||||
|
// add test accounts
|
||||||
|
for i := range accounts {
|
||||||
|
_, err = sdb.CreateAccount(accounts[i].Idx, &accounts[i])
|
||||||
|
require.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dbAccounts, err := sdb.GetAccounts()
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, accounts, dbAccounts)
|
||||||
|
}
|
||||||
|
|
||||||
func printCheckpoints(t *testing.T, path string) {
|
func printCheckpoints(t *testing.T, path string) {
|
||||||
files, err := ioutil.ReadDir(path)
|
files, err := ioutil.ReadDir(path)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// keyidx is used as key in the db to store the current Idx
|
// keyidx is used as key in the db to store the current Idx
|
||||||
keyidx = []byte("idx")
|
keyidx = []byte("k:idx")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *StateDB) resetZKInputs() {
|
func (s *StateDB) resetZKInputs() {
|
||||||
|
|||||||
@@ -51,12 +51,12 @@ func (s *StateDB) setIdxByEthAddrBJJ(idx common.Idx, addr ethCommon.Address, pk
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = tx.Put(k, idxBytes[:])
|
err = tx.Put(append(PrefixKeyAddrBJJ, k...), idxBytes[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// store Addr-idx
|
// store Addr-idx
|
||||||
err = tx.Put(addr.Bytes(), idxBytes[:])
|
err = tx.Put(append(PrefixKeyAddr, addr.Bytes()...), idxBytes[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ func (s *StateDB) setIdxByEthAddrBJJ(idx common.Idx, addr ethCommon.Address, pk
|
|||||||
// Ethereum Address. Will return common.Idx(0) and error in case that Idx is
|
// Ethereum Address. Will return common.Idx(0) and error in case that Idx is
|
||||||
// not found in the StateDB.
|
// not found in the StateDB.
|
||||||
func (s *StateDB) GetIdxByEthAddr(addr ethCommon.Address) (common.Idx, error) {
|
func (s *StateDB) GetIdxByEthAddr(addr ethCommon.Address) (common.Idx, error) {
|
||||||
b, err := s.db.Get(addr.Bytes())
|
b, err := s.db.Get(append(PrefixKeyAddr, addr.Bytes()...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Idx(0), ErrToIdxNotFound
|
return common.Idx(0), ErrToIdxNotFound
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ func (s *StateDB) GetIdxByEthAddrBJJ(addr ethCommon.Address, pk *babyjub.PublicK
|
|||||||
} else if !bytes.Equal(addr.Bytes(), common.EmptyAddr.Bytes()) && pk != nil {
|
} else if !bytes.Equal(addr.Bytes(), common.EmptyAddr.Bytes()) && pk != nil {
|
||||||
// case ToEthAddr!=0 && ToBJJ!=0
|
// case ToEthAddr!=0 && ToBJJ!=0
|
||||||
k := concatEthAddrBJJ(addr, pk)
|
k := concatEthAddrBJJ(addr, pk)
|
||||||
b, err := s.db.Get(k)
|
b, err := s.db.Get(append(PrefixKeyAddrBJJ, k...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Idx(0), ErrToIdxNotFound
|
return common.Idx(0), ErrToIdxNotFound
|
||||||
}
|
}
|
||||||
|
|||||||
4
go.mod
4
go.mod
@@ -7,7 +7,8 @@ require (
|
|||||||
github.com/dghubble/sling v1.3.0
|
github.com/dghubble/sling v1.3.0
|
||||||
github.com/ethereum/go-ethereum v1.9.17
|
github.com/ethereum/go-ethereum v1.9.17
|
||||||
github.com/getkin/kin-openapi v0.22.0
|
github.com/getkin/kin-openapi v0.22.0
|
||||||
github.com/gin-gonic/gin v1.4.0
|
github.com/gin-contrib/cors v1.3.1
|
||||||
|
github.com/gin-gonic/gin v1.5.0
|
||||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||||
github.com/gobuffalo/packr/v2 v2.8.0
|
github.com/gobuffalo/packr/v2 v2.8.0
|
||||||
github.com/iden3/go-iden3-crypto v0.0.6-0.20200823174058-e04ca5764a15
|
github.com/iden3/go-iden3-crypto v0.0.6-0.20200823174058-e04ca5764a15
|
||||||
@@ -24,6 +25,7 @@ require (
|
|||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
go.uber.org/zap v1.16.0
|
go.uber.org/zap v1.16.0
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202
|
||||||
golang.org/x/tools/gopls v0.5.0 // indirect
|
golang.org/x/tools/gopls v0.5.0 // indirect
|
||||||
gopkg.in/go-playground/validator.v9 v9.29.1
|
gopkg.in/go-playground/validator.v9 v9.29.1
|
||||||
)
|
)
|
||||||
|
|||||||
11
go.sum
11
go.sum
@@ -165,10 +165,16 @@ github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49P
|
|||||||
github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs=
|
github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs=
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA=
|
||||||
|
github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
|
||||||
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g=
|
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g=
|
||||||
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
|
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
|
||||||
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ=
|
github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ=
|
||||||
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
|
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
|
||||||
|
github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc=
|
||||||
|
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
|
||||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
@@ -378,6 +384,8 @@ github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXT
|
|||||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||||
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
|
github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
|
||||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
@@ -570,10 +578,12 @@ github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1
|
|||||||
github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
|
github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
|
||||||
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
|
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
github.com/ugorji/go v1.1.8 h1:/D9x7IRpfMHDlizVOgxrag5Fh+/NY+LtI8bsr+AswRA=
|
github.com/ugorji/go v1.1.8 h1:/D9x7IRpfMHDlizVOgxrag5Fh+/NY+LtI8bsr+AswRA=
|
||||||
github.com/ugorji/go v1.1.8/go.mod h1:0lNM99SwWUIRhCXnigEMClngXBk/EmpTXa7mgiewYWA=
|
github.com/ugorji/go v1.1.8/go.mod h1:0lNM99SwWUIRhCXnigEMClngXBk/EmpTXa7mgiewYWA=
|
||||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648=
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648=
|
||||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
github.com/ugorji/go/codec v1.1.8 h1:4dryPvxMP9OtkjIbuNeK2nb27M38XMHLGlfNSNph/5s=
|
github.com/ugorji/go/codec v1.1.8 h1:4dryPvxMP9OtkjIbuNeK2nb27M38XMHLGlfNSNph/5s=
|
||||||
github.com/ugorji/go/codec v1.1.8/go.mod h1:X00B19HDtwvKbQY2DcYjvZxKQp8mzrJoQ6EgoIY/D2E=
|
github.com/ugorji/go/codec v1.1.8/go.mod h1:X00B19HDtwvKbQY2DcYjvZxKQp8mzrJoQ6EgoIY/D2E=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
@@ -713,6 +723,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|||||||
121
test/debugapi/debugapi.go
Normal file
121
test/debugapi/debugapi.go
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
package debugapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-contrib/cors"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/hermeznetwork/hermez-node/common"
|
||||||
|
"github.com/hermeznetwork/hermez-node/db/statedb"
|
||||||
|
"github.com/hermeznetwork/hermez-node/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleNoRoute(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusNotFound, gin.H{
|
||||||
|
"error": "404 page not found",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type errorMsg struct {
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
func badReq(err error, c *gin.Context) {
|
||||||
|
log.Errorw("Bad request", "err", err)
|
||||||
|
c.JSON(http.StatusBadRequest, errorMsg{
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DebugAPI is an http API with debugging endpoints
|
||||||
|
type DebugAPI struct {
|
||||||
|
addr string
|
||||||
|
stateDB *statedb.StateDB // synchronizer statedb
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDebugAPI creates a new DebugAPI
|
||||||
|
func NewDebugAPI(addr string, stateDB *statedb.StateDB) *DebugAPI {
|
||||||
|
return &DebugAPI{
|
||||||
|
stateDB: stateDB,
|
||||||
|
addr: addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *DebugAPI) handleAccount(c *gin.Context) {
|
||||||
|
uri := struct {
|
||||||
|
Idx uint32
|
||||||
|
}{}
|
||||||
|
if err := c.ShouldBindUri(&uri); err != nil {
|
||||||
|
badReq(err, c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account, err := a.stateDB.GetAccount(common.Idx(uri.Idx))
|
||||||
|
if err != nil {
|
||||||
|
badReq(err, c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, account)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *DebugAPI) handleAccounts(c *gin.Context) {
|
||||||
|
accounts, err := a.stateDB.GetAccounts()
|
||||||
|
if err != nil {
|
||||||
|
badReq(err, c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, accounts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *DebugAPI) handleCurrentBatch(c *gin.Context) {
|
||||||
|
batchNum, err := a.stateDB.GetCurrentBatch()
|
||||||
|
if err != nil {
|
||||||
|
badReq(err, c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, batchNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *DebugAPI) handleMTRoot(c *gin.Context) {
|
||||||
|
root := a.stateDB.MTGetRoot()
|
||||||
|
c.JSON(http.StatusOK, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run starts the http server of the DebugAPI. To stop it, pass a context with
|
||||||
|
// cancelation (see `debugapi_test.go` for an example).
|
||||||
|
func (a *DebugAPI) Run(ctx context.Context) error {
|
||||||
|
api := gin.Default()
|
||||||
|
api.NoRoute(handleNoRoute)
|
||||||
|
api.Use(cors.Default())
|
||||||
|
debugAPI := api.Group("/debug")
|
||||||
|
|
||||||
|
debugAPI.GET("sdb/batchnum", a.handleCurrentBatch)
|
||||||
|
debugAPI.GET("sdb/mtroot", a.handleMTRoot)
|
||||||
|
debugAPI.GET("sdb/accounts", a.handleAccounts)
|
||||||
|
debugAPI.GET("sdb/accounts/:Idx", a.handleAccount)
|
||||||
|
|
||||||
|
debugAPIServer := &http.Server{
|
||||||
|
Addr: a.addr,
|
||||||
|
Handler: api,
|
||||||
|
// Use some hardcoded numberes that are suitable for testing
|
||||||
|
ReadTimeout: 30 * time.Second, //nolint:gomnd
|
||||||
|
WriteTimeout: 30 * time.Second, //nolint:gomnd
|
||||||
|
MaxHeaderBytes: 1 << 20, //nolint:gomnd
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
log.Infof("Debug API is ready at %v", a.addr)
|
||||||
|
if err := debugAPIServer.ListenAndServe(); err != nil &&
|
||||||
|
err != http.ErrServerClosed {
|
||||||
|
log.Fatalf("Listen: %s\n", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
<-ctx.Done()
|
||||||
|
log.Info("Stopping Debug API...")
|
||||||
|
if err := debugAPIServer.Shutdown(context.Background()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info("Debug API stopped")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
101
test/debugapi/debugapi_test.go
Normal file
101
test/debugapi/debugapi_test.go
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package debugapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"math/big"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/dghubble/sling"
|
||||||
|
ethCrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/hermeznetwork/hermez-node/common"
|
||||||
|
"github.com/hermeznetwork/hermez-node/db/statedb"
|
||||||
|
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newAccount(t *testing.T, i int) *common.Account {
|
||||||
|
var sk babyjub.PrivateKey
|
||||||
|
copy(sk[:], []byte(strconv.Itoa(i))) // only for testing
|
||||||
|
pk := sk.Public()
|
||||||
|
|
||||||
|
var key ecdsa.PrivateKey
|
||||||
|
key.D = big.NewInt(int64(i + 1)) // only for testing
|
||||||
|
key.PublicKey.X, key.PublicKey.Y = ethCrypto.S256().ScalarBaseMult(key.D.Bytes())
|
||||||
|
key.Curve = ethCrypto.S256()
|
||||||
|
address := ethCrypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
||||||
|
return &common.Account{
|
||||||
|
Idx: common.Idx(256 + i),
|
||||||
|
TokenID: common.TokenID(i),
|
||||||
|
Nonce: common.Nonce(i),
|
||||||
|
Balance: big.NewInt(1000),
|
||||||
|
PublicKey: pk,
|
||||||
|
EthAddr: address,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDebugAPI(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("", "tmpdb")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
sdb, err := statedb.NewStateDB(dir, statedb.TypeSynchronizer, 32)
|
||||||
|
require.Nil(t, err)
|
||||||
|
err = sdb.MakeCheckpoint() // Make a checkpoint to increment the batchNum
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
addr := "localhost:12345"
|
||||||
|
debugAPI := NewDebugAPI(addr, sdb)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
go func() {
|
||||||
|
err := debugAPI.Run(ctx)
|
||||||
|
require.Nil(t, err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
var accounts []common.Account
|
||||||
|
for i := 0; i < 16; i++ {
|
||||||
|
account := newAccount(t, i)
|
||||||
|
accounts = append(accounts, *account)
|
||||||
|
_, err = sdb.CreateAccount(account.Idx, account)
|
||||||
|
require.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
url := fmt.Sprintf("http://%v/debug/", addr)
|
||||||
|
|
||||||
|
var batchNum common.BatchNum
|
||||||
|
req, err := sling.New().Get(url).Path("sdb/batchnum").ReceiveSuccess(&batchNum)
|
||||||
|
require.Equal(t, http.StatusOK, req.StatusCode)
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, common.BatchNum(1), batchNum)
|
||||||
|
|
||||||
|
var mtroot *big.Int
|
||||||
|
req, err = sling.New().Get(url).Path("sdb/mtroot").ReceiveSuccess(&mtroot)
|
||||||
|
require.Equal(t, http.StatusOK, req.StatusCode)
|
||||||
|
require.Nil(t, err)
|
||||||
|
// Testing against a hardcoded value obtained by running the test and
|
||||||
|
// printing the value previously.
|
||||||
|
assert.Equal(t, "8902613552504893273500019895709436294962812188236308621387152512232191202510",
|
||||||
|
mtroot.String())
|
||||||
|
|
||||||
|
var accountAPI common.Account
|
||||||
|
req, err = sling.New().Get(url).
|
||||||
|
Path(fmt.Sprintf("sdb/accounts/%v", accounts[0].Idx)).
|
||||||
|
ReceiveSuccess(&accountAPI)
|
||||||
|
require.Equal(t, http.StatusOK, req.StatusCode)
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, accounts[0], accountAPI)
|
||||||
|
|
||||||
|
var accountsAPI []common.Account
|
||||||
|
req, err = sling.New().Get(url).Path("sdb/accounts").ReceiveSuccess(&accountsAPI)
|
||||||
|
require.Equal(t, http.StatusOK, req.StatusCode)
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, accounts, accountsAPI)
|
||||||
|
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user