diff --git a/Gopkg.lock b/Gopkg.lock index a56d7983..7ed1de5f 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -29,14 +29,22 @@ revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" +[[projects]] + branch = "master" + name = "github.com/edsrzf/mmap-go" + packages = ["."] + revision = "0bce6a6887123b67a60366d2c9fe2dfb74289d2e" + [[projects]] name = "github.com/ethereum/go-ethereum" packages = [ "common", + "common/bitutil", "common/hexutil", "common/math", "common/mclock", "consensus", + "consensus/ethash", "consensus/misc", "core", "core/rawdb", @@ -314,6 +322,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "471d91e2c0a3b0b799ddfd79266deb2f4e6e46a1721f9c00680c370f1eb5662f" + inputs-digest = "b5f54632217e0d318d469bb6cd3a30d971c918e4d4bb0165d16603cbab9ba165" solver-name = "gps-cdcl" solver-version = 1 diff --git a/README.md b/README.md index 864b0d2a..5b51f6ed 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,6 @@ To build, execute these two commands: dep ensure -go build main.go +go build main.go copied.go diff --git a/copied.go b/copied.go new file mode 100644 index 00000000..532f478f --- /dev/null +++ b/copied.go @@ -0,0 +1,42 @@ +// Code copied from go-ethereum +package main + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/params" +) + +// Some weird constants to avoid constant memory allocs for them. +var ( + big8 = big.NewInt(8) + big32 = big.NewInt(32) +) + +// AccumulateRewards credits the coinbase of the given block with the mining +// reward. The total reward consists of the static block reward and rewards for +// included uncles. The coinbase of each uncle block is also rewarded. +func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { + // Select the correct block reward based on chain progression + blockReward := ethash.FrontierBlockReward + if config.IsByzantium(header.Number) { + blockReward = ethash.ByzantiumBlockReward + } + // Accumulate the rewards for the miner and any included uncles + reward := new(big.Int).Set(blockReward) + r := new(big.Int) + for _, uncle := range uncles { + r.Add(uncle.Number, big8) + r.Sub(r, header.Number) + r.Mul(r, blockReward) + r.Div(r, big8) + state.AddBalance(uncle.Coinbase, r) + + r.Div(blockReward, big32) + reward.Add(reward, r) + } + state.AddBalance(header.Coinbase, reward) +} diff --git a/main.go b/main.go index 8321e13e..37d7a610 100644 --- a/main.go +++ b/main.go @@ -3,11 +3,16 @@ package main import ( "bytes" "fmt" + "io" + "os" eth_common "github.com/ethereum/go-ethereum/common" eth_core "github.com/ethereum/go-ethereum/core" eth_state "github.com/ethereum/go-ethereum/core/state" + eth_types "github.com/ethereum/go-ethereum/core/types" + eth_rlp "github.com/ethereum/go-ethereum/rlp" eth_ethdb "github.com/ethereum/go-ethereum/ethdb" + eth_params "github.com/ethereum/go-ethereum/params" eth_trie "github.com/ethereum/go-ethereum/trie" dbm "github.com/tendermint/tmlibs/db" @@ -208,16 +213,69 @@ func main() { // One of the genesis account having 200 ETH b := statedb.GetBalance(eth_common.HexToAddress("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0")) fmt.Printf("Balance: %s\n", b) - root, err := statedb.Commit(false /* deleteEmptyObjects */) + genesis_root, err := statedb.Commit(false /* deleteEmptyObjects */) if err != nil { panic(err) } - fmt.Printf("Genesis state root hash: %x\n", root[:]) - // Try to create a new statedb from genesis hash - genesis_state, err := eth_state.New(root, d) + fmt.Printf("Genesis state root hash: %x\n", genesis_root[:]) + // File with blockchain data exported from geth by using "geth expordb" command + input, err := os.Open("/Users/alexeyakhunov/mygit/blockchain") if err != nil { panic(err) } - b1 := genesis_state.GetBalance(eth_common.HexToAddress("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0")) - fmt.Printf("Balance reloaded: %s\n", b1) + defer input.Close() + // Ethereum mainnet config + chainConfig := eth_params.MainnetChainConfig + stream := eth_rlp.NewStream(input, 0) + var block eth_types.Block + n := 0 + var root500 eth_common.Hash // Root hash after block 500 + var root501 eth_common.Hash // Root hash after block 501 + for { + if err = stream.Decode(&block); err == io.EOF { + err = nil // Clear it + break + } else if err != nil { + panic(fmt.Errorf("at block %d: %v", n, err)) + } + // don't import first block + if block.NumberU64() == 0 { + continue + } + header := block.Header() + // Apply mining rewards to the statedb + accumulateRewards(chainConfig, statedb, header, block.Uncles()) + // Commit block + root, err := statedb.Commit(chainConfig.IsEIP158(block.Number()) /* deleteEmptyObjects */) + if err != nil { + panic(err) + } + switch n { + case 500: + root500 = root + case 501: + root501 = root + } + n++ + if n >= 1000 { + break + } + } + fmt.Printf("Processed %d blocks\n", n) + genesis_state, err := eth_state.New(genesis_root, d) + fmt.Printf("Balance of one of the genesis investors: %s\n", genesis_state.GetBalance(eth_common.HexToAddress("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0"))) + miner501 := eth_common.HexToAddress("0x35e8e5dC5FBd97c5b421A80B596C030a2Be2A04D") // Miner of the block 501 + // Try to create a new statedb from root of the block 500 + state500, err := eth_state.New(root500, d) + if err != nil { + panic(err) + } + miner501_balance_at_500 := state500.GetBalance(miner501) + state501, err := eth_state.New(root501, d) + if err != nil { + panic(err) + } + miner501_balance_at_501 := state501.GetBalance(miner501) + fmt.Printf("Miner of block 501's balance after block 500: %d\n", miner501_balance_at_500) + fmt.Printf("Miner of block 501's balance after block 501: %d\n", miner501_balance_at_501) } \ No newline at end of file