@@ -41,6 +41,7 @@ import (
41
41
"github.com/ethereum/go-ethereum/params"
42
42
"github.com/ethereum/go-ethereum/trie"
43
43
"github.com/holiman/uint256"
44
+ "golang.org/x/exp/slices"
44
45
)
45
46
46
47
var (
@@ -210,6 +211,34 @@ func validatePoolInternals(pool *LegacyPool) error {
210
211
return fmt .Errorf ("totalcost went negative: %v" , txs .totalcost )
211
212
}
212
213
}
214
+ // Ensure all auths in pool are tracked
215
+ for _ , tx := range pool .all .locals {
216
+ for _ , addr := range tx .SetCodeAuthorities () {
217
+ list := pool .all .auths [addr ]
218
+ if i := slices .Index (list , tx .Hash ()); i < 0 {
219
+ return fmt .Errorf ("authority not tracked: addr %s, local tx %s" , addr , tx .Hash ())
220
+ }
221
+ }
222
+ }
223
+ for _ , tx := range pool .all .remotes {
224
+ for _ , addr := range tx .SetCodeAuthorities () {
225
+ list := pool .all .auths [addr ]
226
+ if i := slices .Index (list , tx .Hash ()); i < 0 {
227
+ return fmt .Errorf ("authority not tracked: addr %s, remote tx %s" , addr , tx .Hash ())
228
+ }
229
+ }
230
+ }
231
+
232
+ // Ensure all auths in pool have an associated tx.
233
+ for addr , hashes := range pool .all .auths {
234
+ for _ , hash := range hashes {
235
+ _ , okLocal := pool .all .locals [hash ]
236
+ _ , okRemote := pool .all .remotes [hash ]
237
+ if ! okLocal && ! okRemote {
238
+ return fmt .Errorf ("dangling authority, missing originating tx: addr %s, hash %s" , addr , hash .Hex ())
239
+ }
240
+ }
241
+ }
213
242
return nil
214
243
}
215
244
@@ -2750,6 +2779,32 @@ func TestSetCodeTransactions(t *testing.T) {
2750
2779
}
2751
2780
},
2752
2781
},
2782
+ {
2783
+ name : "remove-hash-from-authority-tracker" ,
2784
+ pending : 10 ,
2785
+ run : func (name string ) {
2786
+ var keys []* ecdsa.PrivateKey
2787
+ for i := 0 ; i < 30 ; i ++ {
2788
+ key , _ := crypto .GenerateKey ()
2789
+ keys = append (keys , key )
2790
+ addr := crypto .PubkeyToAddress (key .PublicKey )
2791
+ testAddBalance (pool , addr , big .NewInt (params .Ether ))
2792
+ }
2793
+ // Create a transactions with 3 unique auths so the lookup's auth map is
2794
+ // filled with addresses.
2795
+ for i := 0 ; i < 30 ; i += 3 {
2796
+ if err := pool .addRemoteSync (pricedSetCodeTx (0 , 250000 , uint256 .NewInt (10 ), uint256 .NewInt (3 ), keys [i ], []unsignedAuth {{0 , keys [i ]}, {0 , keys [i + 1 ]}, {0 , keys [i + 2 ]}})); err != nil {
2797
+ t .Fatalf ("%s: failed to add with remote setcode transaction: %v" , name , err )
2798
+ }
2799
+ }
2800
+ // Replace one of the transactions with a normal transaction so that the
2801
+ // original hash is removed from the tracker. The hash should be
2802
+ // associated with 3 different authorities.
2803
+ if err := pool .addRemoteSync (pricedTransaction (0 , 100000 , big .NewInt (1000 ), keys [0 ])); err != nil {
2804
+ t .Fatalf ("%s: failed to replace with remote transaction: %v" , name , err )
2805
+ }
2806
+ },
2807
+ },
2753
2808
} {
2754
2809
tt .run (tt .name )
2755
2810
pending , queued := pool .Stats ()
0 commit comments