@@ -1114,7 +1114,21 @@ func (s *PublicBlockChainAPI) GetDiffAccounts(ctx context.Context, blockNr rpc.B
1114
1114
return nil , fmt .Errorf ("block not found for block number (%d): %v" , blockNr , err )
1115
1115
}
1116
1116
1117
- return s .b .Chain ().GetDiffAccounts (header .Hash ())
1117
+ accounts , err := s .b .Chain ().GetDiffAccounts (header .Hash ())
1118
+ if err == nil || ! errors .Is (err , core .ErrDiffLayerNotFound ) {
1119
+ return accounts , err
1120
+ }
1121
+
1122
+ // Replay the block when diff layer not found, it is very slow.
1123
+ block , err := s .b .BlockByNumber (ctx , blockNr )
1124
+ if err != nil {
1125
+ return nil , fmt .Errorf ("block not found for block number (%d): %v" , blockNr , err )
1126
+ }
1127
+ _ , statedb , err := s .replay (ctx , block , nil )
1128
+ if err != nil {
1129
+ return nil , err
1130
+ }
1131
+ return statedb .GetDirtyAccounts (), nil
1118
1132
}
1119
1133
1120
1134
func (s * PublicBlockChainAPI ) needToReplay (ctx context.Context , block * types.Block , accounts []common.Address ) (bool , error ) {
@@ -1177,36 +1191,20 @@ func (s *PublicBlockChainAPI) needToReplay(ctx context.Context, block *types.Blo
1177
1191
return false , nil
1178
1192
}
1179
1193
1180
- // GetDiffAccountsWithScope returns detailed changes of some interested accounts in a specific block number.
1181
- func (s * PublicBlockChainAPI ) GetDiffAccountsWithScope (ctx context.Context , blockNr rpc.BlockNumber , accounts []common.Address ) (* types.DiffAccountsInBlock , error ) {
1182
- if s .b .Chain () == nil {
1183
- return nil , fmt .Errorf ("blockchain not support get diff accounts" )
1184
- }
1185
-
1186
- block , err := s .b .BlockByNumber (ctx , blockNr )
1187
- if err != nil {
1188
- return nil , fmt .Errorf ("block not found for block number (%d): %v" , blockNr , err )
1189
- }
1190
-
1194
+ func (s * PublicBlockChainAPI ) replay (ctx context.Context , block * types.Block , accounts []common.Address ) (* types.DiffAccountsInBlock , * state.StateDB , error ) {
1191
1195
result := & types.DiffAccountsInBlock {
1192
- Number : uint64 ( blockNr ),
1196
+ Number : block . NumberU64 ( ),
1193
1197
BlockHash : block .Hash (),
1194
1198
Transactions : make ([]types.DiffAccountsInTx , 0 ),
1195
1199
}
1196
1200
1197
- if needReplay , err := s .needToReplay (ctx , block , accounts ); err != nil {
1198
- return nil , err
1199
- } else if ! needReplay {
1200
- return result , nil
1201
- }
1202
-
1203
1201
parent , err := s .b .BlockByHash (ctx , block .ParentHash ())
1204
1202
if err != nil {
1205
- return nil , fmt .Errorf ("block not found for block number (%d): %v" , blockNr - 1 , err )
1203
+ return nil , nil , fmt .Errorf ("block not found for block number (%d): %v" , block . NumberU64 () - 1 , err )
1206
1204
}
1207
1205
statedb , err := s .b .Chain ().StateAt (parent .Root ())
1208
1206
if err != nil {
1209
- return nil , fmt .Errorf ("state not found for block number (%d): %v" , blockNr - 1 , err )
1207
+ return nil , nil , fmt .Errorf ("state not found for block number (%d): %v" , block . NumberU64 () - 1 , err )
1210
1208
}
1211
1209
1212
1210
accountSet := make (map [common.Address ]struct {}, len (accounts ))
@@ -1256,7 +1254,7 @@ func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, bloc
1256
1254
}
1257
1255
1258
1256
if _ , err := core .ApplyMessage (vmenv , msg , new (core.GasPool ).AddGas (tx .Gas ())); err != nil {
1259
- return nil , fmt .Errorf ("transaction %#x failed: %v" , tx .Hash (), err )
1257
+ return nil , nil , fmt .Errorf ("transaction %#x failed: %v" , tx .Hash (), err )
1260
1258
}
1261
1259
statedb .Finalise (vmenv .ChainConfig ().IsEIP158 (block .Number ()))
1262
1260
@@ -1275,7 +1273,34 @@ func (s *PublicBlockChainAPI) GetDiffAccountsWithScope(ctx context.Context, bloc
1275
1273
}
1276
1274
}
1277
1275
1278
- return result , nil
1276
+ return result , statedb , nil
1277
+ }
1278
+
1279
+ // GetDiffAccountsWithScope returns detailed changes of some interested accounts in a specific block number.
1280
+ func (s * PublicBlockChainAPI ) GetDiffAccountsWithScope (ctx context.Context , blockNr rpc.BlockNumber , accounts []common.Address ) (* types.DiffAccountsInBlock , error ) {
1281
+ if s .b .Chain () == nil {
1282
+ return nil , fmt .Errorf ("blockchain not support get diff accounts" )
1283
+ }
1284
+
1285
+ block , err := s .b .BlockByNumber (ctx , blockNr )
1286
+ if err != nil {
1287
+ return nil , fmt .Errorf ("block not found for block number (%d): %v" , blockNr , err )
1288
+ }
1289
+
1290
+ needReplay , err := s .needToReplay (ctx , block , accounts )
1291
+ if err != nil {
1292
+ return nil , err
1293
+ }
1294
+ if ! needReplay {
1295
+ return & types.DiffAccountsInBlock {
1296
+ Number : uint64 (blockNr ),
1297
+ BlockHash : block .Hash (),
1298
+ Transactions : make ([]types.DiffAccountsInTx , 0 ),
1299
+ }, nil
1300
+ }
1301
+
1302
+ result , _ , err := s .replay (ctx , block , accounts )
1303
+ return result , err
1279
1304
}
1280
1305
1281
1306
// ExecutionResult groups all structured logs emitted by the EVM
0 commit comments