Skip to content

Commit 3e2ccf8

Browse files
authored
Fix GetAsOf() for commitment , so that it handles dereferencing (#17687)
Fixes #17488, and is a prerequisite for fixing: #17561 In `GetAsOf()` if a value is not found in history, `DomainRoTx.GetLatest()` is called. However, for commitment domain `AggregatorRoTx.GetLatest()` needs to be called instead, which handles foreign key dereferencing (account and storage offsets). --------- Co-authored-by: antonis19 <antonis19@users.noreply.github.com>
1 parent ac5c9e8 commit 3e2ccf8

3 files changed

Lines changed: 80 additions & 18 deletions

File tree

db/state/aggregator.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1802,7 +1802,11 @@ func (at *AggregatorRoTx) DebugRangeLatest(tx kv.Tx, domain kv.Domain, from, to
18021802
}
18031803

18041804
func (at *AggregatorRoTx) GetAsOf(name kv.Domain, k []byte, ts uint64, tx kv.Tx) (v []byte, ok bool, err error) {
1805-
return at.d[name].GetAsOf(k, ts, tx)
1805+
v, ok, err = at.d[name].GetAsOf(k, ts, tx)
1806+
if name == kv.CommitmentDomain && !ok {
1807+
v, _, ok, err = at.GetLatest(name, k, tx)
1808+
}
1809+
return v, ok, err
18061810
}
18071811

18081812
func (at *AggregatorRoTx) GetLatest(domain kv.Domain, k []byte, tx kv.Tx) (v []byte, step kv.Step, ok bool, err error) {

db/state/domain.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1458,7 +1458,6 @@ func (dt *DomainRoTx) GetAsOf(key []byte, txNum uint64, roTx kv.Tx) ([]byte, boo
14581458
// pointers to storage and account domains to do the reference. Aggregator tx must be called instead
14591459
return nil, false, nil
14601460
}
1461-
14621461
var ok bool
14631462
v, _, ok, err = dt.GetLatest(key, roTx)
14641463
if err != nil {

rpc/jsonrpc/eth_call_test.go

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@ import (
2020
"bytes"
2121
"context"
2222
"fmt"
23+
"io"
2324
"math/big"
25+
"math/rand"
2426
"testing"
2527
"time"
2628

29+
"crypto/ecdsa"
30+
2731
"github.com/holiman/uint256"
2832
"github.com/stretchr/testify/assert"
2933
"github.com/stretchr/testify/require"
@@ -135,51 +139,51 @@ func TestGetProof(t *testing.T) {
135139
{
136140
name: "currentBlockNoState",
137141
addr: contractAddr,
138-
blockNum: 4,
142+
blockNum: 6,
139143
},
140144
{
141145
name: "currentBlockEOA",
142146
addr: bankAddr,
143-
blockNum: 4,
147+
blockNum: 6,
144148
},
145149
{
146150
name: "currentBlockNoAccount",
147151
addr: common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddead0"),
148-
blockNum: 4,
152+
blockNum: 6,
149153
},
150154
{
151155
name: "currentBlockWithState",
152156
addr: contractAddr,
153-
blockNum: 4,
157+
blockNum: 6,
154158
storageKeys: []hexutil.Bytes{key(0), key(4), key(8), key(10)},
155159
stateVal: 2,
156160
},
157161
{
158162
name: "currentBlockWithStateAndShortKeys",
159163
addr: contractAddr,
160-
blockNum: 4,
164+
blockNum: 6,
161165
storageKeys: []hexutil.Bytes{{0x0}, {0x4}, {0x8}, {0x0a}},
162166
stateVal: 2,
163167
},
164168
{
165169
name: "currentBlockWithMissingState",
166170
addr: contractAddr,
167171
storageKeys: []hexutil.Bytes{hexutil.FromHex("0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead")},
168-
blockNum: 4,
172+
blockNum: 6,
169173
stateVal: 0,
170174
},
171175
{
172176
name: "currentBlockEOAMissingState",
173177
addr: bankAddr,
174178
storageKeys: []hexutil.Bytes{hexutil.FromHex("0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead")},
175-
blockNum: 4,
179+
blockNum: 6,
176180
stateVal: 0,
177181
},
178182
{
179183
name: "currentBlockNoAccountMissingState",
180184
addr: common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddead0"),
181185
storageKeys: []hexutil.Bytes{hexutil.FromHex("0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead")},
182-
blockNum: 4,
186+
blockNum: 6,
183187
stateVal: 0,
184188
},
185189
{
@@ -192,14 +196,18 @@ func TestGetProof(t *testing.T) {
192196
{
193197
name: "notCreatedYetAccount",
194198
addr: receiverAddress, // receiver address only starts existing at block 4
195-
blockNum: 2,
199+
blockNum: 3,
200+
},
201+
{
202+
name: "createdAccountAtBlock", // account created at block 4, proof requested at block 4, latest=6
203+
addr: receiverAddress, // receiver address only starts existing at block 4
204+
blockNum: 4,
205+
},
206+
{
207+
name: "createdAccountBlockAfter", // account created at block 4, proof requested at block 5, latest=6
208+
addr: receiverAddress, // receiver address only starts existing at block 4
209+
blockNum: 5,
196210
},
197-
// {
198-
// name: "tooOldBlock",
199-
// addr: contractAddr,
200-
// blockNum: 1,
201-
// expectedErr: "requested block is too old, block must be within 1 blocks of the head block number (currently 3)",
202-
// },
203211
}
204212

205213
for _, tt := range tests {
@@ -519,8 +527,29 @@ func contractInvocationData(val byte) []byte {
519527
return hexutil.MustDecode(fmt.Sprintf("0x%x00000000000000000000000000000000000000000000000000000000000000%02x", contractFuncSelector, val))
520528
}
521529

530+
func generatePseudoRandomECDSAKey(rand io.Reader) (*ecdsa.PrivateKey, error) {
531+
return ecdsa.GenerateKey(crypto.S256(), rand)
532+
}
533+
534+
func generatePseudoRandomECDSAKeyPairs(rand io.Reader, n int) ([]*ecdsa.PrivateKey, []*ecdsa.PublicKey, error) {
535+
privateKeys := make([]*ecdsa.PrivateKey, n)
536+
publicKeys := make([]*ecdsa.PublicKey, n)
537+
var err error
538+
for i := 0; i < n; i++ {
539+
privateKeys[i], err = generatePseudoRandomECDSAKey(rand)
540+
if err != nil {
541+
return nil, nil, err
542+
}
543+
publicKeys[i] = &privateKeys[i].PublicKey
544+
}
545+
return privateKeys, publicKeys, nil
546+
}
547+
522548
func chainWithDeployedContract(t *testing.T) (*mock.MockSentry, common.Address, common.Address, common.Address) {
523549
var (
550+
seed = int64(12345)
551+
rng = rand.New(rand.NewSource(seed)) // rng for filler accounts
552+
nFillerAccounts = 400 // nr. of accounts to fill up MPT
524553
signer = types.LatestSignerForChainID(nil)
525554
bankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
526555
bankAddress = crypto.PubkeyToAddress(bankKey.PublicKey)
@@ -534,12 +563,16 @@ func chainWithDeployedContract(t *testing.T) (*mock.MockSentry, common.Address,
534563
//Alloc: types.GenesisAlloc{bankAddress: {Balance: bankFunds, Storage: map[common.Hash]common.Hash{crypto.Keccak256Hash([]byte{0x1}): crypto.Keccak256Hash([]byte{0xf})}}}, // TODO (antonis19)
535564
}
536565
)
566+
// accounts to fill up MPT
567+
_, fillerPublicKeys, err := generatePseudoRandomECDSAKeyPairs(rng, nFillerAccounts)
568+
require.NoError(t, err)
569+
537570
m := mock.MockWithGenesis(t, gspec, bankKey, false)
538571
db := m.DB
539572

540573
var contractAddr common.Address
541574

542-
chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 4, func(i int, block *core.BlockGen) {
575+
chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 6, func(i int, block *core.BlockGen) {
543576
nonce := block.TxNonce(bankAddress)
544577
switch i {
545578
case 0:
@@ -551,15 +584,41 @@ func chainWithDeployedContract(t *testing.T) (*mock.MockSentry, common.Address,
551584
txn, err := types.SignTx(types.NewTransaction(nonce, contractAddr, new(uint256.Int), 900000, new(uint256.Int), contractInvocationData(1)), *signer, bankKey)
552585
require.NoError(t, err)
553586
block.AddTx(txn)
587+
// send txs to filler addresses, so that MPT may be populated ( populate only half in this block, to not exceed gas limit)
588+
nonce++
589+
for idx := 0; idx < nFillerAccounts/2; idx++ {
590+
transferAmount := big.NewInt(1e1)
591+
fillerAddress := crypto.PubkeyToAddress(*fillerPublicKeys[idx])
592+
txn, err := types.SignTx(types.NewTransaction(nonce, fillerAddress, uint256.MustFromBig(transferAmount), 21000, new(uint256.Int), nil), *signer, bankKey)
593+
require.NoError(t, err)
594+
block.AddTx(txn)
595+
nonce++
596+
}
554597
case 2:
555598
txn, err := types.SignTx(types.NewTransaction(nonce, contractAddr, new(uint256.Int), 900000, new(uint256.Int), contractInvocationData(2)), *signer, bankKey)
556599
require.NoError(t, err)
557600
block.AddTx(txn)
601+
// send txs to filler addresses, so that MPT may be populated
602+
// ( populate the second half in this block)
603+
nonce++
604+
for idx := nFillerAccounts / 2; idx < nFillerAccounts; idx++ {
605+
transferAmount := big.NewInt(1e1)
606+
fillerAddress := crypto.PubkeyToAddress(*fillerPublicKeys[idx])
607+
txn, err := types.SignTx(types.NewTransaction(nonce, fillerAddress, uint256.MustFromBig(transferAmount), 21000, new(uint256.Int), nil), *signer, bankKey)
608+
require.NoError(t, err)
609+
block.AddTx(txn)
610+
nonce++
611+
}
612+
558613
case 3:
559614
transferAmount := big.NewInt(1e2)
560615
txn, err := types.SignTx(types.NewTransaction(nonce, receiverAddress, uint256.MustFromBig(transferAmount), 21000, new(uint256.Int), nil), *signer, bankKey)
561616
require.NoError(t, err)
562617
block.AddTx(txn)
618+
case 4:
619+
// empty block
620+
case 5:
621+
// empty block
563622
}
564623
})
565624
if err != nil {

0 commit comments

Comments
 (0)