forked from cerc-io/plugeth
automated merge
This commit is contained in:
@@ -157,13 +157,12 @@ func (c *Compiler) compileLine() error {
|
||||
}
|
||||
|
||||
// compileNumber compiles the number to bytes
|
||||
func (c *Compiler) compileNumber(element token) (int, error) {
|
||||
func (c *Compiler) compileNumber(element token) {
|
||||
num := math.MustParseBig256(element.text).Bytes()
|
||||
if len(num) == 0 {
|
||||
num = []byte{0}
|
||||
}
|
||||
c.pushBin(num)
|
||||
return len(num), nil
|
||||
}
|
||||
|
||||
// compileElement compiles the element (push & label or both)
|
||||
|
||||
+3
-3
@@ -84,7 +84,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
|
||||
toaddr := common.Address{}
|
||||
data := make([]byte, nbytes)
|
||||
gas, _ := IntrinsicGas(data, nil, false, false, false, false)
|
||||
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)))
|
||||
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), gen.header.Time)
|
||||
gasPrice := big.NewInt(0)
|
||||
if gen.header.BaseFee != nil {
|
||||
gasPrice = gen.header.BaseFee
|
||||
@@ -128,7 +128,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
|
||||
if gen.header.BaseFee != nil {
|
||||
gasPrice = gen.header.BaseFee
|
||||
}
|
||||
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)))
|
||||
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), gen.header.Time)
|
||||
for {
|
||||
gas -= params.TxGas
|
||||
if gas < params.TxGas {
|
||||
@@ -317,7 +317,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||
if full {
|
||||
hash := header.Hash()
|
||||
rawdb.ReadBody(db, hash, n)
|
||||
rawdb.ReadReceipts(db, hash, n, chain.Config())
|
||||
rawdb.ReadReceipts(db, hash, n, header.Time, chain.Config())
|
||||
}
|
||||
}
|
||||
chain.Stop()
|
||||
|
||||
@@ -55,10 +55,10 @@ func TestHeaderVerification(t *testing.T) {
|
||||
|
||||
if valid {
|
||||
engine := ethash.NewFaker()
|
||||
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true})
|
||||
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]})
|
||||
} else {
|
||||
engine := ethash.NewFakeFailer(headers[i].Number.Uint64())
|
||||
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true})
|
||||
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]})
|
||||
}
|
||||
// Wait for the verification result
|
||||
select {
|
||||
@@ -164,7 +164,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
||||
|
||||
// Verify the blocks before the merging
|
||||
for i := 0; i < len(preBlocks); i++ {
|
||||
_, results := engine.VerifyHeaders(chain, []*types.Header{preHeaders[i]}, []bool{true})
|
||||
_, results := engine.VerifyHeaders(chain, []*types.Header{preHeaders[i]})
|
||||
// Wait for the verification result
|
||||
select {
|
||||
case result := <-results:
|
||||
@@ -189,7 +189,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
||||
|
||||
// Verify the blocks after the merging
|
||||
for i := 0; i < len(postBlocks); i++ {
|
||||
_, results := engine.VerifyHeaders(chain, []*types.Header{postHeaders[i]}, []bool{true})
|
||||
_, results := engine.VerifyHeaders(chain, []*types.Header{postHeaders[i]})
|
||||
// Wait for the verification result
|
||||
select {
|
||||
case result := <-results:
|
||||
@@ -209,19 +209,14 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
||||
}
|
||||
|
||||
// Verify the blocks with pre-merge blocks and post-merge blocks
|
||||
var (
|
||||
headers []*types.Header
|
||||
seals []bool
|
||||
)
|
||||
var headers []*types.Header
|
||||
for _, block := range preBlocks {
|
||||
headers = append(headers, block.Header())
|
||||
seals = append(seals, true)
|
||||
}
|
||||
for _, block := range postBlocks {
|
||||
headers = append(headers, block.Header())
|
||||
seals = append(seals, true)
|
||||
}
|
||||
_, results := engine.VerifyHeaders(chain, headers, seals)
|
||||
_, results := engine.VerifyHeaders(chain, headers)
|
||||
for i := 0; i < len(headers); i++ {
|
||||
select {
|
||||
case result := <-results:
|
||||
@@ -252,11 +247,8 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
|
||||
_, blocks, _ = GenerateChainWithGenesis(gspec, ethash.NewFaker(), 8, nil)
|
||||
)
|
||||
headers := make([]*types.Header, len(blocks))
|
||||
seals := make([]bool, len(blocks))
|
||||
|
||||
for i, block := range blocks {
|
||||
headers[i] = block.Header()
|
||||
seals[i] = true
|
||||
}
|
||||
// Set the number of threads to verify on
|
||||
old := runtime.GOMAXPROCS(threads)
|
||||
@@ -269,11 +261,11 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
|
||||
|
||||
if valid {
|
||||
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
|
||||
_, results = chain.engine.VerifyHeaders(chain, headers)
|
||||
chain.Stop()
|
||||
} else {
|
||||
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil, nil)
|
||||
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
|
||||
_, results = chain.engine.VerifyHeaders(chain, headers)
|
||||
chain.Stop()
|
||||
}
|
||||
// Wait for all the verification results
|
||||
@@ -322,11 +314,8 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
|
||||
_, blocks, _ = GenerateChainWithGenesis(gspec, ethash.NewFaker(), 1024, nil)
|
||||
)
|
||||
headers := make([]*types.Header, len(blocks))
|
||||
seals := make([]bool, len(blocks))
|
||||
|
||||
for i, block := range blocks {
|
||||
headers[i] = block.Header()
|
||||
seals[i] = true
|
||||
}
|
||||
// Set the number of threads to verify on
|
||||
old := runtime.GOMAXPROCS(threads)
|
||||
@@ -336,7 +325,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
|
||||
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil, nil)
|
||||
defer chain.Stop()
|
||||
|
||||
abort, results := chain.engine.VerifyHeaders(chain, headers, seals)
|
||||
abort, results := chain.engine.VerifyHeaders(chain, headers)
|
||||
close(abort)
|
||||
|
||||
// Deplete the results channel
|
||||
|
||||
+14
-22
@@ -365,7 +365,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||
// The first thing the node will do is reconstruct the verification data for
|
||||
// the head block (ethash cache or clique voting snapshot). Might as well do
|
||||
// it in advance.
|
||||
bc.engine.VerifyHeader(bc, bc.CurrentHeader(), true)
|
||||
bc.engine.VerifyHeader(bc, bc.CurrentHeader())
|
||||
|
||||
// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
|
||||
for hash := range BadHashes {
|
||||
@@ -982,8 +982,8 @@ func (bc *BlockChain) Stop() {
|
||||
}
|
||||
}
|
||||
// Flush the collected preimages to disk
|
||||
if err := bc.stateCache.TrieDB().CommitPreimages(); err != nil {
|
||||
log.Error("Failed to commit trie preimages", "err", err)
|
||||
if err := bc.stateCache.TrieDB().Close(); err != nil {
|
||||
log.Error("Failed to close trie db", "err", err)
|
||||
}
|
||||
// Ensure all live cached entries be saved into disk, so that we can skip
|
||||
// cache warmup when node restarts.
|
||||
@@ -1539,7 +1539,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||
return 0, errChainStopped
|
||||
}
|
||||
defer bc.chainmu.Unlock()
|
||||
return bc.insertChain(chain, true, true)
|
||||
return bc.insertChain(chain, true)
|
||||
}
|
||||
|
||||
// insertChain is the internal implementation of InsertChain, which assumes that
|
||||
@@ -1550,14 +1550,14 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||
// racey behaviour. If a sidechain import is in progress, and the historic state
|
||||
// is imported, but then new canon-head is added before the actual sidechain
|
||||
// completes, then the historic state could be pruned again
|
||||
func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) (int, error) {
|
||||
func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) {
|
||||
// If the chain is terminating, don't even bother starting up.
|
||||
if bc.insertStopped() {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
|
||||
SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain)
|
||||
SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()), chain)
|
||||
|
||||
var (
|
||||
stats = insertStats{startTime: mclock.Now()}
|
||||
@@ -1571,13 +1571,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
|
||||
}()
|
||||
// Start the parallel header verifier
|
||||
headers := make([]*types.Header, len(chain))
|
||||
seals := make([]bool, len(chain))
|
||||
|
||||
for i, block := range chain {
|
||||
headers[i] = block.Header()
|
||||
seals[i] = verifySeals
|
||||
}
|
||||
abort, results := bc.engine.VerifyHeaders(bc, headers, seals)
|
||||
abort, results := bc.engine.VerifyHeaders(bc, headers)
|
||||
defer close(abort)
|
||||
|
||||
// Peek the error for the first block to decide the directing import logic
|
||||
@@ -1998,7 +1995,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||
// memory here.
|
||||
if len(blocks) >= 2048 || memory > 64*1024*1024 {
|
||||
log.Info("Importing heavy sidechain segment", "blocks", len(blocks), "start", blocks[0].NumberU64(), "end", block.NumberU64())
|
||||
if _, err := bc.insertChain(blocks, false, true); err != nil {
|
||||
if _, err := bc.insertChain(blocks, true); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
blocks, memory = blocks[:0], 0
|
||||
@@ -2012,7 +2009,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||
}
|
||||
if len(blocks) > 0 {
|
||||
log.Info("Importing sidechain segment", "start", blocks[0].NumberU64(), "end", blocks[len(blocks)-1].NumberU64())
|
||||
return bc.insertChain(blocks, false, true)
|
||||
return bc.insertChain(blocks, true)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
@@ -2055,7 +2052,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
|
||||
} else {
|
||||
b = bc.GetBlock(hashes[i], numbers[i])
|
||||
}
|
||||
if _, err := bc.insertChain(types.Blocks{b}, false, false); err != nil {
|
||||
if _, err := bc.insertChain(types.Blocks{b}, false); err != nil {
|
||||
return b.ParentHash(), err
|
||||
}
|
||||
}
|
||||
@@ -2066,7 +2063,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
|
||||
// the processing of a block. These logs are later announced as deleted or reborn.
|
||||
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
||||
receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64())
|
||||
receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.BaseFee(), b.Transactions())
|
||||
receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), b.Transactions())
|
||||
|
||||
var logs []*types.Log
|
||||
for _, receipt := range receipts {
|
||||
@@ -2262,7 +2259,7 @@ func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block) error {
|
||||
}
|
||||
defer bc.chainmu.Unlock()
|
||||
|
||||
_, err := bc.insertChain(types.Blocks{block}, true, false)
|
||||
_, err := bc.insertChain(types.Blocks{block}, false)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2490,17 +2487,12 @@ Receipts: %v
|
||||
// InsertHeaderChain attempts to insert the given header chain in to the local
|
||||
// chain, possibly creating a reorg. If an error is returned, it will return the
|
||||
// index number of the failing header as well an error describing what went wrong.
|
||||
//
|
||||
// The verify parameter can be used to fine tune whether nonce verification
|
||||
// should be done or not. The reason behind the optional check is because some
|
||||
// of the header retrieval mechanisms already need to verify nonces, as well as
|
||||
// because nonces can be verified sparsely, not needing to check each.
|
||||
func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
|
||||
func (bc *BlockChain) InsertHeaderChain(chain []*types.Header) (int, error) {
|
||||
if len(chain) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
start := time.Now()
|
||||
if i, err := bc.hc.ValidateHeaderChain(chain, checkFreq); err != nil {
|
||||
if i, err := bc.hc.ValidateHeaderChain(chain); err != nil {
|
||||
return i, err
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,11 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
|
||||
if number == nil {
|
||||
return nil
|
||||
}
|
||||
receipts := rawdb.ReadReceipts(bc.db, hash, *number, bc.chainConfig)
|
||||
header := bc.GetHeader(hash, *number)
|
||||
if header == nil {
|
||||
return nil
|
||||
}
|
||||
receipts := rawdb.ReadReceipts(bc.db, hash, *number, header.Time, bc.chainConfig)
|
||||
if receipts == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -295,12 +299,6 @@ func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) {
|
||||
return bc.stateCache.TrieDB().Node(hash)
|
||||
}
|
||||
|
||||
// ContractCode retrieves a blob of data associated with a contract hash
|
||||
// either from ephemeral in-memory cache, or from persistent storage.
|
||||
func (bc *BlockChain) ContractCode(hash common.Hash) ([]byte, error) {
|
||||
return bc.stateCache.ContractCode(common.Hash{}, hash)
|
||||
}
|
||||
|
||||
// ContractCodeWithPrefix retrieves a blob of data associated with a contract
|
||||
// hash either from ephemeral in-memory cache, or from persistent storage.
|
||||
//
|
||||
|
||||
+29
-29
@@ -74,7 +74,7 @@ func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *G
|
||||
}
|
||||
// Header-only chain requested
|
||||
genDb, headers := makeHeaderChainWithGenesis(genesis, n, engine, canonicalSeed)
|
||||
_, err := blockchain.InsertHeaderChain(headers, 1)
|
||||
_, err := blockchain.InsertHeaderChain(headers)
|
||||
return genDb, genesis, blockchain, err
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara
|
||||
}
|
||||
} else {
|
||||
headerChainB = makeHeaderChain(blockchain2.chainConfig, blockchain2.CurrentHeader(), n, ethash.NewFaker(), genDb, forkSeed)
|
||||
if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil {
|
||||
if _, err := blockchain2.InsertHeaderChain(headerChainB); err != nil {
|
||||
t.Fatalf("failed to insert forking chain: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -148,7 +148,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara
|
||||
func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
|
||||
for _, block := range chain {
|
||||
// Try and process the block
|
||||
err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true)
|
||||
err := blockchain.engine.VerifyHeader(blockchain, block.Header())
|
||||
if err == nil {
|
||||
err = blockchain.validator.ValidateBody(block)
|
||||
}
|
||||
@@ -187,7 +187,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
|
||||
func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error {
|
||||
for _, header := range chain {
|
||||
// Try and validate the header
|
||||
if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil {
|
||||
if err := blockchain.engine.VerifyHeader(blockchain, header); err != nil {
|
||||
return err
|
||||
}
|
||||
// Manually insert the header into the database, but don't reorganise (allows subsequent testing)
|
||||
@@ -252,7 +252,7 @@ func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full b
|
||||
}
|
||||
} else {
|
||||
headerChainB := makeHeaderChain(blockchain2.chainConfig, blockchain2.CurrentHeader(), n, ethash.NewFaker(), genDb, forkSeed)
|
||||
if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil {
|
||||
if _, err := blockchain2.InsertHeaderChain(headerChainB); err != nil {
|
||||
t.Fatalf("failed to insert forking chain: %v", err)
|
||||
}
|
||||
if blockchain2.CurrentHeader().Number.Uint64() != headerChainB[len(headerChainB)-1].Number.Uint64() {
|
||||
@@ -549,10 +549,10 @@ func testReorg(t *testing.T, first, second []int64, td int64, full bool) {
|
||||
for i, block := range diffBlocks {
|
||||
diffHeaders[i] = block.Header()
|
||||
}
|
||||
if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil {
|
||||
if _, err := blockchain.InsertHeaderChain(easyHeaders); err != nil {
|
||||
t.Fatalf("failed to insert easy chain: %v", err)
|
||||
}
|
||||
if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil {
|
||||
if _, err := blockchain.InsertHeaderChain(diffHeaders); err != nil {
|
||||
t.Fatalf("failed to insert difficult chain: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -613,7 +613,7 @@ func testBadHashes(t *testing.T, full bool) {
|
||||
BadHashes[headers[2].Hash()] = true
|
||||
defer func() { delete(BadHashes, headers[2].Hash()) }()
|
||||
|
||||
_, err = blockchain.InsertHeaderChain(headers, 1)
|
||||
_, err = blockchain.InsertHeaderChain(headers)
|
||||
}
|
||||
if !errors.Is(err, ErrBannedHash) {
|
||||
t.Errorf("error mismatch: have: %v, want: %v", err, ErrBannedHash)
|
||||
@@ -645,7 +645,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
|
||||
BadHashes[blocks[3].Header().Hash()] = true
|
||||
defer func() { delete(BadHashes, blocks[3].Header().Hash()) }()
|
||||
} else {
|
||||
if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil {
|
||||
if _, err = blockchain.InsertHeaderChain(headers); err != nil {
|
||||
t.Errorf("failed to import headers: %v", err)
|
||||
}
|
||||
if blockchain.CurrentHeader().Hash() != headers[3].Hash() {
|
||||
@@ -711,7 +711,7 @@ func testInsertNonceError(t *testing.T, full bool) {
|
||||
|
||||
blockchain.engine = ethash.NewFakeFailer(failNum)
|
||||
blockchain.hc.engine = blockchain.engine
|
||||
failRes, err = blockchain.InsertHeaderChain(headers, 1)
|
||||
failRes, err = blockchain.InsertHeaderChain(headers)
|
||||
}
|
||||
// Check that the returned error indicates the failure
|
||||
if failRes != failAt {
|
||||
@@ -785,7 +785,7 @@ func TestFastVsFullChains(t *testing.T) {
|
||||
for i, block := range blocks {
|
||||
headers[i] = block.Header()
|
||||
}
|
||||
if n, err := fast.InsertHeaderChain(headers, 1); err != nil {
|
||||
if n, err := fast.InsertHeaderChain(headers); err != nil {
|
||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||
}
|
||||
if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil {
|
||||
@@ -800,7 +800,7 @@ func TestFastVsFullChains(t *testing.T) {
|
||||
ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||
defer ancient.Stop()
|
||||
|
||||
if n, err := ancient.InsertHeaderChain(headers, 1); err != nil {
|
||||
if n, err := ancient.InsertHeaderChain(headers); err != nil {
|
||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||
}
|
||||
if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(len(blocks)/2)); err != nil {
|
||||
@@ -809,7 +809,7 @@ func TestFastVsFullChains(t *testing.T) {
|
||||
|
||||
// Iterate over all chain data components, and cross reference
|
||||
for i := 0; i < len(blocks); i++ {
|
||||
num, hash := blocks[i].NumberU64(), blocks[i].Hash()
|
||||
num, hash, time := blocks[i].NumberU64(), blocks[i].Hash(), blocks[i].Time()
|
||||
|
||||
if ftd, atd := fast.GetTd(hash, num), archive.GetTd(hash, num); ftd.Cmp(atd) != 0 {
|
||||
t.Errorf("block #%d [%x]: td mismatch: fastdb %v, archivedb %v", num, hash, ftd, atd)
|
||||
@@ -832,9 +832,9 @@ func TestFastVsFullChains(t *testing.T) {
|
||||
}
|
||||
|
||||
// Check receipts.
|
||||
freceipts := rawdb.ReadReceipts(fastDb, hash, num, fast.Config())
|
||||
anreceipts := rawdb.ReadReceipts(ancientDb, hash, num, fast.Config())
|
||||
areceipts := rawdb.ReadReceipts(archiveDb, hash, num, fast.Config())
|
||||
freceipts := rawdb.ReadReceipts(fastDb, hash, num, time, fast.Config())
|
||||
anreceipts := rawdb.ReadReceipts(ancientDb, hash, num, time, fast.Config())
|
||||
areceipts := rawdb.ReadReceipts(archiveDb, hash, num, time, fast.Config())
|
||||
if types.DeriveSha(freceipts, trie.NewStackTrie(nil)) != types.DeriveSha(areceipts, trie.NewStackTrie(nil)) {
|
||||
t.Errorf("block #%d [%x]: receipts mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, freceipts, anreceipts, areceipts)
|
||||
}
|
||||
@@ -931,7 +931,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||
for i, block := range blocks {
|
||||
headers[i] = block.Header()
|
||||
}
|
||||
if n, err := fast.InsertHeaderChain(headers, 1); err != nil {
|
||||
if n, err := fast.InsertHeaderChain(headers); err != nil {
|
||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||
}
|
||||
if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil {
|
||||
@@ -947,7 +947,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||
ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||
defer ancient.Stop()
|
||||
|
||||
if n, err := ancient.InsertHeaderChain(headers, 1); err != nil {
|
||||
if n, err := ancient.InsertHeaderChain(headers); err != nil {
|
||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||
}
|
||||
if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil {
|
||||
@@ -964,7 +964,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||
lightDb := makeDb()
|
||||
defer lightDb.Close()
|
||||
light, _ := NewBlockChain(lightDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
|
||||
if n, err := light.InsertHeaderChain(headers); err != nil {
|
||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||
}
|
||||
defer light.Stop()
|
||||
@@ -1701,7 +1701,7 @@ func TestTrieForkGC(t *testing.T) {
|
||||
chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root())
|
||||
chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root())
|
||||
}
|
||||
if len(chain.stateCache.TrieDB().Nodes()) > 0 {
|
||||
if nodes, _ := chain.TrieDB().Size(); nodes > 0 {
|
||||
t.Fatalf("stale tries still alive after garbase collection")
|
||||
}
|
||||
}
|
||||
@@ -1781,7 +1781,7 @@ func TestBlockchainRecovery(t *testing.T) {
|
||||
for i, block := range blocks {
|
||||
headers[i] = block.Header()
|
||||
}
|
||||
if n, err := ancient.InsertHeaderChain(headers, 1); err != nil {
|
||||
if n, err := ancient.InsertHeaderChain(headers); err != nil {
|
||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||
}
|
||||
if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil {
|
||||
@@ -1850,7 +1850,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
|
||||
for i, block := range canonblocks {
|
||||
canonHeaders[i] = block.Header()
|
||||
}
|
||||
if _, err = ancientChain.InsertHeaderChain(canonHeaders, 1); err != nil {
|
||||
if _, err = ancientChain.InsertHeaderChain(canonHeaders); err != nil {
|
||||
t.Fatal("can't import canon headers:", err)
|
||||
}
|
||||
|
||||
@@ -2128,7 +2128,7 @@ func testInsertKnownChainData(t *testing.T, typ string) {
|
||||
for _, block := range blocks {
|
||||
headers = append(headers, block.Header())
|
||||
}
|
||||
_, err := chain.InsertHeaderChain(headers, 1)
|
||||
_, err := chain.InsertHeaderChain(headers)
|
||||
return err
|
||||
}
|
||||
asserter = func(t *testing.T, block *types.Block) {
|
||||
@@ -2142,7 +2142,7 @@ func testInsertKnownChainData(t *testing.T, typ string) {
|
||||
for _, block := range blocks {
|
||||
headers = append(headers, block.Header())
|
||||
}
|
||||
_, err := chain.InsertHeaderChain(headers, 1)
|
||||
_, err := chain.InsertHeaderChain(headers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2299,7 +2299,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
|
||||
for _, block := range blocks {
|
||||
headers = append(headers, block.Header())
|
||||
}
|
||||
i, err := chain.InsertHeaderChain(headers, 1)
|
||||
i, err := chain.InsertHeaderChain(headers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("index %d, number %d: %w", i, headers[i].Number, err)
|
||||
}
|
||||
@@ -2316,7 +2316,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
|
||||
for _, block := range blocks {
|
||||
headers = append(headers, block.Header())
|
||||
}
|
||||
i, err := chain.InsertHeaderChain(headers, 1)
|
||||
i, err := chain.InsertHeaderChain(headers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("index %d: %w", i, err)
|
||||
}
|
||||
@@ -2492,7 +2492,7 @@ func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) {
|
||||
for i, block := range canonblocks {
|
||||
canonHeaders[i] = block.Header()
|
||||
}
|
||||
if n, err := chain.InsertHeaderChain(canonHeaders, 0); err != nil {
|
||||
if n, err := chain.InsertHeaderChain(canonHeaders); err != nil {
|
||||
t.Fatalf("header %d: failed to insert into chain: %v", n, err)
|
||||
}
|
||||
canonNum := chain.CurrentHeader().Number.Uint64()
|
||||
@@ -2501,7 +2501,7 @@ func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) {
|
||||
for i, block := range sideblocks {
|
||||
sideHeaders[i] = block.Header()
|
||||
}
|
||||
if n, err := chain.InsertHeaderChain(sideHeaders, 0); err != nil {
|
||||
if n, err := chain.InsertHeaderChain(sideHeaders); err != nil {
|
||||
t.Fatalf("header %d: failed to insert into chain: %v", n, err)
|
||||
}
|
||||
head := chain.CurrentHeader()
|
||||
@@ -2692,7 +2692,7 @@ func TestSkipStaleTxIndicesInSnapSync(t *testing.T) {
|
||||
for i, block := range blocks {
|
||||
headers[i] = block.Header()
|
||||
}
|
||||
if n, err := chain.InsertHeaderChain(headers, 0); err != nil {
|
||||
if n, err := chain.InsertHeaderChain(headers); err != nil {
|
||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||
}
|
||||
// The indices before ancient-N(32) should be ignored. After that all blocks should be indexed.
|
||||
|
||||
+14
-17
@@ -120,7 +120,7 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
|
||||
// Create an ephemeral in-memory database for computing hash,
|
||||
// all the derived states will be discarded to not pollute disk.
|
||||
db := state.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
statedb, err := state.New(common.Hash{}, db, nil)
|
||||
statedb, err := state.New(types.EmptyRootHash, db, nil)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
@@ -139,7 +139,7 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
|
||||
// all the generated states will be persisted into the given database.
|
||||
// Also, the genesis state specification will be flushed as well.
|
||||
func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
|
||||
statedb, err := state.New(common.Hash{}, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
||||
statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -267,7 +267,7 @@ func (e *GenesisMismatchError) Error() string {
|
||||
|
||||
// ChainOverrides contains the changes to chain config.
|
||||
type ChainOverrides struct {
|
||||
OverrideShanghai *uint64
|
||||
OverrideCancun *uint64
|
||||
}
|
||||
|
||||
// SetupGenesisBlock writes or updates the genesis block in db.
|
||||
@@ -293,8 +293,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
||||
}
|
||||
applyOverrides := func(config *params.ChainConfig) {
|
||||
if config != nil {
|
||||
if overrides != nil && overrides.OverrideShanghai != nil {
|
||||
config.ShanghaiTime = overrides.OverrideShanghai
|
||||
if overrides != nil && overrides.OverrideCancun != nil {
|
||||
config.CancunTime = overrides.OverrideCancun
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -379,11 +379,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
||||
return newcfg, stored, nil
|
||||
}
|
||||
|
||||
// LoadCliqueConfig loads the stored clique config if the chain config
|
||||
// is already present in database, otherwise, return the config in the
|
||||
// provided genesis specification. Note the returned clique config can
|
||||
// be nil if we are not in the clique network.
|
||||
func LoadCliqueConfig(db ethdb.Database, genesis *Genesis) (*params.CliqueConfig, error) {
|
||||
// LoadChainConfig loads the stored chain config if it is already present in
|
||||
// database, otherwise, return the config in the provided genesis specification.
|
||||
func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, error) {
|
||||
// Load the stored chain config from the database. It can be nil
|
||||
// in case the database is empty. Notably, we only care about the
|
||||
// chain config corresponds to the canonical chain.
|
||||
@@ -391,10 +389,10 @@ func LoadCliqueConfig(db ethdb.Database, genesis *Genesis) (*params.CliqueConfig
|
||||
if stored != (common.Hash{}) {
|
||||
storedcfg := rawdb.ReadChainConfig(db, stored)
|
||||
if storedcfg != nil {
|
||||
return storedcfg.Clique, nil
|
||||
return storedcfg, nil
|
||||
}
|
||||
}
|
||||
// Load the clique config from the provided genesis specification.
|
||||
// Load the config from the provided genesis specification
|
||||
if genesis != nil {
|
||||
// Reject invalid genesis spec without valid chain config
|
||||
if genesis.Config == nil {
|
||||
@@ -407,12 +405,11 @@ func LoadCliqueConfig(db ethdb.Database, genesis *Genesis) (*params.CliqueConfig
|
||||
if stored != (common.Hash{}) && genesis.ToBlock().Hash() != stored {
|
||||
return nil, &GenesisMismatchError{stored, genesis.ToBlock().Hash()}
|
||||
}
|
||||
return genesis.Config.Clique, nil
|
||||
return genesis.Config, nil
|
||||
}
|
||||
// There is no stored chain config and no new config provided,
|
||||
// In this case the default chain config(mainnet) will be used,
|
||||
// namely ethash is the specified consensus engine, return nil.
|
||||
return nil, nil
|
||||
// In this case the default chain config(mainnet) will be used
|
||||
return params.MainnetChainConfig, nil
|
||||
}
|
||||
|
||||
func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
|
||||
@@ -466,7 +463,7 @@ func (g *Genesis) ToBlock() *types.Block {
|
||||
}
|
||||
}
|
||||
var withdrawals []*types.Withdrawal
|
||||
if g.Config != nil && g.Config.IsShanghai(g.Timestamp) {
|
||||
if g.Config != nil && g.Config.IsShanghai(big.NewInt(int64(g.Number)), g.Timestamp) {
|
||||
head.WithdrawalsHash = &types.EmptyWithdrawalsHash
|
||||
withdrawals = make([]*types.Withdrawal, 0)
|
||||
}
|
||||
|
||||
+3
-18
@@ -300,7 +300,7 @@ func (hc *HeaderChain) writeHeadersAndSetHead(headers []*types.Header, forker *F
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
|
||||
func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header) (int, error) {
|
||||
// Do a sanity check that the provided chain is actually ordered and linked
|
||||
for i := 1; i < len(chain); i++ {
|
||||
if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 {
|
||||
@@ -322,23 +322,8 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int)
|
||||
return i, ErrBannedHash
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the list of seal verification requests, and start the parallel verifier
|
||||
seals := make([]bool, len(chain))
|
||||
if checkFreq != 0 {
|
||||
// In case of checkFreq == 0 all seals are left false.
|
||||
for i := 0; i <= len(seals)/checkFreq; i++ {
|
||||
index := i*checkFreq + hc.rand.Intn(checkFreq)
|
||||
if index >= len(seals) {
|
||||
index = len(seals) - 1
|
||||
}
|
||||
seals[index] = true
|
||||
}
|
||||
// Last should always be verified to avoid junk.
|
||||
seals[len(seals)-1] = true
|
||||
}
|
||||
|
||||
abort, results := hc.engine.VerifyHeaders(hc, chain, seals)
|
||||
// Start the parallel verifier
|
||||
abort, results := hc.engine.VerifyHeaders(hc, chain)
|
||||
defer close(abort)
|
||||
|
||||
// Iterate over the headers and ensure they all check out
|
||||
|
||||
@@ -625,7 +625,7 @@ func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Rec
|
||||
// The current implementation populates these metadata fields by reading the receipts'
|
||||
// corresponding block body, so if the block body is not found it will return nil even
|
||||
// if the receipt itself is stored.
|
||||
func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) types.Receipts {
|
||||
func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, time uint64, config *params.ChainConfig) types.Receipts {
|
||||
// We're deriving many fields from the block body, retrieve beside the receipt
|
||||
receipts := ReadRawReceipts(db, hash, number)
|
||||
if receipts == nil {
|
||||
@@ -643,7 +643,7 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *para
|
||||
} else {
|
||||
baseFee = header.BaseFee
|
||||
}
|
||||
if err := receipts.DeriveFields(config, hash, number, baseFee, body.Transactions); err != nil {
|
||||
if err := receipts.DeriveFields(config, hash, number, time, baseFee, body.Transactions); err != nil {
|
||||
log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ func TestBlockReceiptStorage(t *testing.T) {
|
||||
|
||||
// Check that no receipt entries are in a pristine database
|
||||
hash := common.BytesToHash([]byte{0x03, 0x14})
|
||||
if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
t.Fatalf("non existent receipts returned: %v", rs)
|
||||
}
|
||||
// Insert the body that corresponds to the receipts
|
||||
@@ -387,7 +387,7 @@ func TestBlockReceiptStorage(t *testing.T) {
|
||||
|
||||
// Insert the receipt slice into the database and check presence
|
||||
WriteReceipts(db, hash, 0, receipts)
|
||||
if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) == 0 {
|
||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) == 0 {
|
||||
t.Fatalf("no receipts returned")
|
||||
} else {
|
||||
if err := checkReceiptsRLP(rs, receipts); err != nil {
|
||||
@@ -396,7 +396,7 @@ func TestBlockReceiptStorage(t *testing.T) {
|
||||
}
|
||||
// Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed)
|
||||
DeleteBody(db, hash, 0)
|
||||
if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); rs != nil {
|
||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); rs != nil {
|
||||
t.Fatalf("receipts returned when body was deleted: %v", rs)
|
||||
}
|
||||
// Ensure that receipts without metadata can be returned without the block body too
|
||||
@@ -407,7 +407,7 @@ func TestBlockReceiptStorage(t *testing.T) {
|
||||
WriteBody(db, hash, 0, body)
|
||||
|
||||
DeleteReceipts(db, hash, 0)
|
||||
if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
t.Fatalf("deleted receipts returned: %v", rs)
|
||||
}
|
||||
}
|
||||
@@ -727,7 +727,7 @@ func TestReadLogs(t *testing.T) {
|
||||
|
||||
hash := common.BytesToHash([]byte{0x03, 0x14})
|
||||
// Check that no receipt entries are in a pristine database
|
||||
if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
t.Fatalf("non existent receipts returned: %v", rs)
|
||||
}
|
||||
// Insert the body that corresponds to the receipts
|
||||
|
||||
@@ -130,8 +130,12 @@ func ReadReceipt(db ethdb.Reader, hash common.Hash, config *params.ChainConfig)
|
||||
if blockHash == (common.Hash{}) {
|
||||
return nil, common.Hash{}, 0, 0
|
||||
}
|
||||
blockHeader := ReadHeader(db, blockHash, *blockNumber)
|
||||
if blockHeader == nil {
|
||||
return nil, common.Hash{}, 0, 0
|
||||
}
|
||||
// Read all the receipts from the block and return the one with the matching hash
|
||||
receipts := ReadReceipts(db, blockHash, *blockNumber, config)
|
||||
receipts := ReadReceipts(db, blockHash, *blockNumber, blockHeader.Time, config)
|
||||
for receiptIndex, receipt := range receipts {
|
||||
if receipt.TxHash == hash {
|
||||
return receipt, blockHash, *blockNumber, uint64(receiptIndex)
|
||||
|
||||
+20
-7
@@ -358,9 +358,15 @@ type OpenOptions struct {
|
||||
//
|
||||
// type == null type != null
|
||||
// +----------------------------------------
|
||||
// db is non-existent | leveldb default | specified type
|
||||
// db is existent | from db | specified type (if compatible)
|
||||
// db is non-existent | pebble default | specified type
|
||||
// db is existent | from db | specified type (if compatible)
|
||||
func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
|
||||
// Reject any unsupported database type
|
||||
if len(o.Type) != 0 && o.Type != dbLeveldb && o.Type != dbPebble {
|
||||
return nil, fmt.Errorf("unknown db.engine %v", o.Type)
|
||||
}
|
||||
// Retrieve any pre-existing database's type and use that or the requested one
|
||||
// as long as there's no conflict between the two types
|
||||
existingDb := hasPreexistingDb(o.Directory)
|
||||
if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb {
|
||||
return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb)
|
||||
@@ -373,12 +379,19 @@ func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
|
||||
return nil, errors.New("db.engine 'pebble' not supported on this platform")
|
||||
}
|
||||
}
|
||||
if len(o.Type) != 0 && o.Type != dbLeveldb {
|
||||
return nil, fmt.Errorf("unknown db.engine %v", o.Type)
|
||||
if o.Type == dbLeveldb || existingDb == dbLeveldb {
|
||||
log.Info("Using leveldb as the backing database")
|
||||
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
}
|
||||
// No pre-existing database, no user-requested one either. Default to Pebble
|
||||
// on supported platforms and LevelDB on anything else.
|
||||
if PebbleEnabled {
|
||||
log.Info("Defaulting to pebble as the backing database")
|
||||
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
} else {
|
||||
log.Info("Defaulting to leveldb as the backing database")
|
||||
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
}
|
||||
log.Info("Using leveldb as the backing database")
|
||||
// Use leveldb, either as default (no explicit choice), or pre-existing, or chosen explicitly
|
||||
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
}
|
||||
|
||||
// Open opens both a disk-based key-value database such as leveldb or pebble, but also
|
||||
|
||||
+47
-1
@@ -22,6 +22,7 @@ import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
)
|
||||
|
||||
@@ -100,7 +101,7 @@ var (
|
||||
CodePrefix = []byte("c") // CodePrefix + code hash -> account code
|
||||
skeletonHeaderPrefix = []byte("S") // skeletonHeaderPrefix + num (uint64 big endian) -> header
|
||||
|
||||
// Path-based trie node scheme.
|
||||
// Path-based storage scheme of merkle patricia trie.
|
||||
trieNodeAccountPrefix = []byte("A") // trieNodeAccountPrefix + hexPath -> trie node
|
||||
trieNodeStoragePrefix = []byte("O") // trieNodeStoragePrefix + accountHash + hexPath -> trie node
|
||||
|
||||
@@ -248,3 +249,48 @@ func accountTrieNodeKey(path []byte) []byte {
|
||||
func storageTrieNodeKey(accountHash common.Hash, path []byte) []byte {
|
||||
return append(append(trieNodeStoragePrefix, accountHash.Bytes()...), path...)
|
||||
}
|
||||
|
||||
// IsLegacyTrieNode reports whether a provided database entry is a legacy trie
|
||||
// node. The characteristics of legacy trie node are:
|
||||
// - the key length is 32 bytes
|
||||
// - the key is the hash of val
|
||||
func IsLegacyTrieNode(key []byte, val []byte) bool {
|
||||
if len(key) != common.HashLength {
|
||||
return false
|
||||
}
|
||||
return bytes.Equal(key, crypto.Keccak256(val))
|
||||
}
|
||||
|
||||
// IsAccountTrieNode reports whether a provided database entry is an account
|
||||
// trie node in path-based state scheme.
|
||||
func IsAccountTrieNode(key []byte) (bool, []byte) {
|
||||
if !bytes.HasPrefix(key, trieNodeAccountPrefix) {
|
||||
return false, nil
|
||||
}
|
||||
// The remaining key should only consist a hex node path
|
||||
// whose length is in the range 0 to 64 (64 is excluded
|
||||
// since leaves are always wrapped with shortNode).
|
||||
if len(key) >= len(trieNodeAccountPrefix)+common.HashLength*2 {
|
||||
return false, nil
|
||||
}
|
||||
return true, key[len(trieNodeAccountPrefix):]
|
||||
}
|
||||
|
||||
// IsStorageTrieNode reports whether a provided database entry is a storage
|
||||
// trie node in path-based state scheme.
|
||||
func IsStorageTrieNode(key []byte) (bool, common.Hash, []byte) {
|
||||
if !bytes.HasPrefix(key, trieNodeStoragePrefix) {
|
||||
return false, common.Hash{}, nil
|
||||
}
|
||||
// The remaining key consists of 2 parts:
|
||||
// - 32 bytes account hash
|
||||
// - hex node path whose length is in the range 0 to 64
|
||||
if len(key) < len(trieNodeStoragePrefix)+common.HashLength {
|
||||
return false, common.Hash{}, nil
|
||||
}
|
||||
if len(key) >= len(trieNodeStoragePrefix)+common.HashLength+common.HashLength*2 {
|
||||
return false, common.Hash{}, nil
|
||||
}
|
||||
accountHash := common.BytesToHash(key[len(trieNodeStoragePrefix) : len(trieNodeStoragePrefix)+common.HashLength])
|
||||
return true, accountHash, key[len(trieNodeStoragePrefix)+common.HashLength:]
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -109,7 +110,7 @@ type Trie interface {
|
||||
// The returned nodeset can be nil if the trie is clean(nothing to commit).
|
||||
// Once the trie is committed, it's not usable anymore. A new trie must
|
||||
// be created with new root and updated trie database for following usage
|
||||
Commit(collectLeaf bool) (common.Hash, *trie.NodeSet)
|
||||
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet)
|
||||
|
||||
// NodeIterator returns an iterator that returns nodes of the trie. Iteration
|
||||
// starts at the key after the given start key.
|
||||
|
||||
+19
-14
@@ -44,7 +44,7 @@ type DumpCollector interface {
|
||||
// OnRoot is called with the state root
|
||||
OnRoot(common.Hash)
|
||||
// OnAccount is called once for each account in the trie
|
||||
OnAccount(common.Address, DumpAccount)
|
||||
OnAccount(*common.Address, DumpAccount)
|
||||
}
|
||||
|
||||
// DumpAccount represents an account in the state.
|
||||
@@ -72,8 +72,10 @@ func (d *Dump) OnRoot(root common.Hash) {
|
||||
}
|
||||
|
||||
// OnAccount implements DumpCollector interface
|
||||
func (d *Dump) OnAccount(addr common.Address, account DumpAccount) {
|
||||
d.Accounts[addr] = account
|
||||
func (d *Dump) OnAccount(addr *common.Address, account DumpAccount) {
|
||||
if addr != nil {
|
||||
d.Accounts[*addr] = account
|
||||
}
|
||||
}
|
||||
|
||||
// IteratorDump is an implementation for iterating over data.
|
||||
@@ -89,8 +91,10 @@ func (d *IteratorDump) OnRoot(root common.Hash) {
|
||||
}
|
||||
|
||||
// OnAccount implements DumpCollector interface
|
||||
func (d *IteratorDump) OnAccount(addr common.Address, account DumpAccount) {
|
||||
d.Accounts[addr] = account
|
||||
func (d *IteratorDump) OnAccount(addr *common.Address, account DumpAccount) {
|
||||
if addr != nil {
|
||||
d.Accounts[*addr] = account
|
||||
}
|
||||
}
|
||||
|
||||
// iterativeDump is a DumpCollector-implementation which dumps output line-by-line iteratively.
|
||||
@@ -99,7 +103,7 @@ type iterativeDump struct {
|
||||
}
|
||||
|
||||
// OnAccount implements DumpCollector interface
|
||||
func (d iterativeDump) OnAccount(addr common.Address, account DumpAccount) {
|
||||
func (d iterativeDump) OnAccount(addr *common.Address, account DumpAccount) {
|
||||
dumpAccount := &DumpAccount{
|
||||
Balance: account.Balance,
|
||||
Nonce: account.Nonce,
|
||||
@@ -108,10 +112,7 @@ func (d iterativeDump) OnAccount(addr common.Address, account DumpAccount) {
|
||||
Code: account.Code,
|
||||
Storage: account.Storage,
|
||||
SecureKey: account.SecureKey,
|
||||
Address: nil,
|
||||
}
|
||||
if addr != (common.Address{}) {
|
||||
dumpAccount.Address = &addr
|
||||
Address: addr,
|
||||
}
|
||||
d.Encode(dumpAccount)
|
||||
}
|
||||
@@ -152,16 +153,20 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
|
||||
CodeHash: data.CodeHash,
|
||||
SecureKey: it.Key,
|
||||
}
|
||||
addrBytes := s.trie.GetKey(it.Key)
|
||||
var (
|
||||
addrBytes = s.trie.GetKey(it.Key)
|
||||
addr = common.BytesToAddress(addrBytes)
|
||||
address *common.Address
|
||||
)
|
||||
if addrBytes == nil {
|
||||
// Preimage missing
|
||||
missingPreimages++
|
||||
if conf.OnlyWithAddresses {
|
||||
continue
|
||||
}
|
||||
account.SecureKey = it.Key
|
||||
} else {
|
||||
address = &addr
|
||||
}
|
||||
addr := common.BytesToAddress(addrBytes)
|
||||
obj := newObject(s, addr, data)
|
||||
if !conf.SkipCode {
|
||||
account.Code = obj.Code(s.db)
|
||||
@@ -183,7 +188,7 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
|
||||
account.Storage[common.BytesToHash(s.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(content)
|
||||
}
|
||||
}
|
||||
c.OnAccount(addr, account)
|
||||
c.OnAccount(address, account)
|
||||
accounts++
|
||||
if time.Since(logged) > 8*time.Second {
|
||||
log.Info("Trie dumping in progress", "at", it.Key, "accounts", accounts,
|
||||
|
||||
@@ -26,9 +26,9 @@ import (
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
||||
// NodeIterator is an iterator to traverse the entire state trie post-order,
|
||||
// nodeIterator is an iterator to traverse the entire state trie post-order,
|
||||
// including all of the contract code and contract state tries.
|
||||
type NodeIterator struct {
|
||||
type nodeIterator struct {
|
||||
state *StateDB // State being iterated
|
||||
|
||||
stateIt trie.NodeIterator // Primary iterator for the global state trie
|
||||
@@ -44,9 +44,9 @@ type NodeIterator struct {
|
||||
Error error // Failure set in case of an internal error in the iterator
|
||||
}
|
||||
|
||||
// NewNodeIterator creates an post-order state node iterator.
|
||||
func NewNodeIterator(state *StateDB) *NodeIterator {
|
||||
return &NodeIterator{
|
||||
// newNodeIterator creates an post-order state node iterator.
|
||||
func newNodeIterator(state *StateDB) *nodeIterator {
|
||||
return &nodeIterator{
|
||||
state: state,
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ func NewNodeIterator(state *StateDB) *NodeIterator {
|
||||
// Next moves the iterator to the next node, returning whether there are any
|
||||
// further nodes. In case of an internal error this method returns false and
|
||||
// sets the Error field to the encountered failure.
|
||||
func (it *NodeIterator) Next() bool {
|
||||
func (it *nodeIterator) Next() bool {
|
||||
// If the iterator failed previously, don't do anything
|
||||
if it.Error != nil {
|
||||
return false
|
||||
@@ -68,7 +68,7 @@ func (it *NodeIterator) Next() bool {
|
||||
}
|
||||
|
||||
// step moves the iterator to the next entry of the state trie.
|
||||
func (it *NodeIterator) step() error {
|
||||
func (it *nodeIterator) step() error {
|
||||
// Abort if we reached the end of the iteration
|
||||
if it.state == nil {
|
||||
return nil
|
||||
@@ -131,7 +131,7 @@ func (it *NodeIterator) step() error {
|
||||
|
||||
// retrieve pulls and caches the current state entry the iterator is traversing.
|
||||
// The method returns whether there are any more data left for inspection.
|
||||
func (it *NodeIterator) retrieve() bool {
|
||||
func (it *nodeIterator) retrieve() bool {
|
||||
// Clear out any previously set values
|
||||
it.Hash = common.Hash{}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
// Tests that the node iterator indeed walks over the entire database contents.
|
||||
@@ -35,7 +36,7 @@ func TestNodeIteratorCoverage(t *testing.T) {
|
||||
}
|
||||
// Gather all the node hashes found by the iterator
|
||||
hashes := make(map[common.Hash]struct{})
|
||||
for it := NewNodeIterator(state); it.Next(); {
|
||||
for it := newNodeIterator(state); it.Next(); {
|
||||
if it.Hash != (common.Hash{}) {
|
||||
hashes[it.Hash] = struct{}{}
|
||||
}
|
||||
@@ -85,9 +86,18 @@ func TestNodeIteratorCoverage(t *testing.T) {
|
||||
// database entry belongs to a trie node or not.
|
||||
func isTrieNode(scheme string, key, val []byte) (bool, common.Hash) {
|
||||
if scheme == rawdb.HashScheme {
|
||||
if len(key) == common.HashLength {
|
||||
if rawdb.IsLegacyTrieNode(key, val) {
|
||||
return true, common.BytesToHash(key)
|
||||
}
|
||||
} else {
|
||||
ok, _ := rawdb.IsAccountTrieNode(key)
|
||||
if ok {
|
||||
return true, crypto.Keccak256Hash(val)
|
||||
}
|
||||
ok, _, _ = rawdb.IsStorageTrieNode(key)
|
||||
if ok {
|
||||
return true, crypto.Keccak256Hash(val)
|
||||
}
|
||||
}
|
||||
return false, common.Hash{}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,6 @@ func (bloom *stateBloom) Delete(key []byte) error { panic("not supported") }
|
||||
// reports whether the key is contained.
|
||||
// - If it says yes, the key may be contained
|
||||
// - If it says no, the key is definitely not contained.
|
||||
func (bloom *stateBloom) Contain(key []byte) (bool, error) {
|
||||
return bloom.bloom.Contains(stateBloomHasher(key)), nil
|
||||
func (bloom *stateBloom) Contain(key []byte) bool {
|
||||
return bloom.bloom.Contains(stateBloomHasher(key))
|
||||
}
|
||||
|
||||
@@ -146,9 +146,7 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta
|
||||
if _, exist := middleStateRoots[common.BytesToHash(checkKey)]; exist {
|
||||
log.Debug("Forcibly delete the middle state roots", "hash", common.BytesToHash(checkKey))
|
||||
} else {
|
||||
if ok, err := stateBloom.Contain(checkKey); err != nil {
|
||||
return err
|
||||
} else if ok {
|
||||
if stateBloom.Contain(checkKey) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,9 +292,14 @@ func (dl *diffLayer) Account(hash common.Hash) (*Account, error) {
|
||||
//
|
||||
// Note the returned account is not a copy, please don't modify it.
|
||||
func (dl *diffLayer) AccountRLP(hash common.Hash) ([]byte, error) {
|
||||
dl.lock.RLock()
|
||||
// Check staleness before reaching further.
|
||||
if dl.Stale() {
|
||||
dl.lock.RUnlock()
|
||||
return nil, ErrSnapshotStale
|
||||
}
|
||||
// Check the bloom filter first whether there's even a point in reaching into
|
||||
// all the maps in all the layers below
|
||||
dl.lock.RLock()
|
||||
hit := dl.diffed.Contains(accountBloomHasher(hash))
|
||||
if !hit {
|
||||
hit = dl.diffed.Contains(destructBloomHasher(hash))
|
||||
@@ -361,6 +366,11 @@ func (dl *diffLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
|
||||
// Check the bloom filter first whether there's even a point in reaching into
|
||||
// all the maps in all the layers below
|
||||
dl.lock.RLock()
|
||||
// Check staleness before reaching further.
|
||||
if dl.Stale() {
|
||||
dl.lock.RUnlock()
|
||||
return nil, ErrSnapshotStale
|
||||
}
|
||||
hit := dl.diffed.Contains(storageBloomHasher{accountHash, storageHash})
|
||||
if !hit {
|
||||
hit = dl.diffed.Contains(destructBloomHasher(accountHash))
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -363,7 +364,7 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, trieId *trie.ID, prefi
|
||||
}
|
||||
root, nodes := snapTrie.Commit(false)
|
||||
if nodes != nil {
|
||||
tdb.Update(trie.NewWithNodeSet(nodes))
|
||||
tdb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||
tdb.Commit(root, false)
|
||||
}
|
||||
resolver = func(owner common.Hash, path []byte, hash common.Hash) []byte {
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
@@ -48,14 +49,14 @@ func TestGeneration(t *testing.T) {
|
||||
// a fake one manually. We're going with a small account trie of 3 accounts,
|
||||
// two of which also has the same 3-slot storage trie attached.
|
||||
var helper = newHelper()
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false)
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false)
|
||||
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
|
||||
root, snap := helper.CommitAndGenerate()
|
||||
if have, want := root, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"); have != want {
|
||||
@@ -83,7 +84,7 @@ func TestGenerateExistentState(t *testing.T) {
|
||||
// two of which also has the same 3-slot storage trie attached.
|
||||
var helper = newHelper()
|
||||
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
|
||||
@@ -91,7 +92,7 @@ func TestGenerateExistentState(t *testing.T) {
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
|
||||
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
|
||||
@@ -144,18 +145,18 @@ type testHelper struct {
|
||||
diskdb ethdb.Database
|
||||
triedb *trie.Database
|
||||
accTrie *trie.StateTrie
|
||||
nodes *trie.MergedNodeSet
|
||||
nodes *trienode.MergedNodeSet
|
||||
}
|
||||
|
||||
func newHelper() *testHelper {
|
||||
diskdb := rawdb.NewMemoryDatabase()
|
||||
triedb := trie.NewDatabase(diskdb)
|
||||
accTrie, _ := trie.NewStateTrie(trie.StateTrieID(common.Hash{}), triedb)
|
||||
accTrie, _ := trie.NewStateTrie(trie.StateTrieID(types.EmptyRootHash), triedb)
|
||||
return &testHelper{
|
||||
diskdb: diskdb,
|
||||
triedb: triedb,
|
||||
accTrie: accTrie,
|
||||
nodes: trie.NewMergedNodeSet(),
|
||||
nodes: trienode.NewMergedNodeSet(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,8 +183,8 @@ func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *testHelper) makeStorageTrie(stateRoot, owner common.Hash, keys []string, vals []string, commit bool) []byte {
|
||||
id := trie.StorageTrieID(stateRoot, owner, common.Hash{})
|
||||
func (t *testHelper) makeStorageTrie(owner common.Hash, keys []string, vals []string, commit bool) []byte {
|
||||
id := trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash)
|
||||
stTrie, _ := trie.NewStateTrie(id, t.triedb)
|
||||
for i, k := range keys {
|
||||
stTrie.MustUpdate([]byte(k), []byte(vals[i]))
|
||||
@@ -203,7 +204,7 @@ func (t *testHelper) Commit() common.Hash {
|
||||
if nodes != nil {
|
||||
t.nodes.Merge(nodes)
|
||||
}
|
||||
t.triedb.Update(t.nodes)
|
||||
t.triedb.Update(root, types.EmptyRootHash, t.nodes)
|
||||
t.triedb.Commit(root, false)
|
||||
return root
|
||||
}
|
||||
@@ -240,23 +241,23 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
|
||||
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
|
||||
|
||||
// Account two, non empty root but empty database
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
|
||||
// Miss slots
|
||||
{
|
||||
// Account three, non empty root but misses slots in the beginning
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"})
|
||||
|
||||
// Account four, non empty root but misses slots in the middle
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"})
|
||||
|
||||
// Account five, non empty root but misses slots in the end
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"})
|
||||
}
|
||||
@@ -264,22 +265,22 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
|
||||
// Wrong storage slots
|
||||
{
|
||||
// Account six, non empty root but wrong slots in the beginning
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"})
|
||||
|
||||
// Account seven, non empty root but wrong slots in the middle
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"})
|
||||
|
||||
// Account eight, non empty root but wrong slots in the end
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"})
|
||||
|
||||
// Account 9, non empty root but rotated slots
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"})
|
||||
}
|
||||
@@ -287,17 +288,17 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
|
||||
// Extra storage slots
|
||||
{
|
||||
// Account 10, non empty root but extra slots in the beginning
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"})
|
||||
|
||||
// Account 11, non empty root but extra slots in the middle
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"})
|
||||
|
||||
// Account 12, non empty root but extra slots in the end
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"})
|
||||
}
|
||||
@@ -327,11 +328,11 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
|
||||
func TestGenerateExistentStateWithWrongAccounts(t *testing.T) {
|
||||
helper := newHelper()
|
||||
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
|
||||
// Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6]
|
||||
// Extra accounts [acc-0, acc-5, acc-7]
|
||||
@@ -419,10 +420,10 @@ func TestGenerateMissingStorageTrie(t *testing.T) {
|
||||
// two of which also has the same 3-slot storage trie attached.
|
||||
helper := newHelper()
|
||||
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
||||
|
||||
root := helper.Commit()
|
||||
@@ -453,10 +454,10 @@ func TestGenerateCorruptStorageTrie(t *testing.T) {
|
||||
// two of which also has the same 3-slot storage trie attached.
|
||||
helper := newHelper()
|
||||
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
||||
|
||||
root := helper.Commit()
|
||||
@@ -484,7 +485,7 @@ func TestGenerateWithExtraAccounts(t *testing.T) {
|
||||
helper := newHelper()
|
||||
{
|
||||
// Account one in the trie
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")),
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")),
|
||||
[]string{"key-1", "key-2", "key-3", "key-4", "key-5"},
|
||||
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
|
||||
true,
|
||||
@@ -504,7 +505,7 @@ func TestGenerateWithExtraAccounts(t *testing.T) {
|
||||
}
|
||||
{
|
||||
// Account two exists only in the snapshot
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")),
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte("acc-2")),
|
||||
[]string{"key-1", "key-2", "key-3", "key-4", "key-5"},
|
||||
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
|
||||
true,
|
||||
@@ -555,7 +556,7 @@ func TestGenerateWithManyExtraAccounts(t *testing.T) {
|
||||
helper := newHelper()
|
||||
{
|
||||
// Account one in the trie
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")),
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")),
|
||||
[]string{"key-1", "key-2", "key-3"},
|
||||
[]string{"val-1", "val-2", "val-3"},
|
||||
true,
|
||||
@@ -685,7 +686,7 @@ func TestGenerateFromEmptySnap(t *testing.T) {
|
||||
helper := newHelper()
|
||||
// Add 1K accounts to the trie
|
||||
for i := 0; i < 400; i++ {
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount(fmt.Sprintf("acc-%d", i),
|
||||
&Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
}
|
||||
@@ -723,7 +724,7 @@ func TestGenerateWithIncompleteStorage(t *testing.T) {
|
||||
// on the sensitive spots at the boundaries
|
||||
for i := 0; i < 8; i++ {
|
||||
accKey := fmt.Sprintf("acc-%d", i)
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(accKey)), stKeys, stVals, true)
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte(accKey)), stKeys, stVals, true)
|
||||
helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
var moddedKeys []string
|
||||
var moddedVals []string
|
||||
@@ -815,11 +816,11 @@ func populateDangling(disk ethdb.KeyValueStore) {
|
||||
func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
|
||||
var helper = newHelper()
|
||||
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
|
||||
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
|
||||
@@ -850,11 +851,11 @@ func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
|
||||
func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) {
|
||||
var helper = newHelper()
|
||||
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
|
||||
populateDangling(helper.diskdb)
|
||||
|
||||
@@ -185,6 +185,10 @@ func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) {
|
||||
// be returned with junk data. This version of the test retains the bottom diff
|
||||
// layer to check the usual mode of operation where the accumulator is retained.
|
||||
func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) {
|
||||
// Un-commenting this triggers the bloom set to be deterministic. The values below
|
||||
// were used to trigger the flaw described in https://github.com/ethereum/go-ethereum/issues/27254.
|
||||
// bloomDestructHasherOffset, bloomAccountHasherOffset, bloomStorageHasherOffset = 14, 24, 5
|
||||
|
||||
// Create an empty base layer and a snapshot tree out of it
|
||||
base := &diskLayer{
|
||||
diskdb: rawdb.NewMemoryDatabase(),
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
||||
type Code []byte
|
||||
@@ -350,7 +350,7 @@ func (s *stateObject) updateRoot(db Database) {
|
||||
|
||||
// commitTrie submits the storage changes into the storage trie and re-computes
|
||||
// the root. Besides, all trie changes will be collected in a nodeset and returned.
|
||||
func (s *stateObject) commitTrie(db Database) (*trie.NodeSet, error) {
|
||||
func (s *stateObject) commitTrie(db Database) (*trienode.NodeSet, error) {
|
||||
tr, err := s.updateTrie(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -18,11 +18,13 @@ package state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
@@ -35,13 +37,13 @@ type stateTest struct {
|
||||
|
||||
func newStateTest() *stateTest {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
sdb, _ := New(common.Hash{}, NewDatabase(db), nil)
|
||||
sdb, _ := New(types.EmptyRootHash, NewDatabase(db), nil)
|
||||
return &stateTest{db: db, state: sdb}
|
||||
}
|
||||
|
||||
func TestDump(t *testing.T) {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
sdb, _ := New(common.Hash{}, NewDatabaseWithConfig(db, &trie.Config{Preimages: true}), nil)
|
||||
sdb, _ := New(types.EmptyRootHash, NewDatabaseWithConfig(db, &trie.Config{Preimages: true}), nil)
|
||||
s := &stateTest{db: db, state: sdb}
|
||||
|
||||
// generate a few entries
|
||||
@@ -91,6 +93,41 @@ func TestDump(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIterativeDump(t *testing.T) {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
sdb, _ := New(types.EmptyRootHash, NewDatabaseWithConfig(db, &trie.Config{Preimages: true}), nil)
|
||||
s := &stateTest{db: db, state: sdb}
|
||||
|
||||
// generate a few entries
|
||||
obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
|
||||
obj1.AddBalance(big.NewInt(22))
|
||||
obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
|
||||
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
|
||||
obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
|
||||
obj3.SetBalance(big.NewInt(44))
|
||||
obj4 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x00}))
|
||||
obj4.AddBalance(big.NewInt(1337))
|
||||
|
||||
// write some of them to the trie
|
||||
s.state.updateStateObject(obj1)
|
||||
s.state.updateStateObject(obj2)
|
||||
s.state.Commit(false)
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
s.state.IterativeDump(nil, json.NewEncoder(b))
|
||||
// check that DumpToCollector contains the state objects that are in trie
|
||||
got := b.String()
|
||||
want := `{"root":"0xd5710ea8166b7b04bc2bfb129d7db12931cee82f75ca8e2d075b4884322bf3de"}
|
||||
{"balance":"22","nonce":0,"root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","address":"0x0000000000000000000000000000000000000001","key":"0x1468288056310c82aa4c01a7e12a10f8111a0560e72b700555479031b86c357d"}
|
||||
{"balance":"1337","nonce":0,"root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","address":"0x0000000000000000000000000000000000000000","key":"0x5380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a"}
|
||||
{"balance":"0","nonce":0,"root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","codeHash":"0x87874902497a5bb968da31a2998d8f22e949d1ef6214bcdedd8bae24cca4b9e3","code":"0x03030303030303","address":"0x0000000000000000000000000000000000000102","key":"0xa17eacbc25cda025e81db9c5c62868822c73ce097cee2a63e33a2e41268358a1"}
|
||||
{"balance":"44","nonce":0,"root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","address":"0x0000000000000000000000000000000000000002","key":"0xd52688a8f926c816ca1e079067caba944f158e764817b83fc43594370ca9cf62"}
|
||||
`
|
||||
if got != want {
|
||||
t.Errorf("DumpToCollector mismatch:\ngot: %s\nwant: %s\n", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNull(t *testing.T) {
|
||||
s := newStateTest()
|
||||
address := common.HexToAddress("0x823140710bf13990e4500136726d8b55")
|
||||
@@ -150,7 +187,7 @@ func TestSnapshotEmpty(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSnapshot2(t *testing.T) {
|
||||
state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
|
||||
stateobjaddr0 := common.BytesToAddress([]byte("so0"))
|
||||
stateobjaddr1 := common.BytesToAddress([]byte("so1"))
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
||||
type revision struct {
|
||||
@@ -792,13 +793,13 @@ func (s *StateDB) Copy() *StateDB {
|
||||
state.snap = s.snap
|
||||
|
||||
// deep copy needed
|
||||
state.snapAccounts = make(map[common.Hash][]byte)
|
||||
state.snapAccounts = make(map[common.Hash][]byte, len(s.snapAccounts))
|
||||
for k, v := range s.snapAccounts {
|
||||
state.snapAccounts[k] = v
|
||||
}
|
||||
state.snapStorage = make(map[common.Hash]map[common.Hash][]byte)
|
||||
state.snapStorage = make(map[common.Hash]map[common.Hash][]byte, len(s.snapStorage))
|
||||
for k, v := range s.snapStorage {
|
||||
temp := make(map[common.Hash][]byte)
|
||||
temp := make(map[common.Hash][]byte, len(v))
|
||||
for kk, vv := range v {
|
||||
temp[kk] = vv
|
||||
}
|
||||
@@ -980,7 +981,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
accountTrieNodesDeleted int
|
||||
storageTrieNodesUpdated int
|
||||
storageTrieNodesDeleted int
|
||||
nodes = trie.NewMergedNodeSet()
|
||||
nodes = trienode.NewMergedNodeSet()
|
||||
codeWriter = s.db.DiskDB().NewBatch()
|
||||
)
|
||||
// begin PluGeth injection
|
||||
@@ -1001,7 +1002,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
// Merge the dirty nodes of storage trie into global set
|
||||
// Merge the dirty nodes of storage trie into global set.
|
||||
if set != nil {
|
||||
if err := nodes.Merge(set); err != nil {
|
||||
return common.Hash{}, err
|
||||
@@ -1091,7 +1092,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
}
|
||||
if root != origin {
|
||||
start := time.Now()
|
||||
if err := s.db.TrieDB().Update(nodes); err != nil {
|
||||
if err := s.db.TrieDB().Update(root, origin, nodes); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
s.originalRoot = root
|
||||
@@ -1180,7 +1181,7 @@ func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addre
|
||||
|
||||
// convertAccountSet converts a provided account set from address keyed to hash keyed.
|
||||
func (s *StateDB) convertAccountSet(set map[common.Address]struct{}) map[common.Hash]struct{} {
|
||||
ret := make(map[common.Hash]struct{})
|
||||
ret := make(map[common.Hash]struct{}, len(set))
|
||||
for addr := range set {
|
||||
obj, exist := s.stateObjects[addr]
|
||||
if !exist {
|
||||
|
||||
+14
-14
@@ -39,7 +39,7 @@ import (
|
||||
func TestUpdateLeaks(t *testing.T) {
|
||||
// Create an empty state database
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
state, _ := New(common.Hash{}, NewDatabase(db), nil)
|
||||
state, _ := New(types.EmptyRootHash, NewDatabase(db), nil)
|
||||
|
||||
// Update it with some accounts
|
||||
for i := byte(0); i < 255; i++ {
|
||||
@@ -73,8 +73,8 @@ func TestIntermediateLeaks(t *testing.T) {
|
||||
// Create two state databases, one transitioning to the final state, the other final from the beginning
|
||||
transDb := rawdb.NewMemoryDatabase()
|
||||
finalDb := rawdb.NewMemoryDatabase()
|
||||
transState, _ := New(common.Hash{}, NewDatabase(transDb), nil)
|
||||
finalState, _ := New(common.Hash{}, NewDatabase(finalDb), nil)
|
||||
transState, _ := New(types.EmptyRootHash, NewDatabase(transDb), nil)
|
||||
finalState, _ := New(types.EmptyRootHash, NewDatabase(finalDb), nil)
|
||||
|
||||
modify := func(state *StateDB, addr common.Address, i, tweak byte) {
|
||||
state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak)))
|
||||
@@ -149,7 +149,7 @@ func TestIntermediateLeaks(t *testing.T) {
|
||||
// https://github.com/ethereum/go-ethereum/pull/15549.
|
||||
func TestCopy(t *testing.T) {
|
||||
// Create a random state test to copy and modify "independently"
|
||||
orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
orig, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
|
||||
for i := byte(0); i < 255; i++ {
|
||||
obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||
@@ -409,7 +409,7 @@ func (test *snapshotTest) String() string {
|
||||
func (test *snapshotTest) run() bool {
|
||||
// Run all actions and create snapshots.
|
||||
var (
|
||||
state, _ = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
state, _ = New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
snapshotRevs = make([]int, len(test.snapshots))
|
||||
sindex = 0
|
||||
)
|
||||
@@ -423,7 +423,7 @@ func (test *snapshotTest) run() bool {
|
||||
// Revert all snapshots in reverse order. Each revert must yield a state
|
||||
// that is equivalent to fresh state with all actions up the snapshot applied.
|
||||
for sindex--; sindex >= 0; sindex-- {
|
||||
checkstate, _ := New(common.Hash{}, state.Database(), nil)
|
||||
checkstate, _ := New(types.EmptyRootHash, state.Database(), nil)
|
||||
for _, action := range test.actions[:test.snapshots[sindex]] {
|
||||
action.fn(action, checkstate)
|
||||
}
|
||||
@@ -501,7 +501,7 @@ func TestTouchDelete(t *testing.T) {
|
||||
// TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
|
||||
// See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512
|
||||
func TestCopyOfCopy(t *testing.T) {
|
||||
state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
addr := common.HexToAddress("aaaa")
|
||||
state.SetBalance(addr, big.NewInt(42))
|
||||
|
||||
@@ -518,7 +518,7 @@ func TestCopyOfCopy(t *testing.T) {
|
||||
//
|
||||
// See https://github.com/ethereum/go-ethereum/issues/20106.
|
||||
func TestCopyCommitCopy(t *testing.T) {
|
||||
state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
|
||||
// Create an account and check if the retrieved balance is correct
|
||||
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
||||
@@ -590,7 +590,7 @@ func TestCopyCommitCopy(t *testing.T) {
|
||||
//
|
||||
// See https://github.com/ethereum/go-ethereum/issues/20106.
|
||||
func TestCopyCopyCommitCopy(t *testing.T) {
|
||||
state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
|
||||
// Create an account and check if the retrieved balance is correct
|
||||
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
||||
@@ -680,7 +680,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
|
||||
// first, but the journal wiped the entire state object on create-revert.
|
||||
func TestDeleteCreateRevert(t *testing.T) {
|
||||
// Create an initial state with a single contract
|
||||
state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
|
||||
addr := common.BytesToAddress([]byte("so"))
|
||||
state.SetBalance(addr, big.NewInt(1))
|
||||
@@ -713,7 +713,7 @@ func TestMissingTrieNodes(t *testing.T) {
|
||||
memDb := rawdb.NewMemoryDatabase()
|
||||
db := NewDatabase(memDb)
|
||||
var root common.Hash
|
||||
state, _ := New(common.Hash{}, db, nil)
|
||||
state, _ := New(types.EmptyRootHash, db, nil)
|
||||
addr := common.BytesToAddress([]byte("so"))
|
||||
{
|
||||
state.SetBalance(addr, big.NewInt(1))
|
||||
@@ -762,7 +762,7 @@ func TestStateDBAccessList(t *testing.T) {
|
||||
|
||||
memDb := rawdb.NewMemoryDatabase()
|
||||
db := NewDatabase(memDb)
|
||||
state, _ := New(common.Hash{}, db, nil)
|
||||
state, _ := New(types.EmptyRootHash, db, nil)
|
||||
state.accessList = newAccessList()
|
||||
|
||||
verifyAddrs := func(astrings ...string) {
|
||||
@@ -932,7 +932,7 @@ func TestFlushOrderDataLoss(t *testing.T) {
|
||||
var (
|
||||
memdb = rawdb.NewMemoryDatabase()
|
||||
statedb = NewDatabase(memdb)
|
||||
state, _ = New(common.Hash{}, statedb, nil)
|
||||
state, _ = New(types.EmptyRootHash, statedb, nil)
|
||||
)
|
||||
for a := byte(0); a < 10; a++ {
|
||||
state.CreateAccount(common.Address{a})
|
||||
@@ -968,7 +968,7 @@ func TestFlushOrderDataLoss(t *testing.T) {
|
||||
func TestStateDBTransientStorage(t *testing.T) {
|
||||
memDb := rawdb.NewMemoryDatabase()
|
||||
db := NewDatabase(memDb)
|
||||
state, _ := New(common.Hash{}, db, nil)
|
||||
state, _ := New(types.EmptyRootHash, db, nil)
|
||||
|
||||
key := common.Hash{0x01}
|
||||
value := common.Hash{0x02}
|
||||
|
||||
@@ -43,7 +43,7 @@ func makeTestState() (ethdb.Database, Database, common.Hash, []*testAccount) {
|
||||
// Create an empty state
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
sdb := NewDatabase(db)
|
||||
state, _ := New(common.Hash{}, sdb, nil)
|
||||
state, _ := New(types.EmptyRootHash, sdb, nil)
|
||||
|
||||
// Fill it with some arbitrary data
|
||||
var accounts []*testAccount
|
||||
@@ -125,7 +125,7 @@ func checkStateConsistency(db ethdb.Database, root common.Hash) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
it := NewNodeIterator(state)
|
||||
it := newNodeIterator(state)
|
||||
for it.Next() {
|
||||
}
|
||||
return it.Error
|
||||
@@ -602,7 +602,8 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||
if len(nodeQueue) > 0 {
|
||||
results := make([]trie.NodeSyncResult, 0, len(nodeQueue))
|
||||
for path, element := range nodeQueue {
|
||||
data, err := srcDb.TrieDB().Node(element.hash)
|
||||
owner, inner := trie.ResolvePath([]byte(element.path))
|
||||
data, err := srcDb.TrieDB().Reader(srcRoot).Node(owner, inner, element.hash)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to retrieve node data for %x", element.hash)
|
||||
}
|
||||
|
||||
@@ -23,10 +23,11 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
func filledStateDB() *StateDB {
|
||||
state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
|
||||
// Create an account and check if the retrieved balance is correct
|
||||
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
||||
|
||||
@@ -53,7 +53,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
|
||||
gaspool = new(GasPool).AddGas(block.GasLimit())
|
||||
blockContext = NewEVMBlockContext(header, p.bc, nil)
|
||||
evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
|
||||
signer = types.MakeSigner(p.config, header.Number)
|
||||
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
||||
)
|
||||
// Iterate over and process the individual transactions
|
||||
byzantium := p.config.IsByzantium(block.Number())
|
||||
|
||||
@@ -70,7 +70,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
||||
misc.ApplyDAOHardFork(statedb)
|
||||
}
|
||||
blockContext := NewEVMBlockContext(header, p.bc, nil)
|
||||
var (
|
||||
context = NewEVMBlockContext(header, p.bc, nil)
|
||||
vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
|
||||
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
||||
)
|
||||
//begin PluGeth code injection
|
||||
blockTracer, ok := pluginGetBlockTracer(header.Hash(), statedb)
|
||||
if ok {
|
||||
@@ -85,7 +89,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
// end PluGeth code injection
|
||||
// Iterate over and process the individual transactions
|
||||
for i, tx := range block.Transactions() {
|
||||
msg, err := TransactionToMessage(tx, types.MakeSigner(p.config, header.Number), header.BaseFee)
|
||||
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
||||
if err != nil {
|
||||
// begin PluGeth injection
|
||||
pluginBlockProcessingError(tx, block, err)
|
||||
@@ -115,15 +119,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
}
|
||||
// Fail if Shanghai not enabled and len(withdrawals) is non-zero.
|
||||
withdrawals := block.Withdrawals()
|
||||
if len(withdrawals) > 0 && !p.config.IsShanghai(block.Time()) {
|
||||
if len(withdrawals) > 0 && !p.config.IsShanghai(block.Number(), block.Time()) {
|
||||
return nil, nil, 0, fmt.Errorf("withdrawals before shanghai")
|
||||
}
|
||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||
p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), withdrawals)
|
||||
// begin PluGeth code injection
|
||||
pluginPostProcessBlock(block)
|
||||
blockTracer.PostProcessBlock(block)
|
||||
// end PluGeth code injection
|
||||
|
||||
return receipts, allLogs, *usedGas, nil
|
||||
}
|
||||
|
||||
@@ -177,7 +178,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
|
||||
// for the transaction, gas used and an error if the transaction failed,
|
||||
// indicating the block was invalid.
|
||||
func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) {
|
||||
msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number), header.BaseFee)
|
||||
msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -403,7 +403,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
|
||||
if config.IsLondon(header.Number) {
|
||||
header.BaseFee = misc.CalcBaseFee(config, parent.Header())
|
||||
}
|
||||
if config.IsShanghai(header.Time) {
|
||||
if config.IsShanghai(header.Number, header.Time) {
|
||||
header.WithdrawalsHash = &types.EmptyWithdrawalsHash
|
||||
}
|
||||
var receipts []*types.Receipt
|
||||
@@ -423,7 +423,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
|
||||
}
|
||||
header.Root = common.BytesToHash(hasher.Sum(nil))
|
||||
// Assemble and return the final block for sealing
|
||||
if config.IsShanghai(header.Time) {
|
||||
if config.IsShanghai(header.Number, header.Time) {
|
||||
return types.NewBlockWithWithdrawals(header, txs, nil, receipts, []*types.Withdrawal{}, trie.NewStackTrie(nil))
|
||||
}
|
||||
return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil))
|
||||
|
||||
@@ -549,7 +549,7 @@ func (pool *TxPool) Pending(enforceTips bool) map[common.Address]types.Transacti
|
||||
pool.mu.Lock()
|
||||
defer pool.mu.Unlock()
|
||||
|
||||
pending := make(map[common.Address]types.Transactions)
|
||||
pending := make(map[common.Address]types.Transactions, len(pool.pending))
|
||||
for addr, list := range pool.pending {
|
||||
txs := list.Flatten()
|
||||
|
||||
@@ -606,6 +606,10 @@ func (pool *TxPool) validateTxBasics(tx *types.Transaction, local bool) error {
|
||||
if !pool.eip1559.Load() && tx.Type() == types.DynamicFeeTxType {
|
||||
return core.ErrTxTypeNotSupported
|
||||
}
|
||||
// Reject blob transactions forever, those will have their own pool.
|
||||
if tx.Type() == types.BlobTxType {
|
||||
return core.ErrTxTypeNotSupported
|
||||
}
|
||||
// Reject transactions over defined size to prevent DOS attacks
|
||||
if tx.Size() > txMaxSize {
|
||||
return ErrOversizedData
|
||||
@@ -1393,7 +1397,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
|
||||
pool.istanbul.Store(pool.chainconfig.IsIstanbul(next))
|
||||
pool.eip2718.Store(pool.chainconfig.IsBerlin(next))
|
||||
pool.eip1559.Store(pool.chainconfig.IsLondon(next))
|
||||
pool.shanghai.Store(pool.chainconfig.IsShanghai(uint64(time.Now().Unix())))
|
||||
pool.shanghai.Store(pool.chainconfig.IsShanghai(next, uint64(time.Now().Unix())))
|
||||
}
|
||||
|
||||
// promoteExecutables moves transactions that have become processable from the
|
||||
|
||||
@@ -78,7 +78,7 @@ func TestTransactionFutureAttack(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the limit enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
config := testTxPoolConfig
|
||||
config.GlobalQueue = 100
|
||||
@@ -114,7 +114,7 @@ func TestTransactionFutureAttack(t *testing.T) {
|
||||
func TestTransactionFuture1559(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Create the pool to test the pricing enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
pool := NewTxPool(testTxPoolConfig, eip1559Config, blockchain)
|
||||
defer pool.Stop()
|
||||
@@ -146,7 +146,7 @@ func TestTransactionFuture1559(t *testing.T) {
|
||||
func TestTransactionZAttack(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Create the pool to test the pricing enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
pool := NewTxPool(testTxPoolConfig, eip1559Config, blockchain)
|
||||
defer pool.Stop()
|
||||
@@ -213,7 +213,7 @@ func TestTransactionZAttack(t *testing.T) {
|
||||
|
||||
func BenchmarkFutureAttack(b *testing.B) {
|
||||
// Create the pool to test the limit enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
config := testTxPoolConfig
|
||||
config.GlobalQueue = 100
|
||||
|
||||
+19
-19
@@ -126,7 +126,7 @@ func setupPool() (*TxPool, *ecdsa.PrivateKey) {
|
||||
}
|
||||
|
||||
func setupPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateKey) {
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(10000000, statedb, new(event.Feed))
|
||||
|
||||
key, _ := crypto.GenerateKey()
|
||||
@@ -218,7 +218,7 @@ func (c *testChain) State() (*state.StateDB, error) {
|
||||
// a state change between those fetches.
|
||||
stdb := c.statedb
|
||||
if *c.trigger {
|
||||
c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
c.statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
// simulate that the new head block included tx0 and tx1
|
||||
c.statedb.SetNonce(c.address, 2)
|
||||
c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Ether))
|
||||
@@ -236,7 +236,7 @@ func TestStateChangeDuringReset(t *testing.T) {
|
||||
var (
|
||||
key, _ = crypto.GenerateKey()
|
||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||
statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
trigger = false
|
||||
)
|
||||
|
||||
@@ -434,7 +434,7 @@ func TestChainFork(t *testing.T) {
|
||||
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
resetState := func() {
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb.AddBalance(addr, big.NewInt(100000000000000))
|
||||
|
||||
pool.chain = newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
@@ -463,7 +463,7 @@ func TestDoubleNonce(t *testing.T) {
|
||||
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
resetState := func() {
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb.AddBalance(addr, big.NewInt(100000000000000))
|
||||
|
||||
pool.chain = newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
@@ -663,7 +663,7 @@ func TestPostponing(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the postponing with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
|
||||
@@ -875,7 +875,7 @@ func testQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the limit enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
config := testTxPoolConfig
|
||||
@@ -967,7 +967,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||
evictionInterval = time.Millisecond * 100
|
||||
|
||||
// Create the pool to test the non-expiration enforcement
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
config := testTxPoolConfig
|
||||
@@ -1152,7 +1152,7 @@ func TestPendingGlobalLimiting(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the limit enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
config := testTxPoolConfig
|
||||
@@ -1254,7 +1254,7 @@ func TestCapClearsFromAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the limit enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
config := testTxPoolConfig
|
||||
@@ -1288,7 +1288,7 @@ func TestPendingMinimumAllowance(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the limit enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
config := testTxPoolConfig
|
||||
@@ -1336,7 +1336,7 @@ func TestRepricing(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the pricing enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
|
||||
@@ -1584,7 +1584,7 @@ func TestRepricingKeepsLocals(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the pricing enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := NewTxPool(testTxPoolConfig, eip1559Config, blockchain)
|
||||
@@ -1657,7 +1657,7 @@ func TestUnderpricing(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the pricing enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
config := testTxPoolConfig
|
||||
@@ -1771,7 +1771,7 @@ func TestStableUnderpricing(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the pricing enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
config := testTxPoolConfig
|
||||
@@ -2003,7 +2003,7 @@ func TestDeduplication(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the pricing enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
|
||||
@@ -2069,7 +2069,7 @@ func TestReplacement(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the pricing enforcement with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
|
||||
@@ -2274,7 +2274,7 @@ func testJournaling(t *testing.T, nolocals bool) {
|
||||
os.Remove(journal)
|
||||
|
||||
// Create the original pool to inject transaction into the journal
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
config := testTxPoolConfig
|
||||
@@ -2372,7 +2372,7 @@ func TestStatusCheck(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create the pool to test the status retrievals with
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
// MarshalJSON marshals as JSON.
|
||||
func (a AccessTuple) MarshalJSON() ([]byte, error) {
|
||||
type AccessTuple struct {
|
||||
Address common.Address `json:"address" gencodec:"required"`
|
||||
StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"`
|
||||
Address common.Address `json:"address" gencodec:"required"`
|
||||
StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"`
|
||||
}
|
||||
var enc AccessTuple
|
||||
enc.Address = a.Address
|
||||
@@ -24,8 +24,8 @@ func (a AccessTuple) MarshalJSON() ([]byte, error) {
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (a *AccessTuple) UnmarshalJSON(input []byte) error {
|
||||
type AccessTuple struct {
|
||||
Address *common.Address `json:"address" gencodec:"required"`
|
||||
StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"`
|
||||
Address *common.Address `json:"address" gencodec:"required"`
|
||||
StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"`
|
||||
}
|
||||
var dec AccessTuple
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
||||
@@ -33,6 +33,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
||||
Nonce BlockNonce `json:"nonce"`
|
||||
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
|
||||
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
||||
ExcessDataGas *big.Int `json:"excessDataGas" rlp:"optional"`
|
||||
Hash common.Hash `json:"hash"`
|
||||
}
|
||||
var enc Header
|
||||
@@ -53,6 +54,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
||||
enc.Nonce = h.Nonce
|
||||
enc.BaseFee = (*hexutil.Big)(h.BaseFee)
|
||||
enc.WithdrawalsHash = h.WithdrawalsHash
|
||||
enc.ExcessDataGas = h.ExcessDataGas
|
||||
enc.Hash = h.Hash()
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
@@ -77,6 +79,7 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
||||
Nonce *BlockNonce `json:"nonce"`
|
||||
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
|
||||
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
|
||||
ExcessDataGas *big.Int `json:"excessDataGas" rlp:"optional"`
|
||||
}
|
||||
var dec Header
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
@@ -145,5 +148,8 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
||||
if dec.WithdrawalsHash != nil {
|
||||
h.WithdrawalsHash = dec.WithdrawalsHash
|
||||
}
|
||||
if dec.ExcessDataGas != nil {
|
||||
h.ExcessDataGas = dec.ExcessDataGas
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
||||
w.WriteBytes(obj.Nonce[:])
|
||||
_tmp1 := obj.BaseFee != nil
|
||||
_tmp2 := obj.WithdrawalsHash != nil
|
||||
if _tmp1 || _tmp2 {
|
||||
_tmp3 := obj.ExcessDataGas != nil
|
||||
if _tmp1 || _tmp2 || _tmp3 {
|
||||
if obj.BaseFee == nil {
|
||||
w.Write(rlp.EmptyString)
|
||||
} else {
|
||||
@@ -52,13 +53,23 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
||||
w.WriteBigInt(obj.BaseFee)
|
||||
}
|
||||
}
|
||||
if _tmp2 {
|
||||
if _tmp2 || _tmp3 {
|
||||
if obj.WithdrawalsHash == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteBytes(obj.WithdrawalsHash[:])
|
||||
}
|
||||
}
|
||||
if _tmp3 {
|
||||
if obj.ExcessDataGas == nil {
|
||||
w.Write(rlp.EmptyString)
|
||||
} else {
|
||||
if obj.ExcessDataGas.Sign() == -1 {
|
||||
return rlp.ErrNegativeBigInt
|
||||
}
|
||||
w.WriteBigInt(obj.ExcessDataGas)
|
||||
}
|
||||
}
|
||||
w.ListEnd(_tmp0)
|
||||
return w.Flush()
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
|
||||
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
|
||||
ContractAddress common.Address `json:"contractAddress"`
|
||||
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
||||
EffectiveGasPrice *hexutil.Big `json:"effectiveGasPrice,omitempty"`
|
||||
EffectiveGasPrice *hexutil.Big `json:"effectiveGasPrice"`
|
||||
BlockHash common.Hash `json:"blockHash,omitempty"`
|
||||
BlockNumber *hexutil.Big `json:"blockNumber,omitempty"`
|
||||
TransactionIndex hexutil.Uint `json:"transactionIndex"`
|
||||
@@ -59,7 +59,7 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
|
||||
TxHash *common.Hash `json:"transactionHash" gencodec:"required"`
|
||||
ContractAddress *common.Address `json:"contractAddress"`
|
||||
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
||||
EffectiveGasPrice *hexutil.Big `json:"effectiveGasPrice,omitempty"`
|
||||
EffectiveGasPrice *hexutil.Big `json:"effectiveGasPrice"`
|
||||
BlockHash *common.Hash `json:"blockHash,omitempty"`
|
||||
BlockNumber *hexutil.Big `json:"blockNumber,omitempty"`
|
||||
TransactionIndex *hexutil.Uint `json:"transactionIndex"`
|
||||
|
||||
@@ -62,7 +62,7 @@ type Receipt struct {
|
||||
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
|
||||
ContractAddress common.Address `json:"contractAddress"`
|
||||
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
|
||||
EffectiveGasPrice *big.Int `json:"effectiveGasPrice"`
|
||||
EffectiveGasPrice *big.Int `json:"effectiveGasPrice"` // required, but tag omitted for backwards compatibility
|
||||
|
||||
// Inclusion information: These fields provide information about the inclusion of the
|
||||
// transaction corresponding to this receipt.
|
||||
@@ -77,6 +77,7 @@ type receiptMarshaling struct {
|
||||
Status hexutil.Uint64
|
||||
CumulativeGasUsed hexutil.Uint64
|
||||
GasUsed hexutil.Uint64
|
||||
EffectiveGasPrice *hexutil.Big
|
||||
BlockNumber *hexutil.Big
|
||||
TransactionIndex hexutil.Uint
|
||||
}
|
||||
@@ -313,8 +314,8 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) {
|
||||
|
||||
// DeriveFields fills the receipts with their computed fields based on consensus
|
||||
// data and contextual infos like containing block and transactions.
|
||||
func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, baseFee *big.Int, txs []*Transaction) error {
|
||||
signer := MakeSigner(config, new(big.Int).SetUint64(number))
|
||||
func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, baseFee *big.Int, txs []*Transaction) error {
|
||||
signer := MakeSigner(config, new(big.Int).SetUint64(number), time)
|
||||
|
||||
logIndex := uint(0)
|
||||
if len(txs) != len(rs) {
|
||||
|
||||
+109
-23
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/kylelemons/godebug/diff"
|
||||
)
|
||||
|
||||
@@ -81,25 +82,15 @@ var (
|
||||
},
|
||||
Type: DynamicFeeTxType,
|
||||
}
|
||||
)
|
||||
|
||||
func TestDecodeEmptyTypedReceipt(t *testing.T) {
|
||||
input := []byte{0x80}
|
||||
var r Receipt
|
||||
err := rlp.DecodeBytes(input, &r)
|
||||
if err != errShortTypedReceipt {
|
||||
t.Fatal("wrong error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that receipt data can be correctly derived from the contextual infos
|
||||
func TestDeriveFields(t *testing.T) {
|
||||
// Create a few transactions to have receipts for
|
||||
to2 := common.HexToAddress("0x2")
|
||||
to3 := common.HexToAddress("0x3")
|
||||
to4 := common.HexToAddress("0x4")
|
||||
to5 := common.HexToAddress("0x5")
|
||||
txs := Transactions{
|
||||
to2 = common.HexToAddress("0x2")
|
||||
to3 = common.HexToAddress("0x3")
|
||||
to4 = common.HexToAddress("0x4")
|
||||
to5 = common.HexToAddress("0x5")
|
||||
to6 = common.HexToAddress("0x6")
|
||||
to7 = common.HexToAddress("0x7")
|
||||
txs = Transactions{
|
||||
NewTx(&LegacyTx{
|
||||
Nonce: 1,
|
||||
Value: big.NewInt(1),
|
||||
@@ -127,29 +118,50 @@ func TestDeriveFields(t *testing.T) {
|
||||
Value: big.NewInt(4),
|
||||
Gas: 4,
|
||||
GasTipCap: big.NewInt(44),
|
||||
GasFeeCap: big.NewInt(1045),
|
||||
GasFeeCap: big.NewInt(1044),
|
||||
}),
|
||||
NewTx(&DynamicFeeTx{
|
||||
To: &to5,
|
||||
Nonce: 5,
|
||||
Value: big.NewInt(5),
|
||||
Gas: 5,
|
||||
GasTipCap: big.NewInt(56),
|
||||
GasTipCap: big.NewInt(55),
|
||||
GasFeeCap: big.NewInt(1055),
|
||||
}),
|
||||
// EIP-4844 transactions.
|
||||
NewTx(&BlobTx{
|
||||
To: &to6,
|
||||
Nonce: 6,
|
||||
Value: uint256.NewInt(6),
|
||||
Gas: 6,
|
||||
GasTipCap: uint256.NewInt(66),
|
||||
GasFeeCap: uint256.NewInt(1066),
|
||||
BlobFeeCap: uint256.NewInt(100066),
|
||||
}),
|
||||
NewTx(&BlobTx{
|
||||
To: &to7,
|
||||
Nonce: 7,
|
||||
Value: uint256.NewInt(7),
|
||||
Gas: 7,
|
||||
GasTipCap: uint256.NewInt(77),
|
||||
GasFeeCap: uint256.NewInt(1077),
|
||||
BlobFeeCap: uint256.NewInt(100077),
|
||||
}),
|
||||
}
|
||||
|
||||
blockNumber := big.NewInt(1)
|
||||
blockHash := common.BytesToHash([]byte{0x03, 0x14})
|
||||
blockNumber = big.NewInt(1)
|
||||
blockTime = uint64(2)
|
||||
blockHash = common.BytesToHash([]byte{0x03, 0x14})
|
||||
|
||||
// Create the corresponding receipts
|
||||
receipts := Receipts{
|
||||
receipts = Receipts{
|
||||
&Receipt{
|
||||
Status: ReceiptStatusFailed,
|
||||
CumulativeGasUsed: 1,
|
||||
Logs: []*Log{
|
||||
{
|
||||
Address: common.BytesToAddress([]byte{0x11}),
|
||||
Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")},
|
||||
// derived fields:
|
||||
BlockNumber: blockNumber.Uint64(),
|
||||
TxHash: txs[0].Hash(),
|
||||
@@ -159,6 +171,7 @@ func TestDeriveFields(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Address: common.BytesToAddress([]byte{0x01, 0x11}),
|
||||
Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")},
|
||||
// derived fields:
|
||||
BlockNumber: blockNumber.Uint64(),
|
||||
TxHash: txs[0].Hash(),
|
||||
@@ -182,6 +195,7 @@ func TestDeriveFields(t *testing.T) {
|
||||
Logs: []*Log{
|
||||
{
|
||||
Address: common.BytesToAddress([]byte{0x22}),
|
||||
Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")},
|
||||
// derived fields:
|
||||
BlockNumber: blockNumber.Uint64(),
|
||||
TxHash: txs[1].Hash(),
|
||||
@@ -191,6 +205,7 @@ func TestDeriveFields(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Address: common.BytesToAddress([]byte{0x02, 0x22}),
|
||||
Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")},
|
||||
// derived fields:
|
||||
BlockNumber: blockNumber.Uint64(),
|
||||
TxHash: txs[1].Hash(),
|
||||
@@ -246,12 +261,50 @@ func TestDeriveFields(t *testing.T) {
|
||||
BlockNumber: blockNumber,
|
||||
TransactionIndex: 4,
|
||||
},
|
||||
&Receipt{
|
||||
Type: BlobTxType,
|
||||
PostState: common.Hash{6}.Bytes(),
|
||||
CumulativeGasUsed: 21,
|
||||
Logs: []*Log{},
|
||||
// derived fields:
|
||||
TxHash: txs[5].Hash(),
|
||||
GasUsed: 6,
|
||||
EffectiveGasPrice: big.NewInt(1066),
|
||||
BlockHash: blockHash,
|
||||
BlockNumber: blockNumber,
|
||||
TransactionIndex: 5,
|
||||
},
|
||||
&Receipt{
|
||||
Type: BlobTxType,
|
||||
PostState: common.Hash{7}.Bytes(),
|
||||
CumulativeGasUsed: 28,
|
||||
Logs: []*Log{},
|
||||
// derived fields:
|
||||
TxHash: txs[6].Hash(),
|
||||
GasUsed: 7,
|
||||
EffectiveGasPrice: big.NewInt(1077),
|
||||
BlockHash: blockHash,
|
||||
BlockNumber: blockNumber,
|
||||
TransactionIndex: 6,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func TestDecodeEmptyTypedReceipt(t *testing.T) {
|
||||
input := []byte{0x80}
|
||||
var r Receipt
|
||||
err := rlp.DecodeBytes(input, &r)
|
||||
if err != errShortTypedReceipt {
|
||||
t.Fatal("wrong error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that receipt data can be correctly derived from the contextual infos
|
||||
func TestDeriveFields(t *testing.T) {
|
||||
// Re-derive receipts.
|
||||
basefee := big.NewInt(1000)
|
||||
derivedReceipts := clearComputedFieldsOnReceipts(receipts)
|
||||
err := Receipts(derivedReceipts).DeriveFields(params.TestChainConfig, blockHash, blockNumber.Uint64(), basefee, txs)
|
||||
err := Receipts(derivedReceipts).DeriveFields(params.TestChainConfig, blockHash, blockNumber.Uint64(), blockTime, basefee, txs)
|
||||
if err != nil {
|
||||
t.Fatalf("DeriveFields(...) = %v, want <nil>", err)
|
||||
}
|
||||
@@ -261,6 +314,7 @@ func TestDeriveFields(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal("error marshaling input receipts:", err)
|
||||
}
|
||||
|
||||
r2, err := json.MarshalIndent(derivedReceipts, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal("error marshaling derived receipts:", err)
|
||||
@@ -271,6 +325,38 @@ func TestDeriveFields(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test that we can marshal/unmarshal receipts to/from json without errors.
|
||||
// This also confirms that our test receipts contain all the required fields.
|
||||
func TestReceiptJSON(t *testing.T) {
|
||||
for i := range receipts {
|
||||
b, err := receipts[i].MarshalJSON()
|
||||
if err != nil {
|
||||
t.Fatal("error marshaling receipt to json:", err)
|
||||
}
|
||||
r := Receipt{}
|
||||
err = r.UnmarshalJSON(b)
|
||||
if err != nil {
|
||||
t.Fatal("error unmarshaling receipt from json:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test we can still parse receipt without EffectiveGasPrice for backwards compatibility, even
|
||||
// though it is required per the spec.
|
||||
func TestEffectiveGasPriceNotRequired(t *testing.T) {
|
||||
r := *receipts[0]
|
||||
r.EffectiveGasPrice = nil
|
||||
b, err := r.MarshalJSON()
|
||||
if err != nil {
|
||||
t.Fatal("error marshaling receipt to json:", err)
|
||||
}
|
||||
r2 := Receipt{}
|
||||
err = r2.UnmarshalJSON(b)
|
||||
if err != nil {
|
||||
t.Fatal("error unmarshaling receipt from json:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestTypedReceiptEncodingDecoding reproduces a flaw that existed in the receipt
|
||||
// rlp decoder, which failed due to a shadowing error.
|
||||
func TestTypedReceiptEncodingDecoding(t *testing.T) {
|
||||
|
||||
@@ -42,9 +42,10 @@ var (
|
||||
|
||||
// Transaction types.
|
||||
const (
|
||||
LegacyTxType = iota
|
||||
AccessListTxType
|
||||
DynamicFeeTxType
|
||||
LegacyTxType = 0x00
|
||||
AccessListTxType = 0x01
|
||||
DynamicFeeTxType = 0x02
|
||||
BlobTxType = 0x03
|
||||
)
|
||||
|
||||
// Transaction is an Ethereum transaction.
|
||||
@@ -82,6 +83,9 @@ type TxData interface {
|
||||
value() *big.Int
|
||||
nonce() uint64
|
||||
to() *common.Address
|
||||
blobGas() uint64
|
||||
blobGasFeeCap() *big.Int
|
||||
blobHashes() []common.Hash
|
||||
|
||||
rawSignatureValues() (v, r, s *big.Int)
|
||||
setSignatureValues(chainID, v, r, s *big.Int)
|
||||
@@ -192,6 +196,10 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
|
||||
var inner DynamicFeeTx
|
||||
err := rlp.DecodeBytes(b[1:], &inner)
|
||||
return &inner, err
|
||||
case BlobTxType:
|
||||
var inner BlobTx
|
||||
err := rlp.DecodeBytes(b[1:], &inner)
|
||||
return &inner, err
|
||||
default:
|
||||
return nil, ErrTxTypeNotSupported
|
||||
}
|
||||
@@ -281,6 +289,15 @@ func (tx *Transaction) GasTipCap() *big.Int { return new(big.Int).Set(tx.inner.g
|
||||
// GasFeeCap returns the fee cap per gas of the transaction.
|
||||
func (tx *Transaction) GasFeeCap() *big.Int { return new(big.Int).Set(tx.inner.gasFeeCap()) }
|
||||
|
||||
// BlobGas returns the data gas limit of the transaction for blob transactions, 0 otherwise.
|
||||
func (tx *Transaction) BlobGas() uint64 { return tx.inner.blobGas() }
|
||||
|
||||
// BlobGasFeeCap returns the data gas fee cap per data gas of the transaction for blob transactions, nil otherwise.
|
||||
func (tx *Transaction) BlobGasFeeCap() *big.Int { return tx.inner.blobGasFeeCap() }
|
||||
|
||||
// BlobHashes returns the hases of the blob commitments for blob transactions, nil otherwise.
|
||||
func (tx *Transaction) BlobHashes() []common.Hash { return tx.inner.blobHashes() }
|
||||
|
||||
// Value returns the ether amount of the transaction.
|
||||
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.inner.value()) }
|
||||
|
||||
@@ -293,9 +310,12 @@ func (tx *Transaction) To() *common.Address {
|
||||
return copyAddressPtr(tx.inner.to())
|
||||
}
|
||||
|
||||
// Cost returns gas * gasPrice + value.
|
||||
// Cost returns (gas * gasPrice) + (blobGas * blobGasPrice) + value.
|
||||
func (tx *Transaction) Cost() *big.Int {
|
||||
total := new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas()))
|
||||
if tx.Type() == BlobTxType {
|
||||
total.Add(total, new(big.Int).Mul(tx.BlobGasFeeCap(), new(big.Int).SetUint64(tx.BlobGas())))
|
||||
}
|
||||
total.Add(total, tx.Value())
|
||||
return total
|
||||
}
|
||||
@@ -364,6 +384,16 @@ func (tx *Transaction) EffectiveGasTipIntCmp(other *big.Int, baseFee *big.Int) i
|
||||
return tx.EffectiveGasTipValue(baseFee).Cmp(other)
|
||||
}
|
||||
|
||||
// BlobGasFeeCapCmp compares the blob fee cap of two transactions.
|
||||
func (tx *Transaction) BlobGasFeeCapCmp(other *Transaction) int {
|
||||
return tx.inner.blobGasFeeCap().Cmp(other.inner.blobGasFeeCap())
|
||||
}
|
||||
|
||||
// BlobGasFeeCapIntCmp compares the blob fee cap of the transaction against the given blob fee cap.
|
||||
func (tx *Transaction) BlobGasFeeCapIntCmp(other *big.Int) int {
|
||||
return tx.inner.blobGasFeeCap().Cmp(other)
|
||||
}
|
||||
|
||||
// Hash returns the transaction hash.
|
||||
func (tx *Transaction) Hash() common.Hash {
|
||||
if hash := tx.hash.Load(); hash != nil {
|
||||
|
||||
@@ -23,28 +23,28 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// txJSON is the JSON representation of transactions.
|
||||
type txJSON struct {
|
||||
Type hexutil.Uint64 `json:"type"`
|
||||
|
||||
// Common transaction fields:
|
||||
ChainID *hexutil.Big `json:"chainId,omitempty"`
|
||||
Nonce *hexutil.Uint64 `json:"nonce"`
|
||||
To *common.Address `json:"to"`
|
||||
Gas *hexutil.Uint64 `json:"gas"`
|
||||
GasPrice *hexutil.Big `json:"gasPrice"`
|
||||
MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
|
||||
MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
|
||||
Gas *hexutil.Uint64 `json:"gas"`
|
||||
MaxFeePerDataGas *hexutil.Big `json:"maxFeePerDataGas,omitempty"`
|
||||
Value *hexutil.Big `json:"value"`
|
||||
Data *hexutil.Bytes `json:"input"`
|
||||
Input *hexutil.Bytes `json:"input"`
|
||||
AccessList *AccessList `json:"accessList,omitempty"`
|
||||
BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
|
||||
V *hexutil.Big `json:"v"`
|
||||
R *hexutil.Big `json:"r"`
|
||||
S *hexutil.Big `json:"s"`
|
||||
To *common.Address `json:"to"`
|
||||
|
||||
// Access list transaction fields:
|
||||
ChainID *hexutil.Big `json:"chainId,omitempty"`
|
||||
AccessList *AccessList `json:"accessList,omitempty"`
|
||||
|
||||
// Only used for encoding:
|
||||
Hash common.Hash `json:"hash"`
|
||||
@@ -61,39 +61,57 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
|
||||
switch itx := tx.inner.(type) {
|
||||
case *LegacyTx:
|
||||
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
|
||||
enc.To = tx.To()
|
||||
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
|
||||
enc.GasPrice = (*hexutil.Big)(itx.GasPrice)
|
||||
enc.Value = (*hexutil.Big)(itx.Value)
|
||||
enc.Data = (*hexutil.Bytes)(&itx.Data)
|
||||
enc.To = tx.To()
|
||||
enc.Input = (*hexutil.Bytes)(&itx.Data)
|
||||
enc.V = (*hexutil.Big)(itx.V)
|
||||
enc.R = (*hexutil.Big)(itx.R)
|
||||
enc.S = (*hexutil.Big)(itx.S)
|
||||
|
||||
case *AccessListTx:
|
||||
enc.ChainID = (*hexutil.Big)(itx.ChainID)
|
||||
enc.AccessList = &itx.AccessList
|
||||
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
|
||||
enc.To = tx.To()
|
||||
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
|
||||
enc.GasPrice = (*hexutil.Big)(itx.GasPrice)
|
||||
enc.Value = (*hexutil.Big)(itx.Value)
|
||||
enc.Data = (*hexutil.Bytes)(&itx.Data)
|
||||
enc.To = tx.To()
|
||||
enc.Input = (*hexutil.Bytes)(&itx.Data)
|
||||
enc.AccessList = &itx.AccessList
|
||||
enc.V = (*hexutil.Big)(itx.V)
|
||||
enc.R = (*hexutil.Big)(itx.R)
|
||||
enc.S = (*hexutil.Big)(itx.S)
|
||||
|
||||
case *DynamicFeeTx:
|
||||
enc.ChainID = (*hexutil.Big)(itx.ChainID)
|
||||
enc.AccessList = &itx.AccessList
|
||||
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
|
||||
enc.To = tx.To()
|
||||
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
|
||||
enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap)
|
||||
enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap)
|
||||
enc.Value = (*hexutil.Big)(itx.Value)
|
||||
enc.Data = (*hexutil.Bytes)(&itx.Data)
|
||||
enc.To = tx.To()
|
||||
enc.Input = (*hexutil.Bytes)(&itx.Data)
|
||||
enc.AccessList = &itx.AccessList
|
||||
enc.V = (*hexutil.Big)(itx.V)
|
||||
enc.R = (*hexutil.Big)(itx.R)
|
||||
enc.S = (*hexutil.Big)(itx.S)
|
||||
|
||||
case *BlobTx:
|
||||
enc.ChainID = (*hexutil.Big)(itx.ChainID.ToBig())
|
||||
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
|
||||
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
|
||||
enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap.ToBig())
|
||||
enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap.ToBig())
|
||||
enc.MaxFeePerDataGas = (*hexutil.Big)(itx.BlobFeeCap.ToBig())
|
||||
enc.Value = (*hexutil.Big)(itx.Value.ToBig())
|
||||
enc.Input = (*hexutil.Bytes)(&itx.Data)
|
||||
enc.AccessList = &itx.AccessList
|
||||
enc.BlobVersionedHashes = itx.BlobHashes
|
||||
enc.To = tx.To()
|
||||
enc.V = (*hexutil.Big)(itx.V.ToBig())
|
||||
enc.R = (*hexutil.Big)(itx.R.ToBig())
|
||||
enc.S = (*hexutil.Big)(itx.S.ToBig())
|
||||
}
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
@@ -111,29 +129,29 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||
case LegacyTxType:
|
||||
var itx LegacyTx
|
||||
inner = &itx
|
||||
if dec.To != nil {
|
||||
itx.To = dec.To
|
||||
}
|
||||
if dec.Nonce == nil {
|
||||
return errors.New("missing required field 'nonce' in transaction")
|
||||
}
|
||||
itx.Nonce = uint64(*dec.Nonce)
|
||||
if dec.GasPrice == nil {
|
||||
return errors.New("missing required field 'gasPrice' in transaction")
|
||||
if dec.To != nil {
|
||||
itx.To = dec.To
|
||||
}
|
||||
itx.GasPrice = (*big.Int)(dec.GasPrice)
|
||||
if dec.Gas == nil {
|
||||
return errors.New("missing required field 'gas' in transaction")
|
||||
}
|
||||
itx.Gas = uint64(*dec.Gas)
|
||||
if dec.GasPrice == nil {
|
||||
return errors.New("missing required field 'gasPrice' in transaction")
|
||||
}
|
||||
itx.GasPrice = (*big.Int)(dec.GasPrice)
|
||||
if dec.Value == nil {
|
||||
return errors.New("missing required field 'value' in transaction")
|
||||
}
|
||||
itx.Value = (*big.Int)(dec.Value)
|
||||
if dec.Data == nil {
|
||||
if dec.Input == nil {
|
||||
return errors.New("missing required field 'input' in transaction")
|
||||
}
|
||||
itx.Data = *dec.Data
|
||||
itx.Data = *dec.Input
|
||||
if dec.V == nil {
|
||||
return errors.New("missing required field 'v' in transaction")
|
||||
}
|
||||
@@ -156,40 +174,39 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||
case AccessListTxType:
|
||||
var itx AccessListTx
|
||||
inner = &itx
|
||||
// Access list is optional for now.
|
||||
if dec.AccessList != nil {
|
||||
itx.AccessList = *dec.AccessList
|
||||
}
|
||||
if dec.ChainID == nil {
|
||||
return errors.New("missing required field 'chainId' in transaction")
|
||||
}
|
||||
itx.ChainID = (*big.Int)(dec.ChainID)
|
||||
if dec.To != nil {
|
||||
itx.To = dec.To
|
||||
}
|
||||
if dec.Nonce == nil {
|
||||
return errors.New("missing required field 'nonce' in transaction")
|
||||
}
|
||||
itx.Nonce = uint64(*dec.Nonce)
|
||||
if dec.GasPrice == nil {
|
||||
return errors.New("missing required field 'gasPrice' in transaction")
|
||||
if dec.To != nil {
|
||||
itx.To = dec.To
|
||||
}
|
||||
itx.GasPrice = (*big.Int)(dec.GasPrice)
|
||||
if dec.Gas == nil {
|
||||
return errors.New("missing required field 'gas' in transaction")
|
||||
}
|
||||
itx.Gas = uint64(*dec.Gas)
|
||||
if dec.GasPrice == nil {
|
||||
return errors.New("missing required field 'gasPrice' in transaction")
|
||||
}
|
||||
itx.GasPrice = (*big.Int)(dec.GasPrice)
|
||||
if dec.Value == nil {
|
||||
return errors.New("missing required field 'value' in transaction")
|
||||
}
|
||||
itx.Value = (*big.Int)(dec.Value)
|
||||
if dec.Data == nil {
|
||||
if dec.Input == nil {
|
||||
return errors.New("missing required field 'input' in transaction")
|
||||
}
|
||||
itx.Data = *dec.Data
|
||||
itx.Data = *dec.Input
|
||||
if dec.V == nil {
|
||||
return errors.New("missing required field 'v' in transaction")
|
||||
}
|
||||
if dec.AccessList != nil {
|
||||
itx.AccessList = *dec.AccessList
|
||||
}
|
||||
itx.V = (*big.Int)(dec.V)
|
||||
if dec.R == nil {
|
||||
return errors.New("missing required field 'r' in transaction")
|
||||
@@ -209,21 +226,21 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||
case DynamicFeeTxType:
|
||||
var itx DynamicFeeTx
|
||||
inner = &itx
|
||||
// Access list is optional for now.
|
||||
if dec.AccessList != nil {
|
||||
itx.AccessList = *dec.AccessList
|
||||
}
|
||||
if dec.ChainID == nil {
|
||||
return errors.New("missing required field 'chainId' in transaction")
|
||||
}
|
||||
itx.ChainID = (*big.Int)(dec.ChainID)
|
||||
if dec.To != nil {
|
||||
itx.To = dec.To
|
||||
}
|
||||
if dec.Nonce == nil {
|
||||
return errors.New("missing required field 'nonce' in transaction")
|
||||
}
|
||||
itx.Nonce = uint64(*dec.Nonce)
|
||||
if dec.To != nil {
|
||||
itx.To = dec.To
|
||||
}
|
||||
if dec.Gas == nil {
|
||||
return errors.New("missing required field 'gas' for txdata")
|
||||
}
|
||||
itx.Gas = uint64(*dec.Gas)
|
||||
if dec.MaxPriorityFeePerGas == nil {
|
||||
return errors.New("missing required field 'maxPriorityFeePerGas' for txdata")
|
||||
}
|
||||
@@ -232,21 +249,20 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||
return errors.New("missing required field 'maxFeePerGas' for txdata")
|
||||
}
|
||||
itx.GasFeeCap = (*big.Int)(dec.MaxFeePerGas)
|
||||
if dec.Gas == nil {
|
||||
return errors.New("missing required field 'gas' for txdata")
|
||||
}
|
||||
itx.Gas = uint64(*dec.Gas)
|
||||
if dec.Value == nil {
|
||||
return errors.New("missing required field 'value' in transaction")
|
||||
}
|
||||
itx.Value = (*big.Int)(dec.Value)
|
||||
if dec.Data == nil {
|
||||
if dec.Input == nil {
|
||||
return errors.New("missing required field 'input' in transaction")
|
||||
}
|
||||
itx.Data = *dec.Data
|
||||
itx.Data = *dec.Input
|
||||
if dec.V == nil {
|
||||
return errors.New("missing required field 'v' in transaction")
|
||||
}
|
||||
if dec.AccessList != nil {
|
||||
itx.AccessList = *dec.AccessList
|
||||
}
|
||||
itx.V = (*big.Int)(dec.V)
|
||||
if dec.R == nil {
|
||||
return errors.New("missing required field 'r' in transaction")
|
||||
@@ -263,6 +279,70 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||
}
|
||||
}
|
||||
|
||||
case BlobTxType:
|
||||
var itx BlobTx
|
||||
inner = &itx
|
||||
if dec.ChainID == nil {
|
||||
return errors.New("missing required field 'chainId' in transaction")
|
||||
}
|
||||
itx.ChainID = uint256.MustFromBig((*big.Int)(dec.ChainID))
|
||||
if dec.Nonce == nil {
|
||||
return errors.New("missing required field 'nonce' in transaction")
|
||||
}
|
||||
itx.Nonce = uint64(*dec.Nonce)
|
||||
if dec.To != nil {
|
||||
itx.To = dec.To
|
||||
}
|
||||
if dec.Gas == nil {
|
||||
return errors.New("missing required field 'gas' for txdata")
|
||||
}
|
||||
itx.Gas = uint64(*dec.Gas)
|
||||
if dec.MaxPriorityFeePerGas == nil {
|
||||
return errors.New("missing required field 'maxPriorityFeePerGas' for txdata")
|
||||
}
|
||||
itx.GasTipCap = uint256.MustFromBig((*big.Int)(dec.MaxPriorityFeePerGas))
|
||||
if dec.MaxFeePerGas == nil {
|
||||
return errors.New("missing required field 'maxFeePerGas' for txdata")
|
||||
}
|
||||
itx.GasFeeCap = uint256.MustFromBig((*big.Int)(dec.MaxFeePerGas))
|
||||
if dec.MaxFeePerDataGas == nil {
|
||||
return errors.New("missing required field 'maxFeePerDataGas' for txdata")
|
||||
}
|
||||
itx.BlobFeeCap = uint256.MustFromBig((*big.Int)(dec.MaxFeePerDataGas))
|
||||
if dec.Value == nil {
|
||||
return errors.New("missing required field 'value' in transaction")
|
||||
}
|
||||
itx.Value = uint256.MustFromBig((*big.Int)(dec.Value))
|
||||
if dec.Input == nil {
|
||||
return errors.New("missing required field 'input' in transaction")
|
||||
}
|
||||
itx.Data = *dec.Input
|
||||
if dec.V == nil {
|
||||
return errors.New("missing required field 'v' in transaction")
|
||||
}
|
||||
if dec.AccessList != nil {
|
||||
itx.AccessList = *dec.AccessList
|
||||
}
|
||||
if dec.BlobVersionedHashes == nil {
|
||||
return errors.New("missing required field 'blobVersionedHashes' in transaction")
|
||||
}
|
||||
itx.BlobHashes = dec.BlobVersionedHashes
|
||||
itx.V = uint256.MustFromBig((*big.Int)(dec.V))
|
||||
if dec.R == nil {
|
||||
return errors.New("missing required field 'r' in transaction")
|
||||
}
|
||||
itx.R = uint256.MustFromBig((*big.Int)(dec.R))
|
||||
if dec.S == nil {
|
||||
return errors.New("missing required field 's' in transaction")
|
||||
}
|
||||
itx.S = uint256.MustFromBig((*big.Int)(dec.S))
|
||||
withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
|
||||
if withSignature {
|
||||
if err := sanityCheckSignature(itx.V.ToBig(), itx.R.ToBig(), itx.S.ToBig(), false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return ErrTxTypeNotSupported
|
||||
}
|
||||
|
||||
@@ -37,9 +37,11 @@ type sigCache struct {
|
||||
}
|
||||
|
||||
// MakeSigner returns a Signer based on the given chain config and block number.
|
||||
func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
|
||||
func MakeSigner(config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) Signer {
|
||||
var signer Signer
|
||||
switch {
|
||||
case config.IsCancun(blockNumber, blockTime):
|
||||
signer = NewCancunSigner(config.ChainID)
|
||||
case config.IsLondon(blockNumber):
|
||||
signer = NewLondonSigner(config.ChainID)
|
||||
case config.IsBerlin(blockNumber):
|
||||
@@ -63,6 +65,9 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
|
||||
// have the current block number available, use MakeSigner instead.
|
||||
func LatestSigner(config *params.ChainConfig) Signer {
|
||||
if config.ChainID != nil {
|
||||
if config.CancunTime != nil {
|
||||
return NewCancunSigner(config.ChainID)
|
||||
}
|
||||
if config.LondonBlock != nil {
|
||||
return NewLondonSigner(config.ChainID)
|
||||
}
|
||||
@@ -87,7 +92,7 @@ func LatestSignerForChainID(chainID *big.Int) Signer {
|
||||
if chainID == nil {
|
||||
return HomesteadSigner{}
|
||||
}
|
||||
return NewLondonSigner(chainID)
|
||||
return NewCancunSigner(chainID)
|
||||
}
|
||||
|
||||
// SignTx signs the transaction using the given signer and private key.
|
||||
@@ -170,6 +175,75 @@ type Signer interface {
|
||||
Equal(Signer) bool
|
||||
}
|
||||
|
||||
type cancunSigner struct{ londonSigner }
|
||||
|
||||
// NewCancunSigner returns a signer that accepts
|
||||
// - EIP-4844 blob transactions
|
||||
// - EIP-1559 dynamic fee transactions
|
||||
// - EIP-2930 access list transactions,
|
||||
// - EIP-155 replay protected transactions, and
|
||||
// - legacy Homestead transactions.
|
||||
func NewCancunSigner(chainId *big.Int) Signer {
|
||||
return cancunSigner{londonSigner{eip2930Signer{NewEIP155Signer(chainId)}}}
|
||||
}
|
||||
|
||||
func (s cancunSigner) Sender(tx *Transaction) (common.Address, error) {
|
||||
if tx.Type() != BlobTxType {
|
||||
return s.londonSigner.Sender(tx)
|
||||
}
|
||||
V, R, S := tx.RawSignatureValues()
|
||||
// Blob txs are defined to use 0 and 1 as their recovery
|
||||
// id, add 27 to become equivalent to unprotected Homestead signatures.
|
||||
V = new(big.Int).Add(V, big.NewInt(27))
|
||||
if tx.ChainId().Cmp(s.chainId) != 0 {
|
||||
return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId)
|
||||
}
|
||||
return recoverPlain(s.Hash(tx), R, S, V, true)
|
||||
}
|
||||
|
||||
func (s cancunSigner) Equal(s2 Signer) bool {
|
||||
x, ok := s2.(cancunSigner)
|
||||
return ok && x.chainId.Cmp(s.chainId) == 0
|
||||
}
|
||||
|
||||
func (s cancunSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) {
|
||||
txdata, ok := tx.inner.(*BlobTx)
|
||||
if !ok {
|
||||
return s.londonSigner.SignatureValues(tx, sig)
|
||||
}
|
||||
// Check that chain ID of tx matches the signer. We also accept ID zero here,
|
||||
// because it indicates that the chain ID was not specified in the tx.
|
||||
if txdata.ChainID.Sign() != 0 && txdata.ChainID.ToBig().Cmp(s.chainId) != 0 {
|
||||
return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId)
|
||||
}
|
||||
R, S, _ = decodeSignature(sig)
|
||||
V = big.NewInt(int64(sig[64]))
|
||||
return R, S, V, nil
|
||||
}
|
||||
|
||||
// Hash returns the hash to be signed by the sender.
|
||||
// It does not uniquely identify the transaction.
|
||||
func (s cancunSigner) Hash(tx *Transaction) common.Hash {
|
||||
if tx.Type() != BlobTxType {
|
||||
return s.londonSigner.Hash(tx)
|
||||
}
|
||||
return prefixedRlpHash(
|
||||
tx.Type(),
|
||||
[]interface{}{
|
||||
s.chainId,
|
||||
tx.Nonce(),
|
||||
tx.GasTipCap(),
|
||||
tx.GasFeeCap(),
|
||||
tx.Gas(),
|
||||
tx.To(),
|
||||
tx.Value(),
|
||||
tx.Data(),
|
||||
tx.AccessList(),
|
||||
tx.BlobGasFeeCap(),
|
||||
tx.BlobHashes(),
|
||||
})
|
||||
}
|
||||
|
||||
type londonSigner struct{ eip2930Signer }
|
||||
|
||||
// NewLondonSigner returns a signer that accepts
|
||||
|
||||
@@ -29,8 +29,8 @@ type AccessList []AccessTuple
|
||||
|
||||
// AccessTuple is the element type of an access list.
|
||||
type AccessTuple struct {
|
||||
Address common.Address `json:"address" gencodec:"required"`
|
||||
StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"`
|
||||
Address common.Address `json:"address" gencodec:"required"`
|
||||
StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"`
|
||||
}
|
||||
|
||||
// StorageKeys returns the total number of storage keys in the access list.
|
||||
@@ -94,17 +94,20 @@ func (tx *AccessListTx) copy() TxData {
|
||||
}
|
||||
|
||||
// accessors for innerTx.
|
||||
func (tx *AccessListTx) txType() byte { return AccessListTxType }
|
||||
func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID }
|
||||
func (tx *AccessListTx) accessList() AccessList { return tx.AccessList }
|
||||
func (tx *AccessListTx) data() []byte { return tx.Data }
|
||||
func (tx *AccessListTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice }
|
||||
func (tx *AccessListTx) gasTipCap() *big.Int { return tx.GasPrice }
|
||||
func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice }
|
||||
func (tx *AccessListTx) value() *big.Int { return tx.Value }
|
||||
func (tx *AccessListTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *AccessListTx) to() *common.Address { return tx.To }
|
||||
func (tx *AccessListTx) txType() byte { return AccessListTxType }
|
||||
func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID }
|
||||
func (tx *AccessListTx) accessList() AccessList { return tx.AccessList }
|
||||
func (tx *AccessListTx) data() []byte { return tx.Data }
|
||||
func (tx *AccessListTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice }
|
||||
func (tx *AccessListTx) gasTipCap() *big.Int { return tx.GasPrice }
|
||||
func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice }
|
||||
func (tx *AccessListTx) value() *big.Int { return tx.Value }
|
||||
func (tx *AccessListTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *AccessListTx) to() *common.Address { return tx.To }
|
||||
func (tx *AccessListTx) blobGas() uint64 { return 0 }
|
||||
func (tx *AccessListTx) blobGasFeeCap() *big.Int { return nil }
|
||||
func (tx *AccessListTx) blobHashes() []common.Hash { return nil }
|
||||
|
||||
func (tx *AccessListTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
|
||||
return dst.Set(tx.GasPrice)
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
// Copyright 2023 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// BlobTx represents an EIP-4844 transaction.
|
||||
type BlobTx struct {
|
||||
ChainID *uint256.Int
|
||||
Nonce uint64
|
||||
GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas
|
||||
GasFeeCap *uint256.Int // a.k.a. maxFeePerGas
|
||||
Gas uint64
|
||||
To *common.Address `rlp:"nil"` // nil means contract creation
|
||||
Value *uint256.Int
|
||||
Data []byte
|
||||
AccessList AccessList
|
||||
BlobFeeCap *uint256.Int // a.k.a. maxFeePerDataGas
|
||||
BlobHashes []common.Hash
|
||||
|
||||
// Signature values
|
||||
V *uint256.Int `json:"v" gencodec:"required"`
|
||||
R *uint256.Int `json:"r" gencodec:"required"`
|
||||
S *uint256.Int `json:"s" gencodec:"required"`
|
||||
}
|
||||
|
||||
// copy creates a deep copy of the transaction data and initializes all fields.
|
||||
func (tx *BlobTx) copy() TxData {
|
||||
cpy := &BlobTx{
|
||||
Nonce: tx.Nonce,
|
||||
To: copyAddressPtr(tx.To),
|
||||
Data: common.CopyBytes(tx.Data),
|
||||
Gas: tx.Gas,
|
||||
// These are copied below.
|
||||
AccessList: make(AccessList, len(tx.AccessList)),
|
||||
BlobHashes: make([]common.Hash, len(tx.BlobHashes)),
|
||||
Value: new(uint256.Int),
|
||||
ChainID: new(uint256.Int),
|
||||
GasTipCap: new(uint256.Int),
|
||||
GasFeeCap: new(uint256.Int),
|
||||
BlobFeeCap: new(uint256.Int),
|
||||
V: new(uint256.Int),
|
||||
R: new(uint256.Int),
|
||||
S: new(uint256.Int),
|
||||
}
|
||||
copy(cpy.AccessList, tx.AccessList)
|
||||
copy(cpy.BlobHashes, tx.BlobHashes)
|
||||
|
||||
if tx.Value != nil {
|
||||
cpy.Value.Set(tx.Value)
|
||||
}
|
||||
if tx.ChainID != nil {
|
||||
cpy.ChainID.Set(tx.ChainID)
|
||||
}
|
||||
if tx.GasTipCap != nil {
|
||||
cpy.GasTipCap.Set(tx.GasTipCap)
|
||||
}
|
||||
if tx.GasFeeCap != nil {
|
||||
cpy.GasFeeCap.Set(tx.GasFeeCap)
|
||||
}
|
||||
if tx.BlobFeeCap != nil {
|
||||
cpy.BlobFeeCap.Set(tx.BlobFeeCap)
|
||||
}
|
||||
if tx.V != nil {
|
||||
cpy.V.Set(tx.V)
|
||||
}
|
||||
if tx.R != nil {
|
||||
cpy.R.Set(tx.R)
|
||||
}
|
||||
if tx.S != nil {
|
||||
cpy.S.Set(tx.S)
|
||||
}
|
||||
return cpy
|
||||
}
|
||||
|
||||
// accessors for innerTx.
|
||||
func (tx *BlobTx) txType() byte { return BlobTxType }
|
||||
func (tx *BlobTx) chainID() *big.Int { return tx.ChainID.ToBig() }
|
||||
func (tx *BlobTx) accessList() AccessList { return tx.AccessList }
|
||||
func (tx *BlobTx) data() []byte { return tx.Data }
|
||||
func (tx *BlobTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *BlobTx) gasFeeCap() *big.Int { return tx.GasFeeCap.ToBig() }
|
||||
func (tx *BlobTx) gasTipCap() *big.Int { return tx.GasTipCap.ToBig() }
|
||||
func (tx *BlobTx) gasPrice() *big.Int { return tx.GasFeeCap.ToBig() }
|
||||
func (tx *BlobTx) value() *big.Int { return tx.Value.ToBig() }
|
||||
func (tx *BlobTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *BlobTx) to() *common.Address { return tx.To }
|
||||
func (tx *BlobTx) blobGas() uint64 { return params.BlobTxDataGasPerBlob * uint64(len(tx.BlobHashes)) }
|
||||
func (tx *BlobTx) blobGasFeeCap() *big.Int { return tx.BlobFeeCap.ToBig() }
|
||||
func (tx *BlobTx) blobHashes() []common.Hash { return tx.BlobHashes }
|
||||
|
||||
func (tx *BlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
|
||||
if baseFee == nil {
|
||||
return dst.Set(tx.GasFeeCap.ToBig())
|
||||
}
|
||||
tip := dst.Sub(tx.GasFeeCap.ToBig(), baseFee)
|
||||
if tip.Cmp(tx.GasTipCap.ToBig()) > 0 {
|
||||
tip.Set(tx.GasTipCap.ToBig())
|
||||
}
|
||||
return tip.Add(tip, baseFee)
|
||||
}
|
||||
|
||||
func (tx *BlobTx) rawSignatureValues() (v, r, s *big.Int) {
|
||||
return tx.V.ToBig(), tx.R.ToBig(), tx.S.ToBig()
|
||||
}
|
||||
|
||||
func (tx *BlobTx) setSignatureValues(chainID, v, r, s *big.Int) {
|
||||
tx.ChainID.SetFromBig(chainID)
|
||||
tx.V.SetFromBig(v)
|
||||
tx.R.SetFromBig(r)
|
||||
tx.S.SetFromBig(s)
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// DynamicFeeTx represents an EIP-1559 transaction.
|
||||
type DynamicFeeTx struct {
|
||||
ChainID *big.Int
|
||||
Nonce uint64
|
||||
@@ -82,17 +83,20 @@ func (tx *DynamicFeeTx) copy() TxData {
|
||||
}
|
||||
|
||||
// accessors for innerTx.
|
||||
func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType }
|
||||
func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID }
|
||||
func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList }
|
||||
func (tx *DynamicFeeTx) data() []byte { return tx.Data }
|
||||
func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap }
|
||||
func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap }
|
||||
func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap }
|
||||
func (tx *DynamicFeeTx) value() *big.Int { return tx.Value }
|
||||
func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *DynamicFeeTx) to() *common.Address { return tx.To }
|
||||
func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType }
|
||||
func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID }
|
||||
func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList }
|
||||
func (tx *DynamicFeeTx) data() []byte { return tx.Data }
|
||||
func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap }
|
||||
func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap }
|
||||
func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap }
|
||||
func (tx *DynamicFeeTx) value() *big.Int { return tx.Value }
|
||||
func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *DynamicFeeTx) to() *common.Address { return tx.To }
|
||||
func (tx *DynamicFeeTx) blobGas() uint64 { return 0 }
|
||||
func (tx *DynamicFeeTx) blobGasFeeCap() *big.Int { return nil }
|
||||
func (tx *DynamicFeeTx) blobHashes() []common.Hash { return nil }
|
||||
|
||||
func (tx *DynamicFeeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
|
||||
if baseFee == nil {
|
||||
|
||||
+15
-12
@@ -22,7 +22,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// LegacyTx is the transaction data of regular Ethereum transactions.
|
||||
// LegacyTx is the transaction data of the original Ethereum transactions.
|
||||
type LegacyTx struct {
|
||||
Nonce uint64 // nonce of sender account
|
||||
GasPrice *big.Int // wei per gas
|
||||
@@ -91,17 +91,20 @@ func (tx *LegacyTx) copy() TxData {
|
||||
}
|
||||
|
||||
// accessors for innerTx.
|
||||
func (tx *LegacyTx) txType() byte { return LegacyTxType }
|
||||
func (tx *LegacyTx) chainID() *big.Int { return deriveChainId(tx.V) }
|
||||
func (tx *LegacyTx) accessList() AccessList { return nil }
|
||||
func (tx *LegacyTx) data() []byte { return tx.Data }
|
||||
func (tx *LegacyTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice }
|
||||
func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice }
|
||||
func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice }
|
||||
func (tx *LegacyTx) value() *big.Int { return tx.Value }
|
||||
func (tx *LegacyTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *LegacyTx) to() *common.Address { return tx.To }
|
||||
func (tx *LegacyTx) txType() byte { return LegacyTxType }
|
||||
func (tx *LegacyTx) chainID() *big.Int { return deriveChainId(tx.V) }
|
||||
func (tx *LegacyTx) accessList() AccessList { return nil }
|
||||
func (tx *LegacyTx) data() []byte { return tx.Data }
|
||||
func (tx *LegacyTx) gas() uint64 { return tx.Gas }
|
||||
func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice }
|
||||
func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice }
|
||||
func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice }
|
||||
func (tx *LegacyTx) value() *big.Int { return tx.Value }
|
||||
func (tx *LegacyTx) nonce() uint64 { return tx.Nonce }
|
||||
func (tx *LegacyTx) to() *common.Address { return tx.To }
|
||||
func (tx *LegacyTx) blobGas() uint64 { return 0 }
|
||||
func (tx *LegacyTx) blobGasFeeCap() *big.Int { return nil }
|
||||
func (tx *LegacyTx) blobHashes() []common.Hash { return nil }
|
||||
|
||||
func (tx *LegacyTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
|
||||
return dst.Set(tx.GasPrice)
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
@@ -83,7 +84,7 @@ func TestEIP2200(t *testing.T) {
|
||||
for i, tt := range eip2200Tests {
|
||||
address := common.BytesToAddress([]byte("contract"))
|
||||
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb.CreateAccount(address)
|
||||
statedb.SetCode(address, hexutil.MustDecode(tt.input))
|
||||
statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
|
||||
@@ -135,7 +136,7 @@ func TestCreateGas(t *testing.T) {
|
||||
var gasUsed = uint64(0)
|
||||
doCheck := func(testGas int) bool {
|
||||
address := common.BytesToAddress([]byte("contract"))
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb.CreateAccount(address)
|
||||
statedb.SetCode(address, hexutil.MustDecode(tt.code))
|
||||
statedb.Finalise(true)
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
@@ -579,7 +580,7 @@ func BenchmarkOpMstore(bench *testing.B) {
|
||||
|
||||
func TestOpTstore(t *testing.T) {
|
||||
var (
|
||||
statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
mem = NewMemory()
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
@@ -42,7 +43,7 @@ func TestLoopInterrupt(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, tt := range loopInterruptTests {
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb.CreateAccount(address)
|
||||
statedb.SetCode(address, common.Hex2Bytes(tt))
|
||||
statedb.Finalise(true)
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
@@ -106,7 +107,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
|
||||
setDefaults(cfg)
|
||||
|
||||
if cfg.State == nil {
|
||||
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
}
|
||||
var (
|
||||
address = common.BytesToAddress([]byte("contract"))
|
||||
@@ -140,7 +141,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
|
||||
setDefaults(cfg)
|
||||
|
||||
if cfg.State == nil {
|
||||
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
}
|
||||
var (
|
||||
vmenv = NewEnv(cfg)
|
||||
|
||||
@@ -103,7 +103,7 @@ func TestExecute(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCall(t *testing.T) {
|
||||
state, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
state, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
address := common.HexToAddress("0x0a")
|
||||
state.SetCode(address, []byte{
|
||||
byte(vm.PUSH1), 10,
|
||||
@@ -159,7 +159,7 @@ func BenchmarkCall(b *testing.B) {
|
||||
}
|
||||
func benchmarkEVM_Create(bench *testing.B, code string) {
|
||||
var (
|
||||
statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
sender = common.BytesToAddress([]byte("sender"))
|
||||
receiver = common.BytesToAddress([]byte("receiver"))
|
||||
)
|
||||
@@ -327,7 +327,7 @@ func TestBlockhash(t *testing.T) {
|
||||
func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode string, b *testing.B) {
|
||||
cfg := new(Config)
|
||||
setDefaults(cfg)
|
||||
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
cfg.GasLimit = gas
|
||||
if len(tracerCode) > 0 {
|
||||
tracer, err := tracers.DefaultDirectory.New(tracerCode, new(tracers.Context), nil)
|
||||
@@ -818,7 +818,7 @@ func TestRuntimeJSTracer(t *testing.T) {
|
||||
main := common.HexToAddress("0xaa")
|
||||
for i, jsTracer := range jsTracers {
|
||||
for j, tc := range tests {
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb.SetCode(main, tc.code)
|
||||
statedb.SetCode(common.HexToAddress("0xbb"), calleeCode)
|
||||
statedb.SetCode(common.HexToAddress("0xcc"), calleeCode)
|
||||
@@ -860,7 +860,7 @@ func TestJSTracerCreateTx(t *testing.T) {
|
||||
exit: function(res) { this.exits++ }}`
|
||||
code := []byte{byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN)}
|
||||
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
Reference in New Issue
Block a user