[rpc] separate transaction counts rpc into regular vs staking (#2788)

* separate transaction counts rpi api into regular vs staking

* fix api_test.sh for getTransactionCount apiv1

* nit. return results directly for get(Staking)TransactionsCount apis
pull/2807/head
Jong Hyuck Won 5 years ago committed by GitHub
parent a37074c7d3
commit 8802f0ca1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      hmy/api_backend.go
  2. 2
      hmy/backend.go
  3. 5
      internal/hmyapi/README.md
  4. 6
      internal/hmyapi/apiv1/backend.go
  5. 6
      internal/hmyapi/apiv1/blockchain.go
  6. 30
      internal/hmyapi/apiv1/transactionpool.go
  7. 3
      internal/hmyapi/apiv2/backend.go
  8. 6
      internal/hmyapi/apiv2/blockchain.go
  9. 36
      internal/hmyapi/apiv2/transactionpool.go
  10. 3
      internal/hmyapi/backend.go
  11. 46
      node/node_explorer.go
  12. 14
      scripts/api_test.sh

@ -220,6 +220,16 @@ func (b *APIBackend) GetPoolTransactions() (types.PoolTransactions, error) {
return txs, nil
}
// GetAccountNonce returns the nonce value of the given address for the given block number
func (b *APIBackend) GetAccountNonce(
ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (uint64, error) {
state, _, err := b.StateAndHeaderByNumber(ctx, blockNr)
if state == nil || err != nil {
return 0, err
}
return state.GetNonce(address), state.Error()
}
// GetBalance returns balance of an given address.
func (b *APIBackend) GetBalance(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*big.Int, error) {
state, _, err := b.StateAndHeaderByNumber(ctx, blockNr)
@ -231,14 +241,22 @@ func (b *APIBackend) GetBalance(ctx context.Context, address common.Address, blo
// GetTransactionsHistory returns list of transactions hashes of address.
func (b *APIBackend) GetTransactionsHistory(address, txType, order string) ([]common.Hash, error) {
hashes, err := b.hmy.nodeAPI.GetTransactionsHistory(address, txType, order)
return hashes, err
return b.hmy.nodeAPI.GetTransactionsHistory(address, txType, order)
}
// GetStakingTransactionsHistory returns list of staking transactions hashes of address.
func (b *APIBackend) GetStakingTransactionsHistory(address, txType, order string) ([]common.Hash, error) {
hashes, err := b.hmy.nodeAPI.GetStakingTransactionsHistory(address, txType, order)
return hashes, err
return b.hmy.nodeAPI.GetStakingTransactionsHistory(address, txType, order)
}
// GetTransactionsCount returns the number of regular transactions of address.
func (b *APIBackend) GetTransactionsCount(address, txType string) (uint64, error) {
return b.hmy.nodeAPI.GetTransactionsCount(address, txType)
}
// GetStakingTransactionsCount returns the number of staking transactions of address.
func (b *APIBackend) GetStakingTransactionsCount(address, txType string) (uint64, error) {
return b.hmy.nodeAPI.GetStakingTransactionsCount(address, txType)
}
// NetVersion returns net version

@ -46,6 +46,8 @@ type NodeAPI interface {
GetNonceOfAddress(address common.Address) uint64
GetTransactionsHistory(address, txType, order string) ([]common.Hash, error)
GetStakingTransactionsHistory(address, txType, order string) ([]common.Hash, error)
GetTransactionsCount(address, txType string) (uint64, error)
GetStakingTransactionsCount(address, txType string) (uint64, error)
IsCurrentlyLeader() bool
ErroredStakingTransactionSink() []staking.RPCTransactionError
ErroredTransactionSink() []types.RPCTransactionError

@ -30,7 +30,7 @@
### Account related
* [x] hmy_getBalance - get balance for account address
* [x] hmy_getTransactionCount - get nonce for account address
* [x] hmy_getAccountNonce - get nonce for account address
* [ ] hmy_accounts - return accounts that lives in node
### Transactions related
@ -44,6 +44,9 @@
* [x] hmy_getTransactionByBlockNumberAndIndex - get transaction object of block by block number and index number
* [ ] hmy_sign - sign message using node specific sign method.
* [ ] hmy_pendingTransactions - returns the pending transactions list.
* [ ] hmy_getTransactionsCount - returns the number of confirmed (not pending) transactions count for the account
* [ ] hmy_getStakingTransactionsCount - returns the number of confirmed (not pending) staking transactions count for the account
### Contract related
* [ ] hmy_call - call contract method

@ -50,6 +50,8 @@ type Backend interface {
GetPoolTransactions() (types.PoolTransactions, error)
GetPoolTransaction(txHash common.Hash) types.PoolTransaction
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
// Get account nonce
GetAccountNonce(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (uint64, error)
// Stats() (pending int, queued int)
// TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions)
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
@ -60,10 +62,10 @@ type Backend interface {
// Get validators for a particular epoch
GetValidators(epoch *big.Int) (*shard.Committee, error)
GetShardID() uint32
// Get transactions history for an address
GetTransactionsHistory(address, txType, order string) ([]common.Hash, error)
// Get staking transactions history for an address
GetStakingTransactionsHistory(address, txType, order string) ([]common.Hash, error)
GetTransactionsCount(address, txType string) (uint64, error)
GetStakingTransactionsCount(address, txType string) (uint64, error)
// retrieve the blockHash using txID and add blockHash to CxPool for resending
ResendCx(ctx context.Context, txID common.Hash) (uint64, bool)
IsLeader() bool

@ -388,6 +388,12 @@ func (s *PublicBlockChainAPI) GetBalanceByBlockNumber(ctx context.Context, addre
return (*hexutil.Big)(balance), err
}
// GetAccountNonce returns the nonce value of the given address for the given block number
func (s *PublicBlockChainAPI) GetAccountNonce(ctx context.Context, address string, blockNr rpc.BlockNumber) (uint64, error) {
addr := internal_common.ParseAddr(address)
return s.b.GetAccountNonce(ctx, addr, rpc.BlockNumber(blockNr))
}
// GetBalance returns the amount of Nano for the given address in the state of the
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
// block numbers are also allowed.

@ -152,7 +152,9 @@ func (s *PublicTransactionPoolAPI) GetStakingTransactionByBlockHashAndIndex(ctx
return nil
}
// GetTransactionCount returns the number of transactions the given address has sent for the given block number
// GetTransactionCount returns the number of transactions the given address has sent for the given block number.
// Legacy for apiv1. For apiv2, please use getAccountNonce/getPoolNonce/getTransactionsCount/getStakingTransactionsCount apis for
// more granular transaction counts queries
func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr string, blockNr rpc.BlockNumber) (*hexutil.Uint64, error) {
address := internal_common.ParseAddr(addr)
// Ask transaction pool for the nonce which includes pending transactions
@ -172,6 +174,32 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr
return (*hexutil.Uint64)(&nonce), state.Error()
}
// GetTransactionsCount returns the number of regular transactions from genesis of input type ("SENT", "RECEIVED", "ALL")
func (s *PublicTransactionPoolAPI) GetTransactionsCount(ctx context.Context, address, txType string) (uint64, error) {
var err error
if !strings.HasPrefix(address, "one1") {
addr := internal_common.ParseAddr(address)
address, err = internal_common.AddressToBech32(addr)
if err != nil {
return 0, err
}
}
return s.b.GetTransactionsCount(address, txType)
}
// GetStakingTransactionsCount returns the number of staking transactions from genesis of input type ("SENT", "RECEIVED", "ALL")
func (s *PublicTransactionPoolAPI) GetStakingTransactionsCount(ctx context.Context, address, txType string) (uint64, error) {
var err error
if !strings.HasPrefix(address, "one1") {
addr := internal_common.ParseAddr(address)
address, err = internal_common.AddressToBech32(addr)
if err != nil {
return 0, err
}
}
return s.b.GetStakingTransactionsCount(address, txType)
}
// SendRawStakingTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce.
func (s *PublicTransactionPoolAPI) SendRawStakingTransaction(

@ -50,6 +50,7 @@ type Backend interface {
GetPoolTransactions() (types.PoolTransactions, error)
GetPoolTransaction(txHash common.Hash) types.PoolTransaction
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
GetAccountNonce(ctx context.Context, addr common.Address, blockNr rpc.BlockNumber) (uint64, error)
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
ChainConfig() *params.ChainConfig
CurrentBlock() *types.Block
@ -59,6 +60,8 @@ type Backend interface {
GetShardID() uint32
GetTransactionsHistory(address, txType, order string) ([]common.Hash, error)
GetStakingTransactionsHistory(address, txType, order string) ([]common.Hash, error)
GetTransactionsCount(address, txType string) (uint64, error)
GetStakingTransactionsCount(address, txType string) (uint64, error)
ResendCx(ctx context.Context, txID common.Hash) (uint64, bool)
IsLeader() bool
SendStakingTx(ctx context.Context, newStakingTx *staking.StakingTransaction) error

@ -352,6 +352,12 @@ func (s *PublicBlockChainAPI) GetBalanceByBlockNumber(ctx context.Context, addre
return s.b.GetBalance(ctx, addr, rpc.BlockNumber(blockNr))
}
// GetAccountNonce returns the nonce value of the given address for the given block number
func (s *PublicBlockChainAPI) GetAccountNonce(ctx context.Context, address string, blockNr rpc.BlockNumber) (uint64, error) {
addr := internal_common.ParseAddr(address)
return s.b.GetAccountNonce(ctx, addr, rpc.BlockNumber(blockNr))
}
// GetBalance returns the amount of Nano for the given address in the state of the
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
// block numbers are also allowed.

@ -200,28 +200,30 @@ func (s *PublicTransactionPoolAPI) GetStakingTransactionByHash(ctx context.Conte
return nil
}
// GetTransactionCount returns the number of transactions the given address has sent from genesis to the input block number
// NOTE: unlike other txn apis where staking vs. regular txns are separate,
// the transaction count here includes the count of both regular and staking txns
func (s *PublicTransactionPoolAPI) GetTransactionCount(
ctx context.Context, addr string, blockNr uint64,
) (uint64, error) {
address := internal_common.ParseAddr(addr)
// Ask transaction pool for the nonce which includes pending transactions
if rpc.BlockNumber(blockNr) == rpc.PendingBlockNumber {
nonce, err := s.b.GetPoolNonce(ctx, address)
// GetTransactionsCount returns the number of regular transactions from genesis of input type ("SENT", "RECEIVED", "ALL")
func (s *PublicTransactionPoolAPI) GetTransactionsCount(ctx context.Context, address, txType string) (uint64, error) {
var err error
if !strings.HasPrefix(address, "one1") {
addr := internal_common.ParseAddr(address)
address, err = internal_common.AddressToBech32(addr)
if err != nil {
return 0, err
}
return nonce, nil
}
// Resolve block number and use its state to ask for the nonce
state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.BlockNumber(blockNr))
if state == nil || err != nil {
return 0, err
return s.b.GetTransactionsCount(address, txType)
}
// GetStakingTransactionsCount returns the number of staking transactions from genesis of input type ("SENT", "RECEIVED", "ALL")
func (s *PublicTransactionPoolAPI) GetStakingTransactionsCount(ctx context.Context, address, txType string) (uint64, error) {
var err error
if !strings.HasPrefix(address, "one1") {
addr := internal_common.ParseAddr(address)
address, err = internal_common.AddressToBech32(addr)
if err != nil {
return 0, err
}
}
nonce := state.GetNonce(address)
return nonce, state.Error()
return s.b.GetStakingTransactionsCount(address, txType)
}
// SendRawStakingTransaction will add the signed transaction to the transaction pool.

@ -45,6 +45,7 @@ type Backend interface {
GetPoolTransactions() (types.PoolTransactions, error)
GetPoolTransaction(txHash common.Hash) types.PoolTransaction
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
GetAccountNonce(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (uint64, error)
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
ChainConfig() *params.ChainConfig
CurrentBlock() *types.Block
@ -53,6 +54,8 @@ type Backend interface {
GetShardID() uint32
GetTransactionsHistory(address, txType, order string) ([]common.Hash, error)
GetStakingTransactionsHistory(address, txType, order string) ([]common.Hash, error)
GetTransactionsCount(address, txType string) (uint64, error)
GetStakingTransactionsCount(address, txType string) (uint64, error)
ResendCx(ctx context.Context, txID common.Hash) (uint64, bool)
IsLeader() bool
SendStakingTx(ctx context.Context, newStakingTx *staking.StakingTransaction) error

@ -210,3 +210,49 @@ func (node *Node) GetStakingTransactionsHistory(address, txType, order string) (
}
return hashes, nil
}
// GetTransactionsCount returns the number of regular transactions hashes of address for input type.
func (node *Node) GetTransactionsCount(address, txType string) (uint64, error) {
addressData := &explorer.Address{}
key := explorer.GetAddressKey(address)
bytes, err := explorer.GetStorageInstance(node.SelfPeer.IP, node.SelfPeer.Port, false).GetDB().Get([]byte(key), nil)
if err != nil {
utils.Logger().Error().Err(err).Msg("[Explorer] Cannot get storage db instance")
return 0, nil
}
if err = rlp.DecodeBytes(bytes, &addressData); err != nil {
utils.Logger().Error().Err(err).Msg("[Explorer] Cannot convert address data from DB")
return 0, err
}
count := uint64(0)
for _, tx := range addressData.TXs {
if txType == "" || txType == "ALL" || txType == tx.Type {
count++
}
}
return count, nil
}
// GetStakingTransactionsCount returns the number of staking transactions hashes of address for input type.
func (node *Node) GetStakingTransactionsCount(address, txType string) (uint64, error) {
addressData := &explorer.Address{}
key := explorer.GetAddressKey(address)
bytes, err := explorer.GetStorageInstance(node.SelfPeer.IP, node.SelfPeer.Port, false).GetDB().Get([]byte(key), nil)
if err != nil {
utils.Logger().Error().Err(err).Msg("[Explorer] Cannot get storage db instance")
return 0, nil
}
if err = rlp.DecodeBytes(bytes, &addressData); err != nil {
utils.Logger().Error().Err(err).Msg("[Explorer] Cannot convert address data from DB")
return 0, err
}
count := uint64(0)
for _, tx := range addressData.StakingTXs {
if txType == "" || txType == "ALL" || txType == tx.Type {
count++
}
}
return count, nil
}

@ -165,7 +165,7 @@ if [ "$NETWORK" == "localnet" ]; then
POSTDATA[net_peerCount]="net_peerCount\",\"params\":[]"
POSTDATA[hmy_getBalance]="hmy_getBalance\",\"params\":[\"one18t4yj4fuutj83uwqckkvxp9gfa0568uc48ggj7\", \"latest\"]"
POSTDATA[hmy_getStorageAt]="hmy_getStorageAt\",\"params\":[\"0xD7Ff41CA29306122185A07d04293DdB35F24Cf2d\", \"0\", \"latest\"]"
POSTDATA[hmy_getTransactionCount]="hmy_getTransactionCount\",\"params\":[\"0x806171f95C5a74371a19e8a312c9e5Cb4E1D24f6\", \"latest\"]" # what is this
POSTDATA[hmy_getAccountNonce]="hmy_getAccountNonce\",\"params\":[\"0x806171f95C5a74371a19e8a312c9e5Cb4E1D24f6\", \"latest\"]"
POSTDATA[hmy_sendRawTransaction]="hmy_sendRawTransaction\",\"params\":[\"$SIGNED_RAW_TRANSACTION\"]"
POSTDATA[hmy_getLogs]="hmy_getLogs\", \"params\":[{\"BlockHash\": \"$TRANSACTION_BLOCK_HASH\"}]"
POSTDATA[hmy_getFilterChanges]="hmy_getFilterChanges\", \"params\":[\"0x58010795a282878ed0d61da72a14b8b0\"]"
@ -193,7 +193,7 @@ if [ "$NETWORK" == "betanet" ]; then
POSTDATA[net_peerCount]="net_peerCount\",\"params\":[]"
POSTDATA[hmy_getBalance]="hmy_getBalance\",\"params\":[\"one18t4yj4fuutj83uwqckkvxp9gfa0568uc48ggj7\", \"latest\"]"
POSTDATA[hmy_getStorageAt]="hmy_getStorageAt\",\"params\":[\"0xD7Ff41CA29306122185A07d04293DdB35F24Cf2d\", \"0\", \"latest\"]"
POSTDATA[hmy_getTransactionCount]="hmy_getTransactionCount\",\"params\":[\"0x806171f95C5a74371a19e8a312c9e5Cb4E1D24f6\", \"latest\"]" # what is this
POSTDATA[hmy_getAccountNonce]="hmy_getAccountNonce\",\"params\":[\"0x806171f95C5a74371a19e8a312c9e5Cb4E1D24f6\", \"latest\"]"
POSTDATA[hmy_sendRawTransaction]="hmy_sendRawTransaction\",\"params\":[\"$SIGNED_RAW_TRANSACTION\"]"
POSTDATA[hmy_getLogs]="hmy_getLogs\", \"params\":[{\"BlockHash\": \"$TRANSACTION_BLOCK_HASH\"}]"
POSTDATA[hmy_getFilterChanges]="hmy_getFilterChanges\", \"params\":[\"0x58010795a282878ed0d61da72a14b8b0\"]"
@ -228,7 +228,7 @@ RESPONSES[hmy_syncing]=""
RESPONSES[net_peerCount]=""
RESPONSES[hmy_getBalance]=""
RESPONSES[hmy_getStorageAt]=""
RESPONSES[hmy_getTransactionCount]=""
RESPONSES[hmy_getAccountNonce]=""
RESPONSES[hmy_sendRawTransaction]=""
RESPONSES[hmy_getLogs]=""
RESPONSES[hmy_getFilterChanges]=""
@ -545,10 +545,10 @@ function API_getStorageAt_test() {
echo
}
function API_getTransactionCount_test() {
function API_getAccountNonce_test() {
TESTS_RAN=$(( TESTS_RAN + 1 ))
echo "POST hmy_getTransactionCount test:"
response_test ${RESPONSES[hmy_getTransactionCount]}
echo "POST hmy_getAccountNonce test:"
response_test ${RESPONSES[hmy_getAccountNonce]}
[ "$?" == "1" ] && TESTS_PASSED=$(( TESTS_PASSED + 1 ))
echo
}
@ -670,7 +670,7 @@ function run_tests() {
API_netPeerCount_test
API_getBalance_test
API_getStorageAt_test
API_getTransactionCount_test
API_getAccountNonce_test
API_sendRawTransaction_test
API_getLogs_test
API_getFilterChanges_test

Loading…
Cancel
Save