mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 19:50:36 +00:00
Add erigon_getBalanceChangesInBlock RPC endpoint (#4609)
* Add eth_getBalanceChangesInBlock RPC endpoint * Fix lints * added assertion for one test * moved balance change api from eth to erigon Co-authored-by: fatemebagherii <fa.bagheri.a@gmail.com>
This commit is contained in:
parent
e8f83db208
commit
b6440eea1e
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/ledgerwatch/erigon-lib/kv"
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
"github.com/ledgerwatch/erigon/common/hexutil"
|
||||
"github.com/ledgerwatch/erigon/core/types"
|
||||
"github.com/ledgerwatch/erigon/p2p"
|
||||
"github.com/ledgerwatch/erigon/rpc"
|
||||
@ -20,6 +21,7 @@ type ErigonAPI interface {
|
||||
GetHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
|
||||
GetHeaderByHash(_ context.Context, hash common.Hash) (*types.Header, error)
|
||||
GetBlockByTimestamp(ctx context.Context, timeStamp rpc.Timestamp, fullTx bool) (map[string]interface{}, error)
|
||||
GetBalanceChangesInBlock(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (map[common.Address]*hexutil.Big, error)
|
||||
|
||||
// Receipt related (see ./erigon_receipts.go)
|
||||
GetLogsByHash(ctx context.Context, hash common.Hash) ([][]*types.Log, error)
|
||||
|
@ -1,15 +1,21 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/ledgerwatch/erigon-lib/kv"
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
"github.com/ledgerwatch/erigon/common/changeset"
|
||||
"github.com/ledgerwatch/erigon/common/dbutils"
|
||||
"github.com/ledgerwatch/erigon/common/hexutil"
|
||||
"github.com/ledgerwatch/erigon/core/rawdb"
|
||||
"github.com/ledgerwatch/erigon/core/types"
|
||||
"github.com/ledgerwatch/erigon/core/types/accounts"
|
||||
"github.com/ledgerwatch/erigon/internal/ethapi"
|
||||
"github.com/ledgerwatch/erigon/rpc"
|
||||
"github.com/ledgerwatch/erigon/turbo/rpchelper"
|
||||
@ -168,3 +174,65 @@ func buildBlockResponse(db kv.Tx, blockNum uint64, fullTx bool) (map[string]inte
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (api *ErigonImpl) GetBalanceChangesInBlock(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (map[common.Address]*hexutil.Big, error) {
|
||||
tx, err := api.db.BeginRo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
blockNumber, _, _, err := rpchelper.GetBlockNumber(blockNrOrHash, tx, api.filters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := tx.Cursor(kv.AccountChangeSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
startkey := dbutils.EncodeBlockNumber(blockNumber)
|
||||
|
||||
decodeFn := changeset.Mapper[kv.AccountChangeSet].Decode
|
||||
|
||||
balancesMapping := make(map[common.Address]*hexutil.Big)
|
||||
|
||||
newReader, err := rpchelper.CreateStateReader(ctx, tx, blockNrOrHash, api.filters, api.stateCache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for dbKey, dbValue, _ := c.Seek(startkey); bytes.Equal(dbKey, startkey) && dbKey != nil; dbKey, dbValue, _ = c.Next() {
|
||||
_, addressBytes, v, err := decodeFn(dbKey, dbValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var oldAcc accounts.Account
|
||||
if err = oldAcc.DecodeForStorage(v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
oldBalance := oldAcc.Balance
|
||||
|
||||
address := common.BytesToAddress(addressBytes)
|
||||
|
||||
newAcc, err := newReader.ReadAccountData(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newBalance := uint256.NewInt(0)
|
||||
if newAcc != nil {
|
||||
newBalance = &newAcc.Balance
|
||||
}
|
||||
|
||||
if !oldBalance.Eq(newBalance) {
|
||||
newBalanceDesc := (*hexutil.Big)(newBalance.ToBig())
|
||||
balancesMapping[address] = newBalanceDesc
|
||||
}
|
||||
}
|
||||
|
||||
return balancesMapping, nil
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/ledgerwatch/erigon/common/hexutil"
|
||||
"github.com/ledgerwatch/erigon/core"
|
||||
"github.com/ledgerwatch/erigon/internal/ethapi"
|
||||
"github.com/ledgerwatch/erigon/rpc"
|
||||
@ -16,6 +18,29 @@ import (
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
)
|
||||
|
||||
func TestGetBalanceChangesInBlock(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
myBlockNum := rpc.BlockNumberOrHashWithNumber(0)
|
||||
|
||||
db := rpcdaemontest.CreateTestKV(t)
|
||||
stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
|
||||
api := NewErigonAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil)
|
||||
balances, err := api.GetBalanceChangesInBlock(context.Background(), myBlockNum)
|
||||
if err != nil {
|
||||
t.Errorf("calling GetBalanceChangesInBlock resulted in an error: %v", err)
|
||||
}
|
||||
expected := map[common.Address]*hexutil.Big{
|
||||
common.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e"): (*hexutil.Big)(uint256.NewInt(200000000000000000).ToBig()),
|
||||
common.HexToAddress("0x703c4b2bD70c169f5717101CaeE543299Fc946C7"): (*hexutil.Big)(uint256.NewInt(300000000000000000).ToBig()),
|
||||
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): (*hexutil.Big)(uint256.NewInt(9000000000000000000).ToBig()),
|
||||
}
|
||||
assert.Equal(len(expected), len(balances))
|
||||
for i := range balances {
|
||||
assert.Contains(expected, i, "%s is not expected to be present in the output.", i)
|
||||
assert.Equal(balances[i], expected[i], "the value for %s is expected to be %v, but got %v.", i, expected[i], balances[i])
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTransactionReceipt(t *testing.T) {
|
||||
db := rpcdaemontest.CreateTestKV(t)
|
||||
stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
|
||||
|
Loading…
Reference in New Issue
Block a user