mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-23 04:03:49 +00:00
Merge branch 'master' into badger2
This commit is contained in:
commit
93ff66f900
@ -25,8 +25,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/reexec"
|
||||
"github.com/ledgerwatch/turbo-geth/rpc"
|
||||
"github.com/ledgerwatch/turbo-geth/internal/cmdtest"
|
||||
"github.com/ledgerwatch/turbo-geth/rpc"
|
||||
)
|
||||
|
||||
func tmpdir(t *testing.T) string {
|
||||
|
@ -5,6 +5,11 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
|
||||
"github.com/ledgerwatch/bolt"
|
||||
"github.com/ledgerwatch/turbo-geth/accounts/abi/bind"
|
||||
"github.com/ledgerwatch/turbo-geth/accounts/abi/bind/backends"
|
||||
@ -21,10 +26,6 @@ import (
|
||||
"github.com/ledgerwatch/turbo-geth/params"
|
||||
"github.com/ledgerwatch/turbo-geth/trie"
|
||||
"github.com/ledgerwatch/turbo-geth/visual"
|
||||
"math/big"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func constructCodeMap(tds *state.TrieDbState) (map[common.Hash][]byte, error) {
|
||||
@ -108,6 +109,92 @@ func keyTape(t *trie.Trie, number int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func stateDatabaseComparison(first *bolt.DB, second *bolt.DB, number int) error {
|
||||
filename := fmt.Sprintf("changes_%d.dot", number)
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i := 0
|
||||
visual.StartGraph(f, true)
|
||||
m := make(map[string]string)
|
||||
|
||||
if err := first.View(func(readTx *bolt.Tx) error {
|
||||
return readTx.ForEach(func(name []byte, b *bolt.Bucket) error {
|
||||
return b.ForEach(func(k, v []byte) error {
|
||||
m[fmt.Sprintf("%x_%x", name, k)] = string(v)
|
||||
return nil
|
||||
})
|
||||
})
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := second.View(func(readTx *bolt.Tx) error {
|
||||
return readTx.ForEach(func(name []byte, b *bolt.Bucket) error {
|
||||
visual.StartCluster(f, i, string(name))
|
||||
if err := b.ForEach(func(k, v []byte) error {
|
||||
keyKeyBytes := &trie.Keybytes{
|
||||
Data: k,
|
||||
Odd: false,
|
||||
Terminating: false,
|
||||
}
|
||||
valKeyBytes := &trie.Keybytes{
|
||||
Data: v,
|
||||
Odd: false,
|
||||
Terminating: false,
|
||||
}
|
||||
val := valKeyBytes.ToHex()
|
||||
key := keyKeyBytes.ToHex()
|
||||
if m[fmt.Sprintf("%x_%x", name, k)] != string(v) {
|
||||
fmt.Fprintf(f, `k_%d -> v_%d`, i, i)
|
||||
visual.Horizontal(f, key, 0, fmt.Sprintf("k_%d", i), visual.HexIndexColors, visual.HexFontColors, 110)
|
||||
if len(val) > 0 {
|
||||
if len(val) > 32 {
|
||||
shortenedVal := val[:32]
|
||||
visual.Horizontal(f, shortenedVal, 99999, fmt.Sprintf("v_%d", i), visual.HexIndexColors, visual.HexFontColors, 100)
|
||||
} else {
|
||||
visual.Horizontal(f, val, 99999, fmt.Sprintf("v_%d", i), visual.HexIndexColors, visual.HexFontColors, 110)
|
||||
}
|
||||
} else {
|
||||
visual.Circle(f, fmt.Sprintf("v_%d", i), "...", false)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(f, `k_%d -> v_%d`, i, i)
|
||||
visual.Horizontal(f, key, 0, fmt.Sprintf("k_%d", i), visual.HexIndexColors, visual.HexFontColors, 110)
|
||||
if len(val) > 0 {
|
||||
if len(val) > 32 {
|
||||
shortenedVal := val[:32]
|
||||
visual.Horizontal(f, shortenedVal, 0, fmt.Sprintf("v_%d", i), visual.HexIndexColors, visual.HexFontColors, 100)
|
||||
} else {
|
||||
visual.Horizontal(f, val, 0, fmt.Sprintf("v_%d", i), visual.HexIndexColors, visual.HexFontColors, 110)
|
||||
}
|
||||
} else {
|
||||
visual.Circle(f, fmt.Sprintf("v_%d", i), "...", false)
|
||||
}
|
||||
}
|
||||
i++
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
visual.EndCluster(f)
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
visual.EndGraph(f)
|
||||
if err := f.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := exec.Command("dot", "-Tpng:gd", "-O", filename)
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
fmt.Printf("error: %v, output: %s\n", err, output)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stateDatabaseMap(db *bolt.DB, number int) error {
|
||||
filename := fmt.Sprintf("state_%d.dot", number)
|
||||
f, err := os.Create(filename)
|
||||
@ -214,6 +301,7 @@ func initialState1() error {
|
||||
return err
|
||||
}
|
||||
t := tds.Trie()
|
||||
snapshotDb := db.MemCopy().DB()
|
||||
var codeMap map[common.Hash][]byte
|
||||
if codeMap, err = constructCodeMap(tds); err != nil {
|
||||
return err
|
||||
@ -224,6 +312,9 @@ func initialState1() error {
|
||||
if _, err = statePicture(t, codeMap, 1, 48, false, false, false, false, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stateDatabaseComparison(snapshotDb, dbBolt, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
|
||||
transactOpts := bind.NewKeyedTransactor(key)
|
||||
@ -334,34 +425,49 @@ func initialState1() error {
|
||||
})
|
||||
|
||||
// BLOCK 1
|
||||
snapshotDb = db.MemCopy().DB()
|
||||
|
||||
if _, err = blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil {
|
||||
return err
|
||||
}
|
||||
if codeMap, err = constructCodeMap(tds); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stateDatabaseComparison(snapshotDb, dbBolt, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = statePicture(t, codeMap, 2, 48, false, false, false, false, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// BLOCK 2
|
||||
snapshotDb = db.MemCopy().DB()
|
||||
|
||||
if _, err = blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil {
|
||||
return err
|
||||
}
|
||||
if codeMap, err = constructCodeMap(tds); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stateDatabaseComparison(snapshotDb, dbBolt, 2); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = statePicture(t, codeMap, 3, 48, false, false, false, false, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// BLOCK 3
|
||||
snapshotDb = db.MemCopy().DB()
|
||||
|
||||
if _, err = blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil {
|
||||
return err
|
||||
}
|
||||
if codeMap, err = constructCodeMap(tds); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stateDatabaseComparison(snapshotDb, dbBolt, 3); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = statePicture(t, codeMap, 4, 48, false, false, false, false, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -373,9 +479,14 @@ func initialState1() error {
|
||||
}
|
||||
|
||||
// BLOCK 4
|
||||
snapshotDb = db.MemCopy().DB()
|
||||
|
||||
if _, err = blockchain.InsertChain(types.Blocks{blocks[3]}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stateDatabaseComparison(snapshotDb, dbBolt, 4); err != nil {
|
||||
return err
|
||||
}
|
||||
if codeMap, err = constructCodeMap(tds); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -384,9 +495,14 @@ func initialState1() error {
|
||||
}
|
||||
|
||||
// BLOCK 5
|
||||
snapshotDb = db.MemCopy().DB()
|
||||
|
||||
if _, err = blockchain.InsertChain(types.Blocks{blocks[4]}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stateDatabaseComparison(snapshotDb, dbBolt, 5); err != nil {
|
||||
return err
|
||||
}
|
||||
if codeMap, err = constructCodeMap(tds); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -395,9 +511,14 @@ func initialState1() error {
|
||||
}
|
||||
|
||||
// BLOCK 6
|
||||
snapshotDb = db.MemCopy().DB()
|
||||
|
||||
if _, err = blockchain.InsertChain(types.Blocks{blocks[5]}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stateDatabaseComparison(snapshotDb, dbBolt, 5); err != nil {
|
||||
return err
|
||||
}
|
||||
if codeMap, err = constructCodeMap(tds); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -409,9 +530,14 @@ func initialState1() error {
|
||||
}
|
||||
|
||||
// BLOCK 7
|
||||
snapshotDb = db.MemCopy().DB()
|
||||
|
||||
if _, err = blockchain.InsertChain(types.Blocks{blocks[6]}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stateDatabaseComparison(snapshotDb, dbBolt, 7); err != nil {
|
||||
return err
|
||||
}
|
||||
if codeMap, err = constructCodeMap(tds); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -422,9 +548,14 @@ func initialState1() error {
|
||||
|
||||
tds.SetResolveReads(true)
|
||||
// BLOCK 8
|
||||
snapshotDb = db.MemCopy().DB()
|
||||
|
||||
if _, err = blockchain.InsertChain(types.Blocks{blocks[7]}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stateDatabaseComparison(snapshotDb, dbBolt, 8); err != nil {
|
||||
return err
|
||||
}
|
||||
if codeMap, err = constructCodeMap(tds); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -318,7 +318,7 @@ func compareStorageRanges(sm, smg map[common.Hash]storageEntry) bool {
|
||||
}
|
||||
}
|
||||
}
|
||||
for k, _ := range smg {
|
||||
for k := range smg {
|
||||
if _, ok := sm[k]; !ok {
|
||||
fmt.Printf("%x not present in sm\n", k)
|
||||
return false
|
||||
@ -654,7 +654,7 @@ func bench1() {
|
||||
}
|
||||
req_id++
|
||||
template = `{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock": "0x%x", "toBlock": "0x%x", "address": "0x%x"}],"id":%d}`
|
||||
for account, _ := range accountSet {
|
||||
for account := range accountSet {
|
||||
var logs EthLogs
|
||||
if err := post(client, turbogeth_url, fmt.Sprintf(template, prevBn, bn, account, req_id), &logs); err != nil {
|
||||
fmt.Printf("Could not get logs for account %x: %v\n", account, err)
|
||||
|
@ -80,12 +80,12 @@ func (dt *DepTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cos
|
||||
func (dt *DepTracer) CaptureEnd(depth int, output []byte, gasUsed uint64, t time.Duration, err error) error {
|
||||
if err == nil {
|
||||
// Merge frame writes with the tx writes
|
||||
for addr, _ := range dt.accountsWriteSetFrame {
|
||||
for addr := range dt.accountsWriteSetFrame {
|
||||
dt.accountsWriteSet[addr] = struct{}{}
|
||||
}
|
||||
for addr, smap := range dt.storageWriteSetFrame {
|
||||
if smap_dest, ok := dt.storageWriteSet[addr]; ok {
|
||||
for loc, _ := range smap {
|
||||
for loc := range smap {
|
||||
smap_dest[loc] = struct{}{}
|
||||
}
|
||||
} else {
|
||||
|
@ -64,7 +64,7 @@ func feemarket() {
|
||||
if minFee.Cmp(minimum) < 0 {
|
||||
minFee.Set(minimum)
|
||||
}
|
||||
for _, _ = range block.Transactions() {
|
||||
for range block.Transactions() {
|
||||
txCount++
|
||||
}
|
||||
fmt.Fprintf(w, "%d,%d\n", blockNum, minFee)
|
||||
|
@ -53,6 +53,7 @@ var chaindata = flag.String("chaindata", "chaindata", "path to the chaindata fil
|
||||
var statefile = flag.String("statefile", "state", "path to the file where the state will be periodically written during the analysis")
|
||||
var start = flag.Int("start", 0, "number of data points to skip when making a chart")
|
||||
var window = flag.Int("window", 1024, "size of the window for moving average")
|
||||
var triesize = flag.Int("triesize", 1024*1024, "maximum number of nodes in the state trie")
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
@ -1681,7 +1682,7 @@ func main() {
|
||||
//nakedAccountChart()
|
||||
//specExecChart1()
|
||||
if *action == "stateless" {
|
||||
stateless(*chaindata, *statefile)
|
||||
stateless(*chaindata, *statefile, *triesize)
|
||||
}
|
||||
if *action == "stateless_chart" {
|
||||
stateless_chart_key_values("/Users/alexeyakhunov/mygit/go-ethereum/st_1/stateless.csv", []int{21, 20, 19, 18}, "breakdown.png", 2800000, 1)
|
||||
|
@ -106,8 +106,8 @@ func writeStats(w io.Writer, blockNum uint64, blockProof trie.BlockProof) {
|
||||
}
|
||||
*/
|
||||
|
||||
func stateless(chaindata string, statefile string) {
|
||||
//state.MaxTrieCacheGen = 64*1024
|
||||
func stateless(chaindata string, statefile string, triesize int) {
|
||||
state.MaxTrieCacheGen = uint32(triesize)
|
||||
startTime := time.Now()
|
||||
sigs := make(chan os.Signal, 1)
|
||||
interruptCh := make(chan bool, 1)
|
||||
@ -152,6 +152,11 @@ func stateless(chaindata string, statefile string) {
|
||||
checkRoots(stateDb, db, preRoot, blockNum-1)
|
||||
}
|
||||
batch := stateDb.NewBatch()
|
||||
defer func() {
|
||||
if _, err = batch.Commit(); err != nil {
|
||||
fmt.Printf("Failed to commit batch: %v\n", err)
|
||||
}
|
||||
}()
|
||||
tds, err := state.NewTrieDbState(preRoot, batch, blockNum-1)
|
||||
check(err)
|
||||
if blockNum > 1 {
|
||||
@ -288,10 +293,6 @@ func stateless(chaindata string, statefile string) {
|
||||
default:
|
||||
}
|
||||
}
|
||||
if _, err := batch.Commit(); err != nil {
|
||||
fmt.Printf("Failed to commit batch: %v\n", err)
|
||||
return
|
||||
}
|
||||
stateDb.Close()
|
||||
fmt.Printf("Processed %d blocks\n", blockNum)
|
||||
fmt.Printf("Next time specify -block %d\n", blockNum)
|
||||
|
@ -550,10 +550,6 @@ func (tds *TrieDbState) updateTrieRoots(forward bool) ([]common.Hash, error) {
|
||||
}
|
||||
for addressHash, m := range b.storageUpdates {
|
||||
addrHash := addressHash.Hash()
|
||||
if _, ok := b.deletedHashes[addressHash.Hash()]; ok {
|
||||
// Deleted contracts will be dealth with later, in the next loop
|
||||
continue
|
||||
}
|
||||
|
||||
for keyHash, v := range m {
|
||||
cKey := dbutils.GenerateCompositeTrieKey(addressHash.Hash(), keyHash)
|
||||
@ -592,6 +588,7 @@ func (tds *TrieDbState) updateTrieRoots(forward bool) ([]common.Hash, error) {
|
||||
ok, root := tds.t.DeepHash(addrHash[:])
|
||||
if ok {
|
||||
account.Root = root
|
||||
//fmt.Printf("(b)Set %x root for addrHash %x\n", root, addrHash)
|
||||
} else {
|
||||
//fmt.Printf("(b)Set empty root for addrHash %x\n", addrHash)
|
||||
account.Root = trie.EmptyRoot
|
||||
@ -601,6 +598,7 @@ func (tds *TrieDbState) updateTrieRoots(forward bool) ([]common.Hash, error) {
|
||||
ok, root := tds.t.DeepHash(addrHash[:])
|
||||
if ok {
|
||||
account.Root = root
|
||||
//fmt.Printf("Set %x root for addrHash %x\n", root, addrHash)
|
||||
} else {
|
||||
//fmt.Printf("Set empty root for addrHash %x\n", addrHash)
|
||||
account.Root = trie.EmptyRoot
|
||||
@ -632,14 +630,27 @@ func (tds *TrieDbState) updateTrieRoots(forward bool) ([]common.Hash, error) {
|
||||
}
|
||||
// For the contracts that got deleted
|
||||
for address := range b.deleted {
|
||||
if _, ok := b.created[address]; ok {
|
||||
// In some rather artificial circumstances, an account can be recreated after having been self-destructed
|
||||
// in the same block. It can only happen when contract is introduced in the genesis state with nonce 0
|
||||
// rather than created by a transaction (in that case, its starting nonce is 1). The self-destructed
|
||||
// contract actually gets removed from the state only at the end of the block, so if its nonce is not 0,
|
||||
// it will prevent any re-creation within the same block. However, if the contract is introduced in
|
||||
// the genesis state, its nonce is 0, and that means it can be self-destructed, and then re-created,
|
||||
// all in the same block. In such cases, we must preserve storage modifications happening after the
|
||||
// self-destruction
|
||||
continue
|
||||
}
|
||||
addrHash, err := tds.HashAddress(address, false /*save*/)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if account, ok := b.accountUpdates[addrHash]; ok && account != nil {
|
||||
//fmt.Printf("(b)Set empty root for addrHash %x due to deleted\n", addrHash)
|
||||
account.Root = trie.EmptyRoot
|
||||
}
|
||||
if account, ok := accountUpdates[addrHash]; ok && account != nil {
|
||||
//fmt.Printf("Set empty root for addrHash %x due to deleted\n", addrHash)
|
||||
account.Root = trie.EmptyRoot
|
||||
}
|
||||
tds.t.DeleteSubtree(addrHash[:], tds.blockNr)
|
||||
@ -1052,12 +1063,6 @@ func (tsw *TrieStateWriter) UpdateAccountData(_ context.Context, address common.
|
||||
}
|
||||
|
||||
tsw.tds.currentBuffer.accountUpdates[addrHash] = account
|
||||
// TODO [Alexey] Are these lines below still required?
|
||||
addrHashWithInc := newAddressHashWithIncarnation(addrHash, account.GetIncarnation())
|
||||
if _, ok := tsw.tds.currentBuffer.storageUpdates[addrHashWithInc]; !ok && account.GetIncarnation() > 0 {
|
||||
tsw.tds.currentBuffer.storageUpdates[addrHashWithInc] = map[common.Hash][]byte{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1097,6 +1102,7 @@ func (tsw *TrieStateWriter) DeleteAccount(_ context.Context, address common.Addr
|
||||
return err
|
||||
}
|
||||
tsw.tds.currentBuffer.accountUpdates[addrHash] = nil
|
||||
delete(tsw.tds.currentBuffer.storageUpdates, newAddressHashWithIncarnation(addrHash, original.GetIncarnation()))
|
||||
tsw.tds.currentBuffer.deleted[address] = struct{}{}
|
||||
return nil
|
||||
}
|
||||
|
@ -676,55 +676,6 @@ func (sdb *IntraBlockState) CreateAccount(addr common.Address, checkPrev bool) {
|
||||
newObj.created = true
|
||||
}
|
||||
|
||||
// Copy creates a deep, independent copy of the state.
|
||||
// Snapshots of the copied state cannot be applied to the copy.
|
||||
func (sdb *IntraBlockState) Copy() *IntraBlockState {
|
||||
// Copy all the basic fields, initialize the memory ones
|
||||
state := &IntraBlockState{
|
||||
stateReader: sdb.stateReader,
|
||||
stateObjects: make(map[common.Address]*stateObject, len(sdb.journal.dirties)),
|
||||
stateObjectsDirty: make(map[common.Address]struct{}, len(sdb.journal.dirties)),
|
||||
nilAccounts: make(map[common.Address]struct{}),
|
||||
refund: sdb.refund,
|
||||
logs: make(map[common.Hash][]*types.Log, len(sdb.logs)),
|
||||
logSize: sdb.logSize,
|
||||
preimages: make(map[common.Hash][]byte, len(sdb.preimages)),
|
||||
journal: newJournal(),
|
||||
}
|
||||
// Copy the dirty states, logs, and preimages
|
||||
for addr := range sdb.journal.dirties {
|
||||
// As documented [here](https://github.com/ledgerwatch/turbo-geth/pull/16485#issuecomment-380438527),
|
||||
// and in the FinalizeTx method, there is a case where an object is in the journal but not
|
||||
// in the stateObjects: OOG after touch on ripeMD prior to Byzantium. Thus, we need to check for
|
||||
// nil
|
||||
if object, exist := sdb.stateObjects[addr]; exist {
|
||||
state.stateObjects[addr] = object.deepCopy(state)
|
||||
state.stateObjectsDirty[addr] = struct{}{}
|
||||
}
|
||||
}
|
||||
// Above, we don't copy the actual journal. This means that if the copy is copied, the
|
||||
// loop above will be a no-op, since the copy's journal is empty.
|
||||
// Thus, here we iterate over stateObjects, to enable copies of copies
|
||||
for addr := range sdb.stateObjectsDirty {
|
||||
if _, exist := state.stateObjects[addr]; !exist {
|
||||
state.stateObjects[addr] = sdb.stateObjects[addr].deepCopy(state)
|
||||
state.stateObjectsDirty[addr] = struct{}{}
|
||||
}
|
||||
}
|
||||
for hash, logs := range sdb.logs {
|
||||
cpy := make([]*types.Log, len(logs))
|
||||
for i, l := range logs {
|
||||
cpy[i] = new(types.Log)
|
||||
*cpy[i] = *l
|
||||
}
|
||||
state.logs[hash] = cpy
|
||||
}
|
||||
for hash, preimage := range sdb.preimages {
|
||||
state.preimages[hash] = preimage
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
// Snapshot returns an identifier for the current revision of the state.
|
||||
func (sdb *IntraBlockState) Snapshot() int {
|
||||
id := sdb.nextRevisionID
|
||||
|
@ -476,24 +476,6 @@ func (s *StateSuite) TestTouchDelete(c *check.C) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
|
||||
// See https://github.com/ledgerwatch/turbo-geth/pull/15225#issuecomment-380191512
|
||||
func TestCopyOfCopy(t *testing.T) {
|
||||
db := ethdb.NewMemDatabase()
|
||||
sdbTds, _ := NewTrieDbState(common.Hash{}, db, 0)
|
||||
sdb := New(sdbTds)
|
||||
sdbTds.StartNewBuffer()
|
||||
addr := common.HexToAddress("aaaa")
|
||||
sdb.SetBalance(addr, big.NewInt(42))
|
||||
|
||||
if got := sdb.Copy().GetBalance(addr).Uint64(); got != 42 {
|
||||
t.Fatalf("1st copy fail, expected 42, got %v", got)
|
||||
}
|
||||
if got := sdb.Copy().Copy().GetBalance(addr).Uint64(); got != 42 {
|
||||
t.Fatalf("2nd copy fail, expected 42, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntraBlockStateNewEmptyAccount(t *testing.T) {
|
||||
db := ethdb.NewMemDatabase()
|
||||
tds, _ := NewTrieDbState(common.Hash{}, db, 0)
|
||||
|
@ -33,9 +33,9 @@ type txNoncer struct {
|
||||
}
|
||||
|
||||
// newTxNoncer creates a new virtual state database to track the pool nonces.
|
||||
func newTxNoncer(statedb *state.IntraBlockState) *txNoncer {
|
||||
func newTxNoncer(fallback *state.IntraBlockState) *txNoncer {
|
||||
return &txNoncer{
|
||||
fallback: statedb.Copy(),
|
||||
fallback: fallback,
|
||||
nonces: make(map[common.Address]uint64),
|
||||
}
|
||||
}
|
||||
|
@ -80,10 +80,9 @@ type txTraceResult struct {
|
||||
// being traced.
|
||||
type blockTraceTask struct {
|
||||
tds *state.TrieDbState
|
||||
statedb *state.IntraBlockState // Intermediate state prepped for tracing
|
||||
block *types.Block // Block to trace the transactions from
|
||||
rootref common.Hash // Trie root reference held for this task
|
||||
results []*txTraceResult // Trace results procudes by the task
|
||||
block *types.Block // Block to trace the transactions from
|
||||
rootref common.Hash // Trie root reference held for this task
|
||||
results []*txTraceResult // Trace results procudes by the task
|
||||
}
|
||||
|
||||
// blockTraceResult represets the results of tracing a single block when an entire
|
||||
@ -210,14 +209,16 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
|
||||
msg, _ := tx.AsMessage(signer)
|
||||
vmctx := core.NewEVMContext(msg, task.block.Header(), api.eth.blockchain, nil)
|
||||
|
||||
res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config)
|
||||
statedb := state.New(task.tds)
|
||||
|
||||
res, err := api.traceTx(ctx, msg, vmctx, statedb, config)
|
||||
if err != nil {
|
||||
task.results[i] = &txTraceResult{Error: err.Error()}
|
||||
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
|
||||
break
|
||||
}
|
||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||
_ = task.statedb.FinalizeTx(api.eth.blockchain.Config().WithEIPsFlags(context.Background(), task.block.Number()), task.tds.TrieStateWriter())
|
||||
_ = statedb.FinalizeTx(api.eth.blockchain.Config().WithEIPsFlags(context.Background(), task.block.Number()), task.tds.TrieStateWriter())
|
||||
task.results[i] = &txTraceResult{Result: res}
|
||||
}
|
||||
// Stream the result back to the user or abort on teardown
|
||||
@ -283,7 +284,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
|
||||
txs := block.Transactions()
|
||||
|
||||
select {
|
||||
case tasks <- &blockTraceTask{statedb: statedb.Copy(), tds: tds.Copy(), block: block, rootref: proot, results: make([]*txTraceResult, len(txs))}:
|
||||
case tasks <- &blockTraceTask{tds: tds.Copy(), block: block, rootref: proot, results: make([]*txTraceResult, len(txs))}:
|
||||
case <-notifier.Closed():
|
||||
return
|
||||
}
|
||||
@ -475,7 +476,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
|
||||
var failed error
|
||||
for i, tx := range txs {
|
||||
// Send the trace task over for execution
|
||||
jobs <- &txTraceTask{statedb: statedb.Copy(), index: i}
|
||||
jobs <- &txTraceTask{statedb: state.New(dbstate), index: i}
|
||||
|
||||
// Generate the next state snapshot fast without tracing
|
||||
msg, _ := tx.AsMessage(signer)
|
||||
|
@ -18,6 +18,8 @@ package ethdb
|
||||
|
||||
// IdealBatchSize defines the size of the data batches should ideally add in one
|
||||
// write.
|
||||
import "github.com/ledgerwatch/bolt"
|
||||
|
||||
const IdealBatchSize = 100 * 1024
|
||||
|
||||
// Putter wraps the database write operations.
|
||||
@ -70,6 +72,7 @@ type Database interface {
|
||||
Size() int
|
||||
Keys() ([][]byte, error)
|
||||
MemCopy() Database
|
||||
DB() *bolt.DB
|
||||
// [TURBO-GETH] Freezer support (minimum amount that is actually used)
|
||||
// FIXME: implement support if needed
|
||||
Ancients() (uint64, error)
|
||||
|
@ -3,12 +3,12 @@ package ethdb
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/ledgerwatch/bolt"
|
||||
"github.com/ledgerwatch/turbo-geth/common"
|
||||
"github.com/ledgerwatch/turbo-geth/common/dbutils"
|
||||
"github.com/ledgerwatch/turbo-geth/log"
|
||||
"github.com/petar/GoLLRB/llrb"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type PutItem struct {
|
||||
@ -461,3 +461,8 @@ func (m *mutation) Ancients() (uint64, error) {
|
||||
func (m *mutation) TruncateAncients(items uint64) error {
|
||||
return errNotSupported
|
||||
}
|
||||
|
||||
// Get bolt database instance
|
||||
func (m *mutation) DB() *bolt.DB {
|
||||
return m.db.DB()
|
||||
}
|
||||
|
@ -255,7 +255,9 @@ func (w *worker) pending() (*types.Block, *state.IntraBlockState, *state.TrieDbS
|
||||
if w.snapshotState == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
return w.snapshotBlock, w.snapshotState.Copy(), w.snapshotTds.Copy()
|
||||
// FIXME: fix miner code
|
||||
// https://github.com/ledgerwatch/turbo-geth/issues/131
|
||||
return w.snapshotBlock, w.snapshotState, w.snapshotTds.Copy()
|
||||
}
|
||||
|
||||
// pendingBlock returns pending block.
|
||||
@ -703,7 +705,9 @@ func (w *worker) updateSnapshot() {
|
||||
w.current.receipts,
|
||||
)
|
||||
|
||||
w.snapshotState = w.current.state.Copy()
|
||||
// FIXME: fix miner code
|
||||
// https://github.com/ledgerwatch/turbo-geth/issues/131
|
||||
w.snapshotState = w.current.state
|
||||
}
|
||||
|
||||
func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) {
|
||||
@ -973,7 +977,9 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st
|
||||
receipts[i] = new(types.Receipt)
|
||||
*receipts[i] = *l
|
||||
}
|
||||
s := w.current.state.Copy()
|
||||
// FIXME: fix miner code
|
||||
// https://github.com/ledgerwatch/turbo-geth/issues/131
|
||||
s := w.current.state
|
||||
tds := w.current.tds.Copy()
|
||||
block, err := w.engine.FinalizeAndAssemble(w.chainConfig, w.current.header, s, w.current.txs, uncles, w.current.receipts)
|
||||
if err != nil {
|
||||
|
@ -44,14 +44,6 @@ func TestBlockchain(t *testing.T) {
|
||||
// using 4.6 TGas
|
||||
bt.skipLoad(`.*randomStatetest94.json.*`)
|
||||
|
||||
bt.fails(`^TestBlockchain/ValidBlocks/bcStateTests/suicideStorageCheckVCreate2.json/suicideStorageCheckVCreate2_Constantinople`, "not fixed yet")
|
||||
bt.fails(`^TestBlockchain/ValidBlocks/bcStateTests/suicideStorageCheckVCreate2.json/suicideStorageCheckVCreate2_ConstantinopleFix`, "not fixed yet")
|
||||
bt.fails(`^TestBlockchain/ValidBlocks/bcStateTests/suicideStorageCheckVCreate2.json/suicideStorageCheckVCreate2_Istanbul`, "not fixed yet")
|
||||
|
||||
bt.fails(`^TestBlockchain/ValidBlocks/bcStateTests/suicideStorageCheckVCreate.json.*`, "not fixed yet")
|
||||
|
||||
bt.fails(`^TestBlockchain/ValidBlocks/bcStateTests/suicideStorageCheck.json.*`, "not fixed yet")
|
||||
|
||||
bt.fails(`(?m)^TestBlockchain/TransitionTests/bcFrontierToHomestead/blockChainFrontierWithLargerTDvsHomesteadBlockchain2.json`, "Work in progress")
|
||||
bt.fails(`(?m)^TestBlockchain/TransitionTests/bcFrontierToHomestead/blockChainFrontierWithLargerTDvsHomesteadBlockchain.json`, "Work in progress")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user