@@ -18,25 +18,74 @@ package eth
18
18
19
19
import (
20
20
"bytes"
21
+ "crypto/ecdsa"
21
22
"fmt"
23
+ "math/big"
22
24
"reflect"
23
25
"slices"
24
26
"strings"
25
27
"testing"
28
+ "time"
26
29
27
30
"github.com/davecgh/go-spew/spew"
28
31
"github.com/ethereum/go-ethereum/common"
32
+ "github.com/ethereum/go-ethereum/consensus/ethash"
33
+ "github.com/ethereum/go-ethereum/core"
29
34
"github.com/ethereum/go-ethereum/core/rawdb"
30
35
"github.com/ethereum/go-ethereum/core/state"
31
36
"github.com/ethereum/go-ethereum/core/tracing"
32
37
"github.com/ethereum/go-ethereum/core/types"
38
+ "github.com/ethereum/go-ethereum/core/vm"
33
39
"github.com/ethereum/go-ethereum/crypto"
40
+ "github.com/ethereum/go-ethereum/params"
34
41
"github.com/ethereum/go-ethereum/triedb"
35
42
"github.com/holiman/uint256"
43
+ "github.com/stretchr/testify/assert"
36
44
)
37
45
38
46
var dumper = spew.ConfigState {Indent : " " }
39
47
48
+ type Account struct {
49
+ key * ecdsa.PrivateKey
50
+ addr common.Address
51
+ }
52
+
53
+ func newAccounts (n int ) (accounts []Account ) {
54
+ for i := 0 ; i < n ; i ++ {
55
+ key , _ := crypto .GenerateKey ()
56
+ addr := crypto .PubkeyToAddress (key .PublicKey )
57
+ accounts = append (accounts , Account {key : key , addr : addr })
58
+ }
59
+ slices .SortFunc (accounts , func (a , b Account ) int { return a .addr .Cmp (b .addr ) })
60
+ return accounts
61
+ }
62
+
63
+ // newTestBlockChain creates a new test blockchain. OBS: After test is done, teardown must be
64
+ // invoked in order to release associated resources.
65
+ func newTestBlockChain (t * testing.T , n int , gspec * core.Genesis , generator func (i int , b * core.BlockGen )) * core.BlockChain {
66
+ engine := ethash .NewFaker ()
67
+ // Generate blocks for testing
68
+ _ , blocks , _ := core .GenerateChainWithGenesis (gspec , engine , n , generator )
69
+
70
+ // Import the canonical chain
71
+ cacheConfig := & core.CacheConfig {
72
+ TrieCleanLimit : 256 ,
73
+ TrieDirtyLimit : 256 ,
74
+ TrieTimeLimit : 5 * time .Minute ,
75
+ SnapshotLimit : 0 ,
76
+ Preimages : true ,
77
+ TrieDirtyDisabled : true , // Archive mode
78
+ }
79
+ chain , err := core .NewBlockChain (rawdb .NewMemoryDatabase (), cacheConfig , gspec , nil , engine , vm.Config {}, nil )
80
+ if err != nil {
81
+ t .Fatalf ("failed to create tester chain: %v" , err )
82
+ }
83
+ if n , err := chain .InsertChain (blocks ); err != nil {
84
+ t .Fatalf ("block %d: failed to insert into chain: %v" , n , err )
85
+ }
86
+ return chain
87
+ }
88
+
40
89
func accountRangeTest (t * testing.T , trie * state.Trie , statedb * state.StateDB , start common.Hash , requestedNum int , expectedNum int ) state.Dump {
41
90
result := statedb .RawDump (& state.DumpConfig {
42
91
SkipCode : true ,
@@ -224,3 +273,66 @@ func TestStorageRangeAt(t *testing.T) {
224
273
}
225
274
}
226
275
}
276
+
277
+ func TestGetModifiedAccounts (t * testing.T ) {
278
+ t .Parallel ()
279
+
280
+ // Initialize test accounts
281
+ accounts := newAccounts (4 )
282
+ genesis := & core.Genesis {
283
+ Config : params .TestChainConfig ,
284
+ Alloc : types.GenesisAlloc {
285
+ accounts [0 ].addr : {Balance : big .NewInt (params .Ether )},
286
+ accounts [1 ].addr : {Balance : big .NewInt (params .Ether )},
287
+ accounts [2 ].addr : {Balance : big .NewInt (params .Ether )},
288
+ accounts [3 ].addr : {Balance : big .NewInt (params .Ether )},
289
+ },
290
+ }
291
+ genBlocks := 1
292
+ signer := types.HomesteadSigner {}
293
+ blockChain := newTestBlockChain (t , genBlocks , genesis , func (_ int , b * core.BlockGen ) {
294
+ // Transfer from account[0] to account[1]
295
+ // value: 1000 wei
296
+ // fee: 0 wei
297
+ for _ , account := range accounts [:3 ] {
298
+ tx , _ := types .SignTx (types .NewTx (& types.LegacyTx {
299
+ Nonce : 0 ,
300
+ To : & accounts [3 ].addr ,
301
+ Value : big .NewInt (1000 ),
302
+ Gas : params .TxGas ,
303
+ GasPrice : b .BaseFee (),
304
+ Data : nil }),
305
+ signer , account .key )
306
+ b .AddTx (tx )
307
+ }
308
+ })
309
+ defer blockChain .Stop ()
310
+
311
+ // Create a debug API instance.
312
+ api := NewDebugAPI (& Ethereum {blockchain : blockChain })
313
+
314
+ // Test GetModifiedAccountsByNumber
315
+ t .Run ("GetModifiedAccountsByNumber" , func (t * testing.T ) {
316
+ addrs , err := api .GetModifiedAccountsByNumber (uint64 (genBlocks ), nil )
317
+ assert .NoError (t , err )
318
+ assert .Len (t , addrs , len (accounts )+ 1 ) // +1 for the coinbase
319
+ for _ , account := range accounts {
320
+ if ! slices .Contains (addrs , account .addr ) {
321
+ t .Fatalf ("account %s not found in modified accounts" , account .addr .Hex ())
322
+ }
323
+ }
324
+ })
325
+
326
+ // Test GetModifiedAccountsByHash
327
+ t .Run ("GetModifiedAccountsByHash" , func (t * testing.T ) {
328
+ header := blockChain .GetHeaderByNumber (uint64 (genBlocks ))
329
+ addrs , err := api .GetModifiedAccountsByHash (header .Hash (), nil )
330
+ assert .NoError (t , err )
331
+ assert .Len (t , addrs , len (accounts )+ 1 ) // +1 for the coinbase
332
+ for _ , account := range accounts {
333
+ if ! slices .Contains (addrs , account .addr ) {
334
+ t .Fatalf ("account %s not found in modified accounts" , account .addr .Hex ())
335
+ }
336
+ }
337
+ })
338
+ }
0 commit comments