Geth 1.13 (Deneb/Cancun) update #264
172
pkg/eth/api.go
172
pkg/eth/api.go
@ -19,19 +19,25 @@ package eth
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cerc-io/plugeth-statediff"
|
ipld_direct_state "github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
|
||||||
|
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/state"
|
||||||
|
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/trie"
|
||||||
|
statediff "github.com/cerc-io/plugeth-statediff"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
@ -39,9 +45,9 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
|
|
||||||
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
|
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
|
||||||
ipld_direct_state "github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -106,6 +112,25 @@ Headers and blocks
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// decodeHash parses a hex-encoded 32-byte hash. The input may optionally
|
||||||
|
// be prefixed by 0x and can have a byte length up to 32.
|
||||||
|
func decodeHash(s string) (h common.Hash, inputLength int, err error) {
|
||||||
|
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
|
||||||
|
s = s[2:]
|
||||||
|
}
|
||||||
|
if (len(s) & 1) > 0 {
|
||||||
|
s = "0" + s
|
||||||
|
}
|
||||||
|
b, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, 0, errors.New("hex string invalid")
|
||||||
|
}
|
||||||
|
if len(b) > 32 {
|
||||||
|
return common.Hash{}, len(b), errors.New("hex string too long, want at most 32 bytes")
|
||||||
|
}
|
||||||
|
return common.BytesToHash(b), len(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetHeaderByNumber returns the requested canonical block header.
|
// GetHeaderByNumber returns the requested canonical block header.
|
||||||
// * When blockNr is -1 the chain head is returned.
|
// * When blockNr is -1 the chain head is returned.
|
||||||
// * We cannot support pending block calls since we do not have an active miner
|
// * We cannot support pending block calls since we do not have an active miner
|
||||||
@ -222,8 +247,7 @@ Uncles
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true
|
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index.
|
||||||
// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
|
|
||||||
func (pea *PublicEthAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
|
func (pea *PublicEthAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
|
||||||
block, err := pea.B.BlockByNumber(ctx, blockNr)
|
block, err := pea.B.BlockByNumber(ctx, blockNr)
|
||||||
if block != nil && err == nil {
|
if block != nil && err == nil {
|
||||||
@ -379,7 +403,7 @@ func (pea *PublicEthAPI) GetBlockTransactionCountByHash(ctx context.Context, blo
|
|||||||
// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
|
// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
|
||||||
func (pea *PublicEthAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction {
|
func (pea *PublicEthAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction {
|
||||||
if block, _ := pea.B.BlockByNumber(ctx, blockNr); block != nil {
|
if block, _ := pea.B.BlockByNumber(ctx, blockNr); block != nil {
|
||||||
return newRPCTransactionFromBlockIndex(block, uint64(index))
|
return newRPCTransactionFromBlockIndex(block, uint64(index), pea.B.ChainConfig())
|
||||||
}
|
}
|
||||||
|
|
||||||
if pea.config.ProxyOnError {
|
if pea.config.ProxyOnError {
|
||||||
@ -396,7 +420,7 @@ func (pea *PublicEthAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context
|
|||||||
// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
|
// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
|
||||||
func (pea *PublicEthAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction {
|
func (pea *PublicEthAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction {
|
||||||
if block, _ := pea.B.BlockByHash(ctx, blockHash); block != nil {
|
if block, _ := pea.B.BlockByHash(ctx, blockHash); block != nil {
|
||||||
return newRPCTransactionFromBlockIndex(block, uint64(index))
|
return newRPCTransactionFromBlockIndex(block, uint64(index), pea.B.ChainConfig())
|
||||||
}
|
}
|
||||||
|
|
||||||
if pea.config.ProxyOnError {
|
if pea.config.ProxyOnError {
|
||||||
@ -443,14 +467,14 @@ func (pea *PublicEthAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Contex
|
|||||||
// GetTransactionByHash returns the transaction for the given hash
|
// GetTransactionByHash returns the transaction for the given hash
|
||||||
// eth ipld-eth-server cannot currently handle pending/tx_pool txs
|
// eth ipld-eth-server cannot currently handle pending/tx_pool txs
|
||||||
func (pea *PublicEthAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
|
func (pea *PublicEthAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
|
||||||
tx, blockHash, blockNumber, index, err := pea.B.GetTransaction(ctx, hash)
|
_, tx, blockHash, blockNumber, index, err := pea.B.GetTransaction(ctx, hash)
|
||||||
if tx != nil && err == nil {
|
if tx != nil && err == nil {
|
||||||
header, err := pea.B.HeaderByHash(ctx, blockHash)
|
header, err := pea.B.HeaderByHash(ctx, blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewRPCTransaction(tx, blockHash, blockNumber, index, header.BaseFee), nil
|
return NewRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, pea.B.ChainConfig()), nil
|
||||||
}
|
}
|
||||||
if pea.config.ProxyOnError {
|
if pea.config.ProxyOnError {
|
||||||
var tx *RPCTransaction
|
var tx *RPCTransaction
|
||||||
@ -465,7 +489,7 @@ func (pea *PublicEthAPI) GetTransactionByHash(ctx context.Context, hash common.H
|
|||||||
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
|
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
|
||||||
func (pea *PublicEthAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
|
func (pea *PublicEthAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
|
||||||
// Retrieve a finalized transaction, or a pooled otherwise
|
// Retrieve a finalized transaction, or a pooled otherwise
|
||||||
tx, _, _, _, err := pea.B.GetTransaction(ctx, hash)
|
_, tx, _, _, _, err := pea.B.GetTransaction(ctx, hash)
|
||||||
if tx != nil && err == nil {
|
if tx != nil && err == nil {
|
||||||
return tx.MarshalBinary()
|
return tx.MarshalBinary()
|
||||||
}
|
}
|
||||||
@ -580,7 +604,7 @@ func (pea *PublicEthAPI) GetTransactionReceipt(ctx context.Context, hash common.
|
|||||||
|
|
||||||
func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
|
func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
|
||||||
// TODO: this can be optimized for Postgres
|
// TODO: this can be optimized for Postgres
|
||||||
tx, blockHash, blockNumber, index, err := pea.B.GetTransaction(ctx, hash)
|
_, tx, blockHash, blockNumber, index, err := pea.B.GetTransaction(ctx, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -595,7 +619,11 @@ func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash co
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = receipts.DeriveFields(pea.B.Config.ChainConfig, blockHash, blockNumber, block.BaseFee(), block.Transactions())
|
var blobGasPrice *big.Int
|
||||||
|
if excessBlobGas := block.ExcessBlobGas(); excessBlobGas != nil {
|
||||||
|
blobGasPrice = eip4844.CalcBlobFee(*excessBlobGas)
|
||||||
|
}
|
||||||
|
err = receipts.DeriveFields(pea.B.Config.ChainConfig, blockHash, blockNumber, block.Time(), block.BaseFee(), blobGasPrice, block.Transactions())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -793,7 +821,7 @@ func (pea *PublicEthAPI) localGetBalance(ctx context.Context, address common.Add
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return (*hexutil.Big)(account.Balance), nil
|
return (*hexutil.Big)(account.Balance.ToBig()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStorageAt returns the storage from the state at the given address, key and
|
// GetStorageAt returns the storage from the state at the given address, key and
|
||||||
@ -822,7 +850,7 @@ func (pea *PublicEthAPI) GetStorageAt(ctx context.Context, address common.Addres
|
|||||||
return value[:], nil
|
return value[:], nil
|
||||||
}
|
}
|
||||||
if pea.config.ProxyOnError {
|
if pea.config.ProxyOnError {
|
||||||
log.Warnxf(ctx, "Missing eth_getStorageAt(%s, %s, %s)", address.Hash().String(), key, blockNrOrHash.String())
|
log.Warnxf(ctx, "Missing eth_getStorageAt(%s, %s, %s)", address, key, blockNrOrHash.String())
|
||||||
var res hexutil.Bytes
|
var res hexutil.Bytes
|
||||||
if err := pea.rpc.CallContext(ctx, &res, "eth_getStorageAt", address, key, blockNrOrHash); res != nil && err == nil {
|
if err := pea.rpc.CallContext(ctx, &res, "eth_getStorageAt", address, key, blockNrOrHash); res != nil && err == nil {
|
||||||
return res, nil
|
return res, nil
|
||||||
@ -868,57 +896,95 @@ func (pea *PublicEthAPI) GetProof(ctx context.Context, address common.Address, s
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// proofList implements ethdb.KeyValueWriter and collects the proofs as
|
||||||
|
// hex-strings for delivery to rpc-caller.
|
||||||
|
type proofList []string
|
||||||
|
|
||||||
|
func (n *proofList) Put(key []byte, value []byte) error {
|
||||||
|
*n = append(*n, hexutil.Encode(value))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *proofList) Delete(key []byte) error {
|
||||||
|
panic("not supported")
|
||||||
|
}
|
||||||
|
|
||||||
// this continues to use ipfs-ethdb based geth StateDB as it requires trie access
|
// this continues to use ipfs-ethdb based geth StateDB as it requires trie access
|
||||||
func (pea *PublicEthAPI) localGetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
|
func (pea *PublicEthAPI) localGetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
|
||||||
state, _, err := pea.B.IPLDTrieStateDBAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
var (
|
||||||
if state == nil || err != nil {
|
keys = make([]common.Hash, len(storageKeys))
|
||||||
|
keyLengths = make([]int, len(storageKeys))
|
||||||
|
storageProof = make([]StorageResult, len(storageKeys))
|
||||||
|
)
|
||||||
|
// Deserialize all keys. This prevents state access on invalid input.
|
||||||
|
for i, hexKey := range storageKeys {
|
||||||
|
var err error
|
||||||
|
keys[i], keyLengths[i], err = decodeHash(hexKey)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
storageTrie, err := state.StorageTrie(address)
|
statedb, header, err := pea.B.IPLDTrieStateDBAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
if storageTrie == nil || err != nil {
|
// statedb, header, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
|
if statedb == nil || err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
storageHash := types.EmptyRootHash
|
codeHash := statedb.GetCodeHash(address)
|
||||||
codeHash := state.GetCodeHash(address)
|
storageRoot := statedb.GetStorageRoot(address)
|
||||||
storageProof := make([]StorageResult, len(storageKeys))
|
|
||||||
|
|
||||||
// if we have a storageTrie, (which means the account exists), we can update the storagehash
|
if len(keys) > 0 {
|
||||||
if storageTrie != nil {
|
var storageTrie state.Trie
|
||||||
storageHash = storageTrie.Hash()
|
if storageRoot != types.EmptyRootHash && storageRoot != (common.Hash{}) {
|
||||||
|
id := trie.StorageTrieID(header.Root, crypto.Keccak256Hash(address.Bytes()), storageRoot)
|
||||||
|
st, err := trie.NewStateTrie(id, statedb.Database().TrieDB())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
storageTrie = st
|
||||||
|
}
|
||||||
|
// Create the proofs for the storageKeys.
|
||||||
|
for i, key := range keys {
|
||||||
|
// Output key encoding is a bit special: if the input was a 32-byte hash, it is
|
||||||
|
// returned as such. Otherwise, we apply the QUANTITY encoding mandated by the
|
||||||
|
// JSON-RPC spec for getProof. This behavior exists to preserve backwards
|
||||||
|
// compatibility with older client versions.
|
||||||
|
var outputKey string
|
||||||
|
if keyLengths[i] != 32 {
|
||||||
|
outputKey = hexutil.EncodeBig(key.Big())
|
||||||
} else {
|
} else {
|
||||||
// no storageTrie means the account does not exist, so the codeHash is the hash of an empty bytearray.
|
outputKey = hexutil.Encode(key[:])
|
||||||
codeHash = crypto.Keccak256Hash(nil)
|
|
||||||
}
|
}
|
||||||
|
if storageTrie == nil {
|
||||||
// create the proof for the storageKeys
|
storageProof[i] = StorageResult{outputKey, &hexutil.Big{}, []string{}}
|
||||||
for i, key := range storageKeys {
|
continue
|
||||||
if storageTrie != nil {
|
|
||||||
proof, storageError := state.GetStorageProof(address, common.HexToHash(key))
|
|
||||||
if storageError != nil {
|
|
||||||
return nil, storageError
|
|
||||||
}
|
}
|
||||||
storageProof[i] = StorageResult{key, (*hexutil.Big)(state.GetState(address, common.HexToHash(key)).Big()), toHexSlice(proof)}
|
var proof proofList
|
||||||
} else {
|
if err := storageTrie.Prove(crypto.Keccak256(key.Bytes()), &proof); err != nil {
|
||||||
storageProof[i] = StorageResult{key, &hexutil.Big{}, []string{}}
|
return nil, err
|
||||||
|
}
|
||||||
|
value := (*hexutil.Big)(statedb.GetState(address, key).Big())
|
||||||
|
storageProof[i] = StorageResult{outputKey, value, proof}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Create the accountProof.
|
||||||
// create the accountProof
|
tr, err := trie.NewStateTrie(trie.StateTrieID(header.Root), statedb.Database().TrieDB())
|
||||||
accountProof, proofErr := state.GetProof(address)
|
if err != nil {
|
||||||
if proofErr != nil {
|
return nil, err
|
||||||
return nil, proofErr
|
|
||||||
}
|
}
|
||||||
|
var accountProof proofList
|
||||||
|
if err := tr.Prove(crypto.Keccak256(address.Bytes()), &accountProof); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
balance := statedb.GetBalance(address).ToBig()
|
||||||
return &AccountResult{
|
return &AccountResult{
|
||||||
Address: address,
|
Address: address,
|
||||||
AccountProof: toHexSlice(accountProof),
|
AccountProof: accountProof,
|
||||||
Balance: (*hexutil.Big)(state.GetBalance(address)),
|
Balance: (*hexutil.Big)(balance),
|
||||||
CodeHash: codeHash,
|
CodeHash: codeHash,
|
||||||
Nonce: hexutil.Uint64(state.GetNonce(address)),
|
Nonce: hexutil.Uint64(statedb.GetNonce(address)),
|
||||||
StorageHash: storageHash,
|
StorageHash: storageRoot,
|
||||||
StorageProof: storageProof,
|
StorageProof: storageProof,
|
||||||
}, state.Error()
|
}, statedb.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSlice returns a slice of state or storage nodes from a provided root to a provided path and past it to a certain depth
|
// GetSlice returns a slice of state or storage nodes from a provided root to a provided path and past it to a certain depth
|
||||||
@ -989,7 +1055,7 @@ func (diff *StateOverride) Apply(state *ipld_direct_state.StateDB) error {
|
|||||||
}
|
}
|
||||||
// Override account balance.
|
// Override account balance.
|
||||||
if account.Balance != nil {
|
if account.Balance != nil {
|
||||||
state.SetBalance(addr, (*big.Int)(*account.Balance))
|
state.SetBalance(addr, uint256.MustFromBig((*big.Int)(*account.Balance)))
|
||||||
}
|
}
|
||||||
if account.State != nil && account.StateDiff != nil {
|
if account.State != nil && account.StateDiff != nil {
|
||||||
return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex())
|
return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex())
|
||||||
@ -1175,11 +1241,7 @@ func (pea *PublicEthAPI) writeStateDiffFor(blockHash common.Hash) {
|
|||||||
|
|
||||||
// rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field
|
// rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field
|
||||||
func (pea *PublicEthAPI) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
func (pea *PublicEthAPI) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
||||||
fields, err := RPCMarshalBlock(b, inclTx, fullTx)
|
fields := RPCMarshalBlock(b, inclTx, fullTx, pea.B.ChainConfig())
|
||||||
if err != nil {
|
|
||||||
log.Errorf("error RPC marshalling block with hash %s: %s", b.Hash().String(), err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if inclTx {
|
if inclTx {
|
||||||
td, err := pea.B.GetTd(b.Hash())
|
td, err := pea.B.GetTd(b.Hash())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1188,12 +1250,12 @@ func (pea *PublicEthAPI) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx boo
|
|||||||
}
|
}
|
||||||
fields["totalDifficulty"] = (*hexutil.Big)(td)
|
fields["totalDifficulty"] = (*hexutil.Big)(td)
|
||||||
}
|
}
|
||||||
return fields, err
|
return fields, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// rpcMarshalBlockWithUncleHashes uses the generalized output filler, then adds the total difficulty field
|
// rpcMarshalBlockWithUncleHashes uses the generalized output filler, then adds the total difficulty field
|
||||||
func (pea *PublicEthAPI) rpcMarshalBlockWithUncleHashes(b *types.Block, uncleHashes []common.Hash, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
func (pea *PublicEthAPI) rpcMarshalBlockWithUncleHashes(b *types.Block, uncleHashes []common.Hash, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
||||||
fields, err := RPCMarshalBlockWithUncleHashes(b, uncleHashes, inclTx, fullTx)
|
fields, err := RPCMarshalBlockWithUncleHashes(b, uncleHashes, inclTx, fullTx, pea.B.ChainConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ package eth_api_test
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/cerc-io/plugeth-statediff/indexer/interfaces"
|
"github.com/cerc-io/plugeth-statediff/indexer/interfaces"
|
||||||
"github.com/cerc-io/plugeth-statediff/indexer/ipld"
|
"github.com/cerc-io/plugeth-statediff/indexer/ipld"
|
||||||
@ -44,8 +43,8 @@ import (
|
|||||||
var (
|
var (
|
||||||
randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f")
|
randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f")
|
||||||
randomHash = crypto.Keccak256Hash(randomAddr.Bytes())
|
randomHash = crypto.Keccak256Hash(randomAddr.Bytes())
|
||||||
number = rpc.BlockNumber(test_helpers.BlockNumber.Int64())
|
number = rpc.BlockNumber(test_helpers.BlockNumber1)
|
||||||
londonBlockNum = rpc.BlockNumber(test_helpers.LondonBlockNum.Int64())
|
londonBlockNum = rpc.BlockNumber(test_helpers.LondonBlockNum)
|
||||||
wrongNumber = number + 1
|
wrongNumber = number + 1
|
||||||
blockHash = test_helpers.MockBlock.Header().Hash()
|
blockHash = test_helpers.MockBlock.Header().Hash()
|
||||||
baseFee = test_helpers.MockLondonBlock.BaseFee()
|
baseFee = test_helpers.MockLondonBlock.BaseFee()
|
||||||
@ -293,9 +292,7 @@ var _ = Describe("API", func() {
|
|||||||
Describe("eth_blockNumber", func() {
|
Describe("eth_blockNumber", func() {
|
||||||
It("Retrieves the head block number", func() {
|
It("Retrieves the head block number", func() {
|
||||||
bn := api.BlockNumber()
|
bn := api.BlockNumber()
|
||||||
ubn := (uint64)(bn)
|
Expect(bn).To(Equal(hexutil.Uint64(test_helpers.LondonBlockNum)))
|
||||||
subn := strconv.FormatUint(ubn, 10)
|
|
||||||
Expect(subn).To(Equal(test_helpers.LondonBlockNum.String()))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1104,20 +1101,20 @@ var _ = Describe("API", func() {
|
|||||||
It("Retrieves the eth balance for the provided account address at the block with the provided number", func() {
|
It("Retrieves the eth balance for the provided account address at the block with the provided number", func() {
|
||||||
bal, err := api.GetBalance(ctx, test_helpers.AccountAddresss, rpc.BlockNumberOrHashWithNumber(number))
|
bal, err := api.GetBalance(ctx, test_helpers.AccountAddresss, rpc.BlockNumberOrHashWithNumber(number))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(test_helpers.AccountBalance)))
|
Expect(bal).To(Equal((*hexutil.Big)(test_helpers.AccountBalance.ToBig())))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddress, rpc.BlockNumberOrHashWithNumber(number))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddress, rpc.BlockNumberOrHashWithNumber(number))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal.ToInt().Cmp(common.Big0)).To(Equal(0))
|
||||||
})
|
})
|
||||||
It("Retrieves the eth balance for the provided account address at the block with the provided hash", func() {
|
It("Retrieves the eth balance for the provided account address at the block with the provided hash", func() {
|
||||||
bal, err := api.GetBalance(ctx, test_helpers.AccountAddresss, rpc.BlockNumberOrHashWithHash(blockHash, true))
|
bal, err := api.GetBalance(ctx, test_helpers.AccountAddresss, rpc.BlockNumberOrHashWithHash(blockHash, true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(test_helpers.AccountBalance)))
|
Expect(bal).To(Equal((*hexutil.Big)(test_helpers.AccountBalance.ToBig())))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddress, rpc.BlockNumberOrHashWithHash(blockHash, true))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddress, rpc.BlockNumberOrHashWithHash(blockHash, true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal.ToInt().Cmp(common.Big0)).To(Equal(0))
|
||||||
})
|
})
|
||||||
It("Retrieves the eth balance for the non-existing account address at the block with the provided hash", func() {
|
It("Retrieves the eth balance for the non-existing account address at the block with the provided hash", func() {
|
||||||
bal, err := api.GetBalance(ctx, randomAddr, rpc.BlockNumberOrHashWithHash(blockHash, true))
|
bal, err := api.GetBalance(ctx, randomAddr, rpc.BlockNumberOrHashWithHash(blockHash, true))
|
||||||
|
@ -25,6 +25,12 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
validator "github.com/cerc-io/eth-ipfs-state-validator/v5/pkg"
|
||||||
|
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v5/postgres/v0"
|
||||||
|
ipld_direct_state "github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
|
||||||
|
ipld_sql "github.com/cerc-io/ipld-eth-statedb/sql"
|
||||||
|
ipld_trie_state "github.com/cerc-io/ipld-eth-statedb/trie_by_cid/state"
|
||||||
|
ipld_trie "github.com/cerc-io/ipld-eth-statedb/trie_by_cid/trie"
|
||||||
"github.com/cerc-io/plugeth-statediff/indexer/ipld"
|
"github.com/cerc-io/plugeth-statediff/indexer/ipld"
|
||||||
"github.com/cerc-io/plugeth-statediff/utils"
|
"github.com/cerc-io/plugeth-statediff/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -42,15 +48,11 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
|
||||||
validator "github.com/cerc-io/eth-ipfs-state-validator/v5/pkg"
|
|
||||||
ipfsethdb "github.com/cerc-io/ipfs-ethdb/v5/postgres/v0"
|
|
||||||
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
|
"github.com/cerc-io/ipld-eth-server/v5/pkg/log"
|
||||||
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
|
"github.com/cerc-io/ipld-eth-server/v5/pkg/shared"
|
||||||
ipld_direct_state "github.com/cerc-io/ipld-eth-statedb/direct_by_leaf"
|
|
||||||
ipld_sql "github.com/cerc-io/ipld-eth-statedb/sql"
|
|
||||||
ipld_trie_state "github.com/cerc-io/ipld-eth-statedb/trie_by_cid/state"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -80,7 +82,7 @@ type Backend struct {
|
|||||||
// ethereum interfaces
|
// ethereum interfaces
|
||||||
EthDB ethdb.Database
|
EthDB ethdb.Database
|
||||||
// We use this state.Database for eth_call and any place we don't need trie access
|
// We use this state.Database for eth_call and any place we don't need trie access
|
||||||
IpldDirectStateDatabase ipld_direct_state.StateDatabase
|
IpldDirectStateDatabase ipld_direct_state.Database
|
||||||
// We use this where state must be accessed by trie
|
// We use this where state must be accessed by trie
|
||||||
IpldTrieStateDatabase ipld_trie_state.Database
|
IpldTrieStateDatabase ipld_trie_state.Database
|
||||||
|
|
||||||
@ -115,7 +117,7 @@ func NewEthBackend(db *sqlx.DB, c *Config) (*Backend, error) {
|
|||||||
DB: db,
|
DB: db,
|
||||||
Retriever: r,
|
Retriever: r,
|
||||||
EthDB: ethDB,
|
EthDB: ethDB,
|
||||||
IpldDirectStateDatabase: ipld_direct_state.NewStateDatabase(driver),
|
IpldDirectStateDatabase: ipld_direct_state.NewDatabase(driver),
|
||||||
IpldTrieStateDatabase: ipld_trie_state.NewDatabase(ethDB),
|
IpldTrieStateDatabase: ipld_trie_state.NewDatabase(ethDB),
|
||||||
Config: c,
|
Config: c,
|
||||||
}, nil
|
}, nil
|
||||||
@ -494,7 +496,7 @@ func (b *Backend) GetReceiptsByBlockHashAndNumber(tx *sqlx.Tx, hash common.Hash,
|
|||||||
|
|
||||||
// GetTransaction retrieves a tx by hash
|
// GetTransaction retrieves a tx by hash
|
||||||
// It also returns the blockhash, blocknumber, and tx index associated with the transaction
|
// It also returns the blockhash, blocknumber, and tx index associated with the transaction
|
||||||
func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
|
||||||
type txRes struct {
|
type txRes struct {
|
||||||
Data []byte `db:"data"`
|
Data []byte `db:"data"`
|
||||||
HeaderID string `db:"header_id"`
|
HeaderID string `db:"header_id"`
|
||||||
@ -503,22 +505,22 @@ func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (*type
|
|||||||
}
|
}
|
||||||
var res = make([]txRes, 0)
|
var res = make([]txRes, 0)
|
||||||
if err := b.DB.Select(&res, RetrieveRPCTransaction, txHash.String()); err != nil {
|
if err := b.DB.Select(&res, RetrieveRPCTransaction, txHash.String()); err != nil {
|
||||||
return nil, common.Hash{}, 0, 0, err
|
return false, nil, common.Hash{}, 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(res) == 0 {
|
if len(res) == 0 {
|
||||||
return nil, common.Hash{}, 0, 0, errTxHashNotFound
|
return false, nil, common.Hash{}, 0, 0, errTxHashNotFound
|
||||||
} else if len(res) > 1 {
|
} else if len(res) > 1 {
|
||||||
// a transaction can be part of a only one canonical block
|
// a transaction can be part of a only one canonical block
|
||||||
return nil, common.Hash{}, 0, 0, errTxHashInMultipleBlocks
|
return false, nil, common.Hash{}, 0, 0, errTxHashInMultipleBlocks
|
||||||
}
|
}
|
||||||
|
|
||||||
var transaction types.Transaction
|
var transaction types.Transaction
|
||||||
if err := transaction.UnmarshalBinary(res[0].Data); err != nil {
|
if err := transaction.UnmarshalBinary(res[0].Data); err != nil {
|
||||||
return nil, common.Hash{}, 0, 0, err
|
return false, nil, common.Hash{}, 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &transaction, common.HexToHash(res[0].HeaderID), res[0].BlockNumber, res[0].Index, nil
|
return true, &transaction, common.HexToHash(res[0].HeaderID), res[0].BlockNumber, res[0].Index, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReceipts retrieves receipts for provided block hash
|
// GetReceipts retrieves receipts for provided block hash
|
||||||
@ -778,7 +780,7 @@ func (b *Backend) GetAccountByHash(ctx context.Context, address common.Address,
|
|||||||
}
|
}
|
||||||
return &types.StateAccount{
|
return &types.StateAccount{
|
||||||
Nonce: acctRecord.Nonce,
|
Nonce: acctRecord.Nonce,
|
||||||
Balance: balance,
|
Balance: uint256.MustFromBig(balance),
|
||||||
Root: common.HexToHash(acctRecord.Root),
|
Root: common.HexToHash(acctRecord.Root),
|
||||||
CodeHash: acctRecord.CodeHash,
|
CodeHash: acctRecord.CodeHash,
|
||||||
}, nil
|
}, nil
|
||||||
@ -917,7 +919,10 @@ func (b *Backend) GetSlice(path string, depth int, root common.Hash, storage boo
|
|||||||
var t ipld_trie_state.Trie
|
var t ipld_trie_state.Trie
|
||||||
var err error
|
var err error
|
||||||
if storage {
|
if storage {
|
||||||
t, err = b.IpldTrieStateDatabase.OpenStorageTrie(common.Hash{}, common.Hash{}, root)
|
// Note 1: once Verkle tries are used, this will be the same as state trie
|
||||||
|
// Note 2: a dummy hash is passed as owner here, and is only used to signal to ipld-eth-statedb
|
||||||
|
// that a storage, not state trie is being accessed
|
||||||
|
t, err = b.IpldTrieStateDatabase.OpenStorageTrie(common.Hash{}, common.Hash{1}, root, nil)
|
||||||
} else {
|
} else {
|
||||||
t, err = b.IpldTrieStateDatabase.OpenTrie(root)
|
t, err = b.IpldTrieStateDatabase.OpenTrie(root)
|
||||||
}
|
}
|
||||||
@ -929,21 +934,24 @@ func (b *Backend) GetSlice(path string, depth int, root common.Hash, storage boo
|
|||||||
// Convert the head hex path to a decoded byte path
|
// Convert the head hex path to a decoded byte path
|
||||||
headPath := common.FromHex(path)
|
headPath := common.FromHex(path)
|
||||||
|
|
||||||
|
// Convert the Trie object to its concrete type for raw node access
|
||||||
|
stateTrie := t.(*ipld_trie.StateTrie)
|
||||||
|
|
||||||
// Get Stem nodes
|
// Get Stem nodes
|
||||||
err = b.getSliceStem(headPath, t, response, &metaData, storage)
|
err = b.getSliceStem(headPath, stateTrie, response, &metaData, storage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Head node
|
// Get Head node
|
||||||
err = b.getSliceHead(headPath, t, response, &metaData, storage)
|
err = b.getSliceHead(headPath, stateTrie, response, &metaData, storage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if depth > 0 {
|
if depth > 0 {
|
||||||
// Get Slice nodes
|
// Get Slice nodes
|
||||||
err = b.getSliceTrie(headPath, t, response, &metaData, depth, storage)
|
err = b.getSliceTrie(headPath, stateTrie, response, &metaData, depth, storage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -954,7 +962,7 @@ func (b *Backend) GetSlice(path string, depth int, root common.Hash, storage boo
|
|||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) getSliceStem(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
|
func (b *Backend) getSliceStem(headPath []byte, t *ipld_trie.StateTrie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
|
||||||
leavesFetchTime := int64(0)
|
leavesFetchTime := int64(0)
|
||||||
totalStemStartTime := makeTimestamp()
|
totalStemStartTime := makeTimestamp()
|
||||||
|
|
||||||
@ -963,7 +971,7 @@ func (b *Backend) getSliceStem(headPath []byte, t ipld_trie_state.Trie, response
|
|||||||
// nodePath := make([]byte, len(headPath[:i]))
|
// nodePath := make([]byte, len(headPath[:i]))
|
||||||
nodePath := headPath[:i]
|
nodePath := headPath[:i]
|
||||||
|
|
||||||
rawNode, _, err := t.TryGetNode(utils.HexToCompact(nodePath))
|
rawNode, _, err := t.GetNode(utils.HexToCompact(nodePath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1002,10 +1010,10 @@ func (b *Backend) getSliceStem(headPath []byte, t ipld_trie_state.Trie, response
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) getSliceHead(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
|
func (b *Backend) getSliceHead(headPath []byte, t *ipld_trie.StateTrie, response *GetSliceResponse, metaData *metaDataFields, storage bool) error {
|
||||||
totalHeadStartTime := makeTimestamp()
|
totalHeadStartTime := makeTimestamp()
|
||||||
|
|
||||||
rawNode, _, err := t.TryGetNode(utils.HexToCompact(headPath))
|
rawNode, _, err := t.GetNode(utils.HexToCompact(headPath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1043,7 +1051,10 @@ func (b *Backend) getSliceHead(headPath []byte, t ipld_trie_state.Trie, response
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) getSliceTrie(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, depth int, storage bool) error {
|
func (b *Backend) getSliceTrie(headPath []byte, t ipld_trie_state.Trie, response *GetSliceResponse, metaData *metaDataFields, depth int, storage bool) error {
|
||||||
it, timeTaken := getIteratorAtPath(t, headPath)
|
it, timeTaken, err := getIteratorAtPath(t, headPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
metaData.trieLoadingTime += timeTaken
|
metaData.trieLoadingTime += timeTaken
|
||||||
|
|
||||||
leavesFetchTime := int64(0)
|
leavesFetchTime := int64(0)
|
||||||
|
@ -28,9 +28,9 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
@ -41,10 +41,11 @@ import (
|
|||||||
var nullHashBytes = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000")
|
var nullHashBytes = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000")
|
||||||
var emptyCodeHash = crypto.Keccak256([]byte{})
|
var emptyCodeHash = crypto.Keccak256([]byte{})
|
||||||
|
|
||||||
|
// These marshalling functions are from internal/ethapi so we have to make our own versions here:
|
||||||
|
|
||||||
// RPCMarshalHeader converts the given header to the RPC output.
|
// RPCMarshalHeader converts the given header to the RPC output.
|
||||||
// This function is eth/internal so we have to make our own version here...
|
|
||||||
func RPCMarshalHeader(head *types.Header) map[string]interface{} {
|
func RPCMarshalHeader(head *types.Header) map[string]interface{} {
|
||||||
headerMap := map[string]interface{}{
|
result := map[string]interface{}{
|
||||||
"number": (*hexutil.Big)(head.Number),
|
"number": (*hexutil.Big)(head.Number),
|
||||||
"hash": head.Hash(),
|
"hash": head.Hash(),
|
||||||
"parentHash": head.ParentHash,
|
"parentHash": head.ParentHash,
|
||||||
@ -56,43 +57,50 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
|
|||||||
"miner": head.Coinbase,
|
"miner": head.Coinbase,
|
||||||
"difficulty": (*hexutil.Big)(head.Difficulty),
|
"difficulty": (*hexutil.Big)(head.Difficulty),
|
||||||
"extraData": hexutil.Bytes(head.Extra),
|
"extraData": hexutil.Bytes(head.Extra),
|
||||||
"size": hexutil.Uint64(head.Size()),
|
|
||||||
"gasLimit": hexutil.Uint64(head.GasLimit),
|
"gasLimit": hexutil.Uint64(head.GasLimit),
|
||||||
"gasUsed": hexutil.Uint64(head.GasUsed),
|
"gasUsed": hexutil.Uint64(head.GasUsed),
|
||||||
"timestamp": hexutil.Uint64(head.Time),
|
"timestamp": hexutil.Uint64(head.Time),
|
||||||
"transactionsRoot": head.TxHash,
|
"transactionsRoot": head.TxHash,
|
||||||
"receiptsRoot": head.ReceiptHash,
|
"receiptsRoot": head.ReceiptHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
if head.BaseFee != nil {
|
if head.BaseFee != nil {
|
||||||
headerMap["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee)
|
result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee)
|
||||||
}
|
}
|
||||||
return headerMap
|
if head.WithdrawalsHash != nil {
|
||||||
|
result["withdrawalsRoot"] = head.WithdrawalsHash
|
||||||
|
}
|
||||||
|
if head.BlobGasUsed != nil {
|
||||||
|
result["blobGasUsed"] = hexutil.Uint64(*head.BlobGasUsed)
|
||||||
|
}
|
||||||
|
if head.ExcessBlobGas != nil {
|
||||||
|
result["excessBlobGas"] = hexutil.Uint64(*head.ExcessBlobGas)
|
||||||
|
}
|
||||||
|
if head.ParentBeaconRoot != nil {
|
||||||
|
result["parentBeaconBlockRoot"] = head.ParentBeaconRoot
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
|
// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
|
||||||
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
|
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
|
||||||
// transaction hashes.
|
// transaction hashes.
|
||||||
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *params.ChainConfig) map[string]interface{} {
|
||||||
fields := RPCMarshalHeader(block.Header())
|
fields := RPCMarshalHeader(block.Header())
|
||||||
fields["size"] = hexutil.Uint64(block.Size())
|
fields["size"] = hexutil.Uint64(block.Size())
|
||||||
|
|
||||||
if inclTx {
|
if inclTx {
|
||||||
formatTx := func(tx *types.Transaction) (interface{}, error) {
|
formatTx := func(idx int, tx *types.Transaction) interface{} {
|
||||||
return tx.Hash(), nil
|
return tx.Hash()
|
||||||
}
|
}
|
||||||
if fullTx {
|
if fullTx {
|
||||||
formatTx = func(tx *types.Transaction) (interface{}, error) {
|
formatTx = func(idx int, tx *types.Transaction) interface{} {
|
||||||
return NewRPCTransactionFromBlockHash(block, tx.Hash()), nil
|
return newRPCTransactionFromBlockIndex(block, uint64(idx), config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
txs := block.Transactions()
|
txs := block.Transactions()
|
||||||
transactions := make([]interface{}, len(txs))
|
transactions := make([]interface{}, len(txs))
|
||||||
var err error
|
|
||||||
for i, tx := range txs {
|
for i, tx := range txs {
|
||||||
if transactions[i], err = formatTx(tx); err != nil {
|
transactions[i] = formatTx(i, tx)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fields["transactions"] = transactions
|
fields["transactions"] = transactions
|
||||||
}
|
}
|
||||||
@ -102,12 +110,14 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]i
|
|||||||
uncleHashes[i] = uncle.Hash()
|
uncleHashes[i] = uncle.Hash()
|
||||||
}
|
}
|
||||||
fields["uncles"] = uncleHashes
|
fields["uncles"] = uncleHashes
|
||||||
|
if block.Header().WithdrawalsHash != nil {
|
||||||
return fields, nil
|
fields["withdrawals"] = block.Withdrawals()
|
||||||
|
}
|
||||||
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCMarshalBlockWithUncleHashes marshals the block with the provided uncle hashes
|
// RPCMarshalBlockWithUncleHashes marshals the block with the provided uncle hashes
|
||||||
func RPCMarshalBlockWithUncleHashes(block *types.Block, uncleHashes []common.Hash, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
func RPCMarshalBlockWithUncleHashes(block *types.Block, uncleHashes []common.Hash, inclTx bool, fullTx bool, config *params.ChainConfig) (map[string]interface{}, error) {
|
||||||
fields := RPCMarshalHeader(block.Header())
|
fields := RPCMarshalHeader(block.Header())
|
||||||
fields["size"] = hexutil.Uint64(block.Size())
|
fields["size"] = hexutil.Uint64(block.Size())
|
||||||
|
|
||||||
@ -117,7 +127,7 @@ func RPCMarshalBlockWithUncleHashes(block *types.Block, uncleHashes []common.Has
|
|||||||
}
|
}
|
||||||
if fullTx {
|
if fullTx {
|
||||||
formatTx = func(tx *types.Transaction) (interface{}, error) {
|
formatTx = func(tx *types.Transaction) (interface{}, error) {
|
||||||
return NewRPCTransactionFromBlockHash(block, tx.Hash()), nil
|
return NewRPCTransactionFromBlockHash(block, tx.Hash(), config), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
txs := block.Transactions()
|
txs := block.Transactions()
|
||||||
@ -135,11 +145,11 @@ func RPCMarshalBlockWithUncleHashes(block *types.Block, uncleHashes []common.Has
|
|||||||
return fields, nil
|
return fields, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRPCTransactionFromBlockHash returns a transaction that will serialize to the RPC representation.
|
// newRPCTransactionFromBlockHash returns a transaction that will serialize to the RPC representation.
|
||||||
func NewRPCTransactionFromBlockHash(b *types.Block, hash common.Hash) *RPCTransaction {
|
func NewRPCTransactionFromBlockHash(b *types.Block, hash common.Hash, config *params.ChainConfig) *RPCTransaction {
|
||||||
for idx, tx := range b.Transactions() {
|
for idx, tx := range b.Transactions() {
|
||||||
if tx.Hash() == hash {
|
if tx.Hash() == hash {
|
||||||
return newRPCTransactionFromBlockIndex(b, uint64(idx))
|
return newRPCTransactionFromBlockIndex(b, uint64(idx), config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -158,11 +168,12 @@ func SignerForTx(tx *types.Transaction) types.Signer {
|
|||||||
|
|
||||||
// NewRPCTransaction returns a transaction that will serialize to the RPC
|
// NewRPCTransaction returns a transaction that will serialize to the RPC
|
||||||
// representation, with the given location metadata set (if available).
|
// representation, with the given location metadata set (if available).
|
||||||
func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64, baseFee *big.Int) *RPCTransaction {
|
func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, blockTime uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *RPCTransaction {
|
||||||
signer := SignerForTx(tx)
|
signer := types.MakeSigner(config, new(big.Int).SetUint64(blockNumber), blockTime)
|
||||||
from, _ := types.Sender(signer, tx)
|
from, _ := types.Sender(signer, tx)
|
||||||
v, r, s := tx.RawSignatureValues()
|
v, r, s := tx.RawSignatureValues()
|
||||||
result := &RPCTransaction{
|
result := &RPCTransaction{
|
||||||
|
Type: hexutil.Uint64(tx.Type()),
|
||||||
From: from,
|
From: from,
|
||||||
Gas: hexutil.Uint64(tx.Gas()),
|
Gas: hexutil.Uint64(tx.Gas()),
|
||||||
GasPrice: (*hexutil.Big)(tx.GasPrice()),
|
GasPrice: (*hexutil.Big)(tx.GasPrice()),
|
||||||
@ -171,7 +182,6 @@ func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
|
|||||||
Nonce: hexutil.Uint64(tx.Nonce()),
|
Nonce: hexutil.Uint64(tx.Nonce()),
|
||||||
To: tx.To(),
|
To: tx.To(),
|
||||||
Value: (*hexutil.Big)(tx.Value()),
|
Value: (*hexutil.Big)(tx.Value()),
|
||||||
Type: hexutil.Uint64(tx.Type()),
|
|
||||||
V: (*hexutil.Big)(v),
|
V: (*hexutil.Big)(v),
|
||||||
R: (*hexutil.Big)(r),
|
R: (*hexutil.Big)(r),
|
||||||
S: (*hexutil.Big)(s),
|
S: (*hexutil.Big)(s),
|
||||||
@ -181,34 +191,69 @@ func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
|
|||||||
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
|
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
|
||||||
result.TransactionIndex = (*hexutil.Uint64)(&index)
|
result.TransactionIndex = (*hexutil.Uint64)(&index)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch tx.Type() {
|
switch tx.Type() {
|
||||||
case types.LegacyTxType:
|
case types.LegacyTxType:
|
||||||
// if a legacy transaction has an EIP-155 chain id, include it explicitly
|
// if a legacy transaction has an EIP-155 chain id, include it explicitly
|
||||||
if id := tx.ChainId(); id.Sign() != 0 {
|
if id := tx.ChainId(); id.Sign() != 0 {
|
||||||
result.ChainID = (*hexutil.Big)(id)
|
result.ChainID = (*hexutil.Big)(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
case types.AccessListTxType:
|
case types.AccessListTxType:
|
||||||
al := tx.AccessList()
|
al := tx.AccessList()
|
||||||
|
yparity := hexutil.Uint64(v.Sign())
|
||||||
result.Accesses = &al
|
result.Accesses = &al
|
||||||
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
||||||
|
result.YParity = &yparity
|
||||||
|
|
||||||
case types.DynamicFeeTxType:
|
case types.DynamicFeeTxType:
|
||||||
al := tx.AccessList()
|
al := tx.AccessList()
|
||||||
|
yparity := hexutil.Uint64(v.Sign())
|
||||||
result.Accesses = &al
|
result.Accesses = &al
|
||||||
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
||||||
|
result.YParity = &yparity
|
||||||
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
|
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
|
||||||
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
|
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
|
||||||
// if the transaction has been mined, compute the effective gas price
|
// if the transaction has been mined, compute the effective gas price
|
||||||
if baseFee != nil && blockHash != (common.Hash{}) {
|
if baseFee != nil && blockHash != (common.Hash{}) {
|
||||||
// price = min(tip, gasFeeCap - baseFee) + baseFee
|
// price = min(gasTipCap + baseFee, gasFeeCap)
|
||||||
price := math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap())
|
result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee))
|
||||||
result.GasPrice = (*hexutil.Big)(price)
|
|
||||||
} else {
|
} else {
|
||||||
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
|
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case types.BlobTxType:
|
||||||
|
al := tx.AccessList()
|
||||||
|
yparity := hexutil.Uint64(v.Sign())
|
||||||
|
result.Accesses = &al
|
||||||
|
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
||||||
|
result.YParity = &yparity
|
||||||
|
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
|
||||||
|
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
|
||||||
|
// if the transaction has been mined, compute the effective gas price
|
||||||
|
if baseFee != nil && blockHash != (common.Hash{}) {
|
||||||
|
result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee))
|
||||||
|
} else {
|
||||||
|
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
|
||||||
|
}
|
||||||
|
result.MaxFeePerBlobGas = (*hexutil.Big)(tx.BlobGasFeeCap())
|
||||||
|
result.BlobVersionedHashes = tx.BlobHashes()
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// effectiveGasPrice computes the transaction gas fee, based on the given basefee value.
|
||||||
|
//
|
||||||
|
// price = min(gasTipCap + baseFee, gasFeeCap)
|
||||||
|
func effectiveGasPrice(tx *types.Transaction, baseFee *big.Int) *big.Int {
|
||||||
|
fee := tx.GasTipCap()
|
||||||
|
fee = fee.Add(fee, baseFee)
|
||||||
|
if tx.GasFeeCapIntCmp(fee) < 0 {
|
||||||
|
return tx.GasFeeCap()
|
||||||
|
}
|
||||||
|
return fee
|
||||||
|
}
|
||||||
|
|
||||||
type rpcBlock struct {
|
type rpcBlock struct {
|
||||||
Hash common.Hash `json:"hash"`
|
Hash common.Hash `json:"hash"`
|
||||||
Transactions []rpcTransaction `json:"transactions"`
|
Transactions []rpcTransaction `json:"transactions"`
|
||||||
@ -270,6 +315,15 @@ func getBlockAndUncleHashes(cli *rpc.Client, ctx context.Context, method string,
|
|||||||
return types.NewBlockWithHeader(head).WithBody(txs, nil), body.UncleHashes, nil
|
return types.NewBlockWithHeader(head).WithBody(txs, nil), body.UncleHashes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation.
|
||||||
|
func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, config *params.ChainConfig) *RPCTransaction {
|
||||||
|
txs := b.Transactions()
|
||||||
|
if index >= uint64(len(txs)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return NewRPCTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time(), index, b.BaseFee(), config)
|
||||||
|
}
|
||||||
|
|
||||||
// newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index.
|
// newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index.
|
||||||
func newRPCRawTransactionFromBlockIndex(b *types.Block, index uint64) hexutil.Bytes {
|
func newRPCRawTransactionFromBlockIndex(b *types.Block, index uint64) hexutil.Bytes {
|
||||||
txs := b.Transactions()
|
txs := b.Transactions()
|
||||||
@ -280,15 +334,6 @@ func newRPCRawTransactionFromBlockIndex(b *types.Block, index uint64) hexutil.By
|
|||||||
return blob
|
return blob
|
||||||
}
|
}
|
||||||
|
|
||||||
// newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation.
|
|
||||||
func newRPCTransactionFromBlockIndex(b *types.Block, index uint64) *RPCTransaction {
|
|
||||||
txs := b.Transactions()
|
|
||||||
if index >= uint64(len(txs)) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return NewRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index, b.BaseFee())
|
|
||||||
}
|
|
||||||
|
|
||||||
func toFilterArg(q ethereum.FilterQuery) (interface{}, error) {
|
func toFilterArg(q ethereum.FilterQuery) (interface{}, error) {
|
||||||
arg := map[string]interface{}{
|
arg := map[string]interface{}{
|
||||||
"address": q.Addresses,
|
"address": q.Addresses,
|
||||||
@ -317,21 +362,28 @@ func toBlockNumArg(number *big.Int) string {
|
|||||||
return hexutil.EncodeBig(number)
|
return hexutil.EncodeBig(number)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIteratorAtPath(t state.Trie, startKey []byte) (trie.NodeIterator, int64) {
|
func getIteratorAtPath(t state.Trie, startKey []byte) (trie.NodeIterator, int64, error) {
|
||||||
startTime := makeTimestamp()
|
startTime := makeTimestamp()
|
||||||
var it trie.NodeIterator
|
var it trie.NodeIterator
|
||||||
|
var err error
|
||||||
|
|
||||||
if len(startKey)%2 != 0 {
|
if len(startKey)%2 != 0 {
|
||||||
// Zero-pad for odd-length keys, required by HexToKeyBytes()
|
// Zero-pad for odd-length keys, required by HexToKeyBytes()
|
||||||
startKey = append(startKey, 0)
|
startKey = append(startKey, 0)
|
||||||
it = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
|
it, err = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
it = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
|
it, err = t.NodeIterator(nodeiter.HexToKeyBytes(startKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
// Step to the required node (not required if original startKey was odd-length)
|
// Step to the required node (not required if original startKey was odd-length)
|
||||||
it.Next(true)
|
it.Next(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return it, makeTimestamp() - startTime
|
return it, makeTimestamp() - startTime, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillSliceNodeData(
|
func fillSliceNodeData(
|
||||||
@ -351,7 +403,7 @@ func fillSliceNodeData(
|
|||||||
if node.NodeType == Leaf && !storage {
|
if node.NodeType == Leaf && !storage {
|
||||||
stateLeafKey, storageRoot, code, err := extractContractAccountInfo(sdb, node, nodeElements)
|
stateLeafKey, storageRoot, code, err := extractContractAccountInfo(sdb, node, nodeElements)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("GetSlice account lookup error: %s", err.Error())
|
return 0, fmt.Errorf("GetSlice account lookup error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(code) > 0 {
|
if len(code) > 0 {
|
||||||
@ -387,7 +439,7 @@ func extractContractAccountInfo(sdb state.Database, node StateNode, nodeElements
|
|||||||
|
|
||||||
// Extract codeHash and get code
|
// Extract codeHash and get code
|
||||||
codeHash := common.BytesToHash(account.CodeHash)
|
codeHash := common.BytesToHash(account.CodeHash)
|
||||||
codeBytes, err := sdb.ContractCode(codeHash)
|
codeBytes, err := sdb.ContractCode(common.Address{}, codeHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", nil, err
|
return "", "", nil, err
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
|
||||||
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/trie"
|
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/trie"
|
||||||
|
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/triedb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeType for explicitly setting type of node
|
// NodeType for explicitly setting type of node
|
||||||
@ -73,7 +74,7 @@ type StorageNode struct {
|
|||||||
LeafKey []byte `json:"leafKey"`
|
LeafKey []byte `json:"leafKey"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ResolveNode(path []byte, node []byte, trieDB *trie.Database) (StateNode, []interface{}, error) {
|
func ResolveNode(path []byte, node []byte, trieDB *triedb.Database) (StateNode, []interface{}, error) {
|
||||||
var nodeElements []interface{}
|
var nodeElements []interface{}
|
||||||
if err := rlp.DecodeBytes(node, &nodeElements); err != nil {
|
if err := rlp.DecodeBytes(node, &nodeElements); err != nil {
|
||||||
return StateNode{}, nil, err
|
return StateNode{}, nil, err
|
||||||
@ -93,7 +94,7 @@ func ResolveNode(path []byte, node []byte, trieDB *trie.Database) (StateNode, []
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ResolveNodeIt return the state diff node pointed by the iterator.
|
// ResolveNodeIt return the state diff node pointed by the iterator.
|
||||||
func ResolveNodeIt(it trie.NodeIterator, trieDB *trie.Database) (StateNode, []interface{}, error) {
|
func ResolveNodeIt(it trie.NodeIterator, trieDB *triedb.Database) (StateNode, []interface{}, error) {
|
||||||
node, err := it.NodeBlob(), it.Error()
|
node, err := it.NodeBlob(), it.Error()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return StateNode{}, nil, err
|
return StateNode{}, nil, err
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
package eth_state_test
|
package eth_state_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/onsi/gomega/format"
|
||||||
|
"github.com/onsi/gomega/types"
|
||||||
|
|
||||||
|
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CheckGetSliceResponse(sliceResponse eth.GetSliceResponse, expectedResponse eth.GetSliceResponse) {
|
func CheckGetSliceResponse(sliceResponse eth.GetSliceResponse, expectedResponse eth.GetSliceResponse) {
|
||||||
@ -11,3 +18,54 @@ func CheckGetSliceResponse(sliceResponse eth.GetSliceResponse, expectedResponse
|
|||||||
Expect(sliceResponse.Leaves).To(Equal(expectedResponse.Leaves))
|
Expect(sliceResponse.Leaves).To(Equal(expectedResponse.Leaves))
|
||||||
Expect(sliceResponse.MetaData.NodeStats).To(Equal(expectedResponse.MetaData.NodeStats))
|
Expect(sliceResponse.MetaData.NodeStats).To(Equal(expectedResponse.MetaData.NodeStats))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EqualBigInt compares a hexutil.Big for equality with a big.Int or hexutil.Big value.
|
||||||
|
// It is an error for both actual and expected to be nil. Use BeNil() instead.
|
||||||
|
func EqualBigInt(expected *big.Int) types.GomegaMatcher {
|
||||||
|
return &BigIntEqualMatcher{
|
||||||
|
Expected: expected,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EqualBigHex compares a hexutil.Big for equality with a big.Int or hexutil.Big value.
|
||||||
|
// It is an error for both actual and expected to be nil. Use BeNil() instead.
|
||||||
|
func EqualBigHex(expected *hexutil.Big) types.GomegaMatcher {
|
||||||
|
return &BigIntEqualMatcher{
|
||||||
|
Expected: expected.ToInt(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type BigIntEqualMatcher struct {
|
||||||
|
Expected *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (matcher *BigIntEqualMatcher) Match(actual interface{}) (success bool, err error) {
|
||||||
|
if actual == nil && matcher.Expected == nil {
|
||||||
|
return false, fmt.Errorf("Refusing to compare <nil> to <nil>.\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.")
|
||||||
|
}
|
||||||
|
|
||||||
|
var asInt *big.Int
|
||||||
|
switch casted := actual.(type) {
|
||||||
|
case *big.Int:
|
||||||
|
asInt = casted
|
||||||
|
case *hexutil.Big:
|
||||||
|
asInt = (*big.Int)(casted)
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf("BigIntEqualMatcher expects a hexutil.Big or big.Int. Got:\n%s", format.Object(actual, 1))
|
||||||
|
}
|
||||||
|
return matcher.Expected.Cmp(asInt) == 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (matcher *BigIntEqualMatcher) FailureMessage(actual interface{}) (message string) {
|
||||||
|
actualString, actualOK := actual.(string)
|
||||||
|
expectedString := matcher.Expected.String()
|
||||||
|
if actualOK {
|
||||||
|
return format.MessageWithDiff(actualString, "to equal", expectedString)
|
||||||
|
}
|
||||||
|
|
||||||
|
return format.Message(actual, "to equal", matcher.Expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (matcher *BigIntEqualMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||||
|
return format.Message(actual, "not to equal", matcher.Expected)
|
||||||
|
}
|
||||||
|
@ -47,7 +47,7 @@ var (
|
|||||||
parsedABI abi.ABI
|
parsedABI abi.ABI
|
||||||
randomAddress = common.HexToAddress("0x9F4203bd7a11aCB94882050E6f1C3ab14BBaD3D9")
|
randomAddress = common.HexToAddress("0x9F4203bd7a11aCB94882050E6f1C3ab14BBaD3D9")
|
||||||
randomHash = crypto.Keccak256Hash(randomAddress.Bytes())
|
randomHash = crypto.Keccak256Hash(randomAddress.Bytes())
|
||||||
number = rpc.BlockNumber(test_helpers.BlockNumber.Int64())
|
number = rpc.BlockNumber(test_helpers.BlockNumber1)
|
||||||
|
|
||||||
block1StateRoot = common.HexToHash("0xa1f614839ebdd58677df2c9d66a3e0acc9462acc49fad6006d0b6e5d2b98ed21")
|
block1StateRoot = common.HexToHash("0xa1f614839ebdd58677df2c9d66a3e0acc9462acc49fad6006d0b6e5d2b98ed21")
|
||||||
rootDataHashBlock1 = "a1f614839ebdd58677df2c9d66a3e0acc9462acc49fad6006d0b6e5d2b98ed21"
|
rootDataHashBlock1 = "a1f614839ebdd58677df2c9d66a3e0acc9462acc49fad6006d0b6e5d2b98ed21"
|
||||||
@ -294,198 +294,198 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
It("Retrieves account balance by block number", func() {
|
It("Retrieves account balance by block number", func() {
|
||||||
bal, err := api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(0))
|
bal, err := api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(0))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock0))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock0))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(1))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(1))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(1))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(1))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(EqualBigInt((common.Big0)))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(1))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(1))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(EqualBigInt((common.Big0)))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(1))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(1))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock1))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(2))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(2))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock2))
|
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock2))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(2))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(EqualBigHex(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(2))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(2))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(3))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(3))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(3))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(3))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock3))
|
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock3))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(3))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(3))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(EqualBigHex(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(3))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(3))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(4))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(4))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(4))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(4))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(4))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(4))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(EqualBigHex(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(4))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(4))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(5))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(5))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock5))
|
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock5))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(5))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(5))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(5))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(5))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(EqualBigHex(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(5))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithNumber(5))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
|
||||||
})
|
})
|
||||||
It("Retrieves account balance by block hash", func() {
|
It("Retrieves account balance by block hash", func() {
|
||||||
bal, err := api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
bal, err := api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock0))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock0))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(EqualBigInt((common.Big0)))
|
||||||
|
|
||||||
_, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
_, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(EqualBigInt((common.Big0)))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[1].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock1))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock2))
|
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock2))
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(EqualBigHex(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[2].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock3))
|
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock3))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(EqualBigHex(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[3].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock1))
|
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock1))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(EqualBigHex(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[4].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct1BalanceBlock5))
|
Expect(bal).To(EqualBigHex(expectedAcct1BalanceBlock5))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedAcct2BalanceBlock4))
|
Expect(bal).To(EqualBigHex(expectedAcct2BalanceBlock4))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedContractBalance))
|
Expect(bal).To(EqualBigHex(expectedContractBalance))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.TestBankAddress, rpc.BlockNumberOrHashWithHash(blocks[5].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal(expectedBankBalanceBlock2))
|
Expect(bal).To(EqualBigHex(expectedBankBalanceBlock2))
|
||||||
})
|
})
|
||||||
It("Returns 0 if account balance not found by block number", func() {
|
It("Returns 0 if account balance not found by block number", func() {
|
||||||
bal, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(0))
|
bal, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithNumber(0))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(EqualBigInt(common.Big0))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(0))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithNumber(0))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(EqualBigInt(common.Big0))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(0))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithNumber(0))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(EqualBigInt(common.Big0))
|
||||||
})
|
})
|
||||||
It("Returns 0 if account balance not found by block hash", func() {
|
It("Returns 0 if account balance not found by block hash", func() {
|
||||||
bal, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
bal, err := api.GetBalance(ctx, test_helpers.Account1Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(EqualBigInt(common.Big0))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.Account2Addr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(EqualBigInt(common.Big0))
|
||||||
|
|
||||||
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
bal, err = api.GetBalance(ctx, test_helpers.ContractAddr, rpc.BlockNumberOrHashWithHash(blocks[0].Hash(), true))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(bal).To(Equal((*hexutil.Big)(common.Big0)))
|
Expect(bal).To(EqualBigInt(common.Big0))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
|
|
||||||
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
|
"github.com/cerc-io/ipld-eth-server/v5/pkg/eth"
|
||||||
@ -40,10 +41,11 @@ import (
|
|||||||
// Test variables
|
// Test variables
|
||||||
var (
|
var (
|
||||||
// block data
|
// block data
|
||||||
BlockNumber = big.NewInt(1)
|
BlockNumber1 = int64(1)
|
||||||
|
BlockTime1 = uint64(0)
|
||||||
MockHeader = types.Header{
|
MockHeader = types.Header{
|
||||||
Time: 0,
|
Time: 0,
|
||||||
Number: new(big.Int).Set(BlockNumber),
|
Number: big.NewInt(BlockNumber1),
|
||||||
Root: common.HexToHash("0x0"),
|
Root: common.HexToHash("0x0"),
|
||||||
TxHash: common.HexToHash("0x0"),
|
TxHash: common.HexToHash("0x0"),
|
||||||
ReceiptHash: common.HexToHash("0x0"),
|
ReceiptHash: common.HexToHash("0x0"),
|
||||||
@ -54,7 +56,7 @@ var (
|
|||||||
MockUncles = []*types.Header{
|
MockUncles = []*types.Header{
|
||||||
{
|
{
|
||||||
Time: 1,
|
Time: 1,
|
||||||
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
|
Number: big.NewInt(BlockNumber1 + 1),
|
||||||
Root: common.HexToHash("0x1"),
|
Root: common.HexToHash("0x1"),
|
||||||
TxHash: common.HexToHash("0x1"),
|
TxHash: common.HexToHash("0x1"),
|
||||||
ReceiptHash: common.HexToHash("0x1"),
|
ReceiptHash: common.HexToHash("0x1"),
|
||||||
@ -64,7 +66,7 @@ var (
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Time: 2,
|
Time: 2,
|
||||||
Number: new(big.Int).Add(BlockNumber, big.NewInt(2)),
|
Number: big.NewInt(BlockNumber1 + 2),
|
||||||
Root: common.HexToHash("0x2"),
|
Root: common.HexToHash("0x2"),
|
||||||
TxHash: common.HexToHash("0x2"),
|
TxHash: common.HexToHash("0x2"),
|
||||||
ReceiptHash: common.HexToHash("0x2"),
|
ReceiptHash: common.HexToHash("0x2"),
|
||||||
@ -76,7 +78,7 @@ var (
|
|||||||
MockBlock = createNewBlock(&MockHeader, MockTransactions, MockUncles, MockReceipts, trie.NewEmpty(nil))
|
MockBlock = createNewBlock(&MockHeader, MockTransactions, MockUncles, MockReceipts, trie.NewEmpty(nil))
|
||||||
MockChildHeader = types.Header{
|
MockChildHeader = types.Header{
|
||||||
Time: 0,
|
Time: 0,
|
||||||
Number: new(big.Int).Add(BlockNumber, common.Big1),
|
Number: big.NewInt(BlockNumber1 + 1),
|
||||||
Root: common.HexToHash("0x0"),
|
Root: common.HexToHash("0x0"),
|
||||||
TxHash: common.HexToHash("0x0"),
|
TxHash: common.HexToHash("0x0"),
|
||||||
ReceiptHash: common.HexToHash("0x0"),
|
ReceiptHash: common.HexToHash("0x0"),
|
||||||
@ -104,7 +106,7 @@ var (
|
|||||||
Address: Address,
|
Address: Address,
|
||||||
Topics: []common.Hash{mockTopic11, mockTopic12},
|
Topics: []common.Hash{mockTopic11, mockTopic12},
|
||||||
Data: []byte{},
|
Data: []byte{},
|
||||||
BlockNumber: BlockNumber.Uint64(),
|
BlockNumber: uint64(BlockNumber1),
|
||||||
TxIndex: 0,
|
TxIndex: 0,
|
||||||
Index: 0,
|
Index: 0,
|
||||||
}
|
}
|
||||||
@ -112,7 +114,7 @@ var (
|
|||||||
Address: AnotherAddress,
|
Address: AnotherAddress,
|
||||||
Topics: []common.Hash{mockTopic21, mockTopic22},
|
Topics: []common.Hash{mockTopic21, mockTopic22},
|
||||||
Data: []byte{},
|
Data: []byte{},
|
||||||
BlockNumber: BlockNumber.Uint64(),
|
BlockNumber: uint64(BlockNumber1),
|
||||||
TxIndex: 1,
|
TxIndex: 1,
|
||||||
Index: 1,
|
Index: 1,
|
||||||
}
|
}
|
||||||
@ -120,7 +122,7 @@ var (
|
|||||||
Address: AnotherAddress1,
|
Address: AnotherAddress1,
|
||||||
Topics: []common.Hash{mockTopic31},
|
Topics: []common.Hash{mockTopic31},
|
||||||
Data: []byte{},
|
Data: []byte{},
|
||||||
BlockNumber: BlockNumber.Uint64(),
|
BlockNumber: uint64(BlockNumber1),
|
||||||
TxIndex: 2,
|
TxIndex: 2,
|
||||||
Index: 2,
|
Index: 2,
|
||||||
}
|
}
|
||||||
@ -129,7 +131,7 @@ var (
|
|||||||
Address: AnotherAddress1,
|
Address: AnotherAddress1,
|
||||||
Topics: []common.Hash{mockTopic41, mockTopic42, mockTopic43},
|
Topics: []common.Hash{mockTopic41, mockTopic42, mockTopic43},
|
||||||
Data: []byte{},
|
Data: []byte{},
|
||||||
BlockNumber: BlockNumber.Uint64(),
|
BlockNumber: uint64(BlockNumber1),
|
||||||
TxIndex: 2,
|
TxIndex: 2,
|
||||||
Index: 3,
|
Index: 3,
|
||||||
}
|
}
|
||||||
@ -137,7 +139,7 @@ var (
|
|||||||
Address: AnotherAddress1,
|
Address: AnotherAddress1,
|
||||||
Topics: []common.Hash{mockTopic51},
|
Topics: []common.Hash{mockTopic51},
|
||||||
Data: []byte{},
|
Data: []byte{},
|
||||||
BlockNumber: BlockNumber.Uint64(),
|
BlockNumber: uint64(BlockNumber1),
|
||||||
TxIndex: 2,
|
TxIndex: 2,
|
||||||
Index: 4,
|
Index: 4,
|
||||||
}
|
}
|
||||||
@ -145,7 +147,7 @@ var (
|
|||||||
Address: AnotherAddress2,
|
Address: AnotherAddress2,
|
||||||
Topics: []common.Hash{mockTopic61},
|
Topics: []common.Hash{mockTopic61},
|
||||||
Data: []byte{},
|
Data: []byte{},
|
||||||
BlockNumber: BlockNumber.Uint64(),
|
BlockNumber: uint64(BlockNumber1),
|
||||||
TxIndex: 3,
|
TxIndex: 3,
|
||||||
Index: 5,
|
Index: 5,
|
||||||
}
|
}
|
||||||
@ -217,7 +219,7 @@ var (
|
|||||||
ContractLeafKey = crypto.Keccak256(ContractAddress[:])
|
ContractLeafKey = crypto.Keccak256(ContractAddress[:])
|
||||||
ContractAccount = types.StateAccount{
|
ContractAccount = types.StateAccount{
|
||||||
Nonce: uint64(1),
|
Nonce: uint64(1),
|
||||||
Balance: big.NewInt(0),
|
Balance: uint256.NewInt(0),
|
||||||
CodeHash: CodeHash.Bytes(),
|
CodeHash: CodeHash.Bytes(),
|
||||||
Root: common.HexToHash(ContractRoot),
|
Root: common.HexToHash(ContractRoot),
|
||||||
}
|
}
|
||||||
@ -229,7 +231,7 @@ var (
|
|||||||
})
|
})
|
||||||
|
|
||||||
nonce0 = uint64(0)
|
nonce0 = uint64(0)
|
||||||
AccountBalance = big.NewInt(1000)
|
AccountBalance = uint256.NewInt(1000)
|
||||||
AccountRoot = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
|
AccountRoot = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
|
||||||
AccountCodeHash = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
|
AccountCodeHash = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
|
||||||
AccountAddresss = common.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e")
|
AccountAddresss = common.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e")
|
||||||
@ -290,21 +292,22 @@ var (
|
|||||||
StateNodes: MockStateNodes,
|
StateNodes: MockStateNodes,
|
||||||
}
|
}
|
||||||
|
|
||||||
LondonBlockNum = new(big.Int).Add(BlockNumber, big.NewInt(2))
|
LondonBlockNum = (BlockNumber1 + 2)
|
||||||
|
LondonBlockTime = BlockTime1 + 1
|
||||||
MockLondonHeader = types.Header{
|
MockLondonHeader = types.Header{
|
||||||
Time: 0,
|
Time: 0,
|
||||||
Number: LondonBlockNum,
|
Number: big.NewInt(LondonBlockNum),
|
||||||
Root: common.HexToHash("0x00"),
|
Root: common.HexToHash("0x00"),
|
||||||
Difficulty: big.NewInt(5000000),
|
Difficulty: big.NewInt(5000000),
|
||||||
Extra: []byte{},
|
Extra: []byte{},
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
}
|
}
|
||||||
|
|
||||||
MockLondonTransactions, MockLondonReceipts, _ = createDynamicTransactionsAndReceipts(LondonBlockNum)
|
MockLondonTransactions, MockLondonReceipts, _ = createDynamicTransactionsAndReceipts(big.NewInt(LondonBlockNum), LondonBlockTime)
|
||||||
MockLondonUncles = []*types.Header{
|
MockLondonUncles = []*types.Header{
|
||||||
{
|
{
|
||||||
Time: 1,
|
Time: 1,
|
||||||
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
|
Number: big.NewInt(BlockNumber1 + 1),
|
||||||
ParentHash: common.HexToHash("0x2"),
|
ParentHash: common.HexToHash("0x2"),
|
||||||
Root: common.HexToHash("0x1"),
|
Root: common.HexToHash("0x1"),
|
||||||
TxHash: common.HexToHash("0x1"),
|
TxHash: common.HexToHash("0x1"),
|
||||||
@ -314,7 +317,7 @@ var (
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Time: 2,
|
Time: 2,
|
||||||
Number: new(big.Int).Add(BlockNumber, big.NewInt(1)),
|
Number: big.NewInt(BlockNumber1 + 1),
|
||||||
ParentHash: common.HexToHash("0x1"),
|
ParentHash: common.HexToHash("0x1"),
|
||||||
Root: common.HexToHash("0x2"),
|
Root: common.HexToHash("0x2"),
|
||||||
TxHash: common.HexToHash("0x2"),
|
TxHash: common.HexToHash("0x2"),
|
||||||
@ -338,7 +341,7 @@ func createNewBlock(header *types.Header, txs []*types.Transaction, uncles []*ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createDynamicTransactionsAndReceipts is a helper function to generate signed mock transactions and mock receipts with mock logs
|
// createDynamicTransactionsAndReceipts is a helper function to generate signed mock transactions and mock receipts with mock logs
|
||||||
func createDynamicTransactionsAndReceipts(blockNumber *big.Int) (types.Transactions, types.Receipts, common.Address) {
|
func createDynamicTransactionsAndReceipts(blockNumber *big.Int, blockTime uint64) (types.Transactions, types.Receipts, common.Address) {
|
||||||
// make transactions
|
// make transactions
|
||||||
config := *params.TestChainConfig
|
config := *params.TestChainConfig
|
||||||
config.LondonBlock = blockNumber
|
config.LondonBlock = blockNumber
|
||||||
@ -353,7 +356,7 @@ func createDynamicTransactionsAndReceipts(blockNumber *big.Int) (types.Transacti
|
|||||||
Data: []byte{},
|
Data: []byte{},
|
||||||
})
|
})
|
||||||
|
|
||||||
transactionSigner := types.MakeSigner(&config, blockNumber)
|
transactionSigner := types.MakeSigner(&config, blockNumber, blockTime)
|
||||||
mockCurve := elliptic.P256()
|
mockCurve := elliptic.P256()
|
||||||
mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader)
|
mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -391,7 +394,7 @@ func createLegacyTransactionsAndReceipts() (types.Transactions, types.Receipts,
|
|||||||
trx2 := types.NewTransaction(1, AnotherAddress, big.NewInt(2000), 100, big.NewInt(200), []byte{})
|
trx2 := types.NewTransaction(1, AnotherAddress, big.NewInt(2000), 100, big.NewInt(200), []byte{})
|
||||||
trx3 := types.NewContractCreation(2, big.NewInt(1500), 75, big.NewInt(150), ContractCode)
|
trx3 := types.NewContractCreation(2, big.NewInt(1500), 75, big.NewInt(150), ContractCode)
|
||||||
trx4 := types.NewTransaction(3, AnotherAddress1, big.NewInt(2000), 100, big.NewInt(200), []byte{})
|
trx4 := types.NewTransaction(3, AnotherAddress1, big.NewInt(2000), 100, big.NewInt(200), []byte{})
|
||||||
transactionSigner := types.MakeSigner(params.MainnetChainConfig, new(big.Int).Set(BlockNumber))
|
transactionSigner := types.MakeSigner(params.MainnetChainConfig, big.NewInt(BlockNumber1), 0)
|
||||||
mockCurve := elliptic.P256()
|
mockCurve := elliptic.P256()
|
||||||
mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader)
|
mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
|
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
|
||||||
|
// Note: copied from go-ethereum/internal/ethapi
|
||||||
type RPCTransaction struct {
|
type RPCTransaction struct {
|
||||||
BlockHash *common.Hash `json:"blockHash"`
|
BlockHash *common.Hash `json:"blockHash"`
|
||||||
BlockNumber *hexutil.Big `json:"blockNumber"`
|
BlockNumber *hexutil.Big `json:"blockNumber"`
|
||||||
@ -41,6 +42,7 @@ type RPCTransaction struct {
|
|||||||
GasPrice *hexutil.Big `json:"gasPrice"`
|
GasPrice *hexutil.Big `json:"gasPrice"`
|
||||||
GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"`
|
GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"`
|
||||||
GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"`
|
GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"`
|
||||||
|
MaxFeePerBlobGas *hexutil.Big `json:"maxFeePerBlobGas,omitempty"`
|
||||||
Hash common.Hash `json:"hash"`
|
Hash common.Hash `json:"hash"`
|
||||||
Input hexutil.Bytes `json:"input"`
|
Input hexutil.Bytes `json:"input"`
|
||||||
Nonce hexutil.Uint64 `json:"nonce"`
|
Nonce hexutil.Uint64 `json:"nonce"`
|
||||||
@ -50,9 +52,11 @@ type RPCTransaction struct {
|
|||||||
Type hexutil.Uint64 `json:"type"`
|
Type hexutil.Uint64 `json:"type"`
|
||||||
Accesses *types.AccessList `json:"accessList,omitempty"`
|
Accesses *types.AccessList `json:"accessList,omitempty"`
|
||||||
ChainID *hexutil.Big `json:"chainId,omitempty"`
|
ChainID *hexutil.Big `json:"chainId,omitempty"`
|
||||||
|
BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
|
||||||
V *hexutil.Big `json:"v"`
|
V *hexutil.Big `json:"v"`
|
||||||
R *hexutil.Big `json:"r"`
|
R *hexutil.Big `json:"r"`
|
||||||
S *hexutil.Big `json:"s"`
|
S *hexutil.Big `json:"s"`
|
||||||
|
YParity *hexutil.Uint64 `json:"yParity,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCReceipt represents a receipt that will serialize to the RPC representation of a receipt
|
// RPCReceipt represents a receipt that will serialize to the RPC representation of a receipt
|
||||||
|
@ -64,7 +64,7 @@ func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return hexutil.Big{}, err
|
return hexutil.Big{}, err
|
||||||
}
|
}
|
||||||
return hexutil.Big(*state.GetBalance(a.address)), nil
|
return hexutil.Big(*state.GetBalance(a.address).ToBig()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error) {
|
func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user