Merge pull request #3179 from obscuren/eip-158

EIP158 & 160 Hardfork
This commit is contained in:
Felix Lange authored and GitHub committed 2016-11-14 10:52:02 +01:00
commit ca73dea3b9
961 files changed
+149770 -66826

No files matched your search

+3 -3
View File
@@ -48,15 +48,15 @@ func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
keyAddr := crypto.PubkeyToAddress(key.PublicKey)
return &TransactOpts{
From: keyAddr,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
Signer: func(signer types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) {
if address != keyAddr {
return nil, errors.New("not authorized to sign this account")
}
signature, err := crypto.SignEthereum(tx.SigHash().Bytes(), key)
signature, err := crypto.SignEthereum(signer.Hash(tx).Bytes(), key)
if err != nil {
return nil, err
}
return tx.WithSignature(signature)
return tx.WithSignature(signer, signature)
},
}
}
+15 -13
View File
@@ -31,11 +31,12 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"golang.org/x/net/context"
)
// Default chain configuration which sets homestead phase at block 0 (i.e. no frontier)
var chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)}
var chainConfig = &params.ChainConfig{HomesteadBlock: big.NewInt(0), EIP150Block: new(big.Int), EIP158Block: new(big.Int)}
// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
var _ bind.ContractBackend = (*SimulatedBackend)(nil)
@@ -51,6 +52,8 @@ type SimulatedBackend struct {
mu sync.Mutex
pendingBlock *types.Block // Currently pending block that will be imported on request
pendingState *state.StateDB // Currently pending state that will be the active on on request
config *params.ChainConfig
}
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
@@ -85,7 +88,7 @@ func (b *SimulatedBackend) Rollback() {
}
func (b *SimulatedBackend) rollback() {
blocks, _ := core.GenerateChain(nil, b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})
blocks, _ := core.GenerateChain(chainConfig, b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})
b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), b.database)
}
@@ -234,7 +237,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
b.mu.Lock()
defer b.mu.Unlock()
sender, err := tx.From()
sender, err := types.Sender(types.HomesteadSigner{}, tx)
if err != nil {
panic(fmt.Errorf("invalid transaction: %v", err))
}
@@ -243,7 +246,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
panic(fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce))
}
blocks, _ := core.GenerateChain(nil, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
blocks, _ := core.GenerateChain(chainConfig, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
for _, tx := range b.pendingBlock.Transactions() {
block.AddTx(tx)
}
@@ -259,12 +262,11 @@ type callmsg struct {
ethereum.CallMsg
}
func (m callmsg) From() (common.Address, error) { return m.CallMsg.From, nil }
func (m callmsg) FromFrontier() (common.Address, error) { return m.CallMsg.From, nil }
func (m callmsg) Nonce() uint64 { return 0 }
func (m callmsg) CheckNonce() bool { return false }
func (m callmsg) To() *common.Address { return m.CallMsg.To }
func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callmsg) Gas() *big.Int { return m.CallMsg.Gas }
func (m callmsg) Value() *big.Int { return m.CallMsg.Value }
func (m callmsg) Data() []byte { return m.CallMsg.Data }
func (m callmsg) From() common.Address { return m.CallMsg.From }
func (m callmsg) Nonce() uint64 { return 0 }
func (m callmsg) CheckNonce() bool { return false }
func (m callmsg) To() *common.Address { return m.CallMsg.To }
func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callmsg) Gas() *big.Int { return m.CallMsg.Gas }
func (m callmsg) Value() *big.Int { return m.CallMsg.Value }
func (m callmsg) Data() []byte { return m.CallMsg.Data }
+2 -2
View File
@@ -31,7 +31,7 @@ import (
// SignerFn is a signer function callback when a contract requires a method to
// sign the transaction before submission.
type SignerFn func(common.Address, *types.Transaction) (*types.Transaction, error)
type SignerFn func(types.Signer, common.Address, *types.Transaction) (*types.Transaction, error)
// CallOpts is the collection of options to fine tune a contract call request.
type CallOpts struct {
@@ -214,7 +214,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
if opts.Signer == nil {
return nil, errors.New("no signer to authorize the transaction with")
}
signedTx, err := opts.Signer(opts.From, rawTx)
signedTx, err := opts.Signer(types.HomesteadSigner{}, opts.From, rawTx)
if err != nil {
return nil, err
}
+1 -1
View File
@@ -60,7 +60,7 @@ func TestWaitDeployed(t *testing.T) {
// Create the transaction.
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, big.NewInt(1), common.FromHex(test.code))
tx, _ = tx.SignECDSA(testKey)
tx, _ = tx.SignECDSA(types.HomesteadSigner{}, testKey)
// Wait for it to get mined in the background.
var (
+3 -2
View File
@@ -76,10 +76,11 @@ func runTestWithReader(test string, r io.Reader) error {
case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests":
err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, params.MainNetHomesteadGasRepriceBlock, r, skipTests)
case "st", "state", "statetest", "statetests":
rs := tests.RuleSet{HomesteadBlock: params.MainNetHomesteadBlock, DAOForkBlock: params.MainNetDAOForkBlock, DAOForkSupport: true}
rs := &params.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock, DAOForkBlock: params.MainNetDAOForkBlock, DAOForkSupport: true, EIP150Block: params.MainNetHomesteadGasRepriceBlock}
err = tests.RunStateTestWithReader(rs, r, skipTests)
case "tx", "transactiontest", "transactiontests":
err = tests.RunTransactionTestsWithReader(r, skipTests)
rs := &params.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock, DAOForkBlock: params.MainNetDAOForkBlock, DAOForkSupport: true, EIP150Block: params.MainNetHomesteadGasRepriceBlock}
err = tests.RunTransactionTestsWithReader(rs, r, skipTests)
case "vm", "vmtest", "vmtests":
err = tests.RunVmTestWithReader(r, skipTests)
case "rlp", "rlptest", "rlptests":
+18 -18
View File
@@ -191,7 +191,7 @@ func run(ctx *cli.Context) error {
vmdone := time.Since(tstart)
if ctx.GlobalBool(DumpFlag.Name) {
statedb.Commit()
statedb.Commit(true)
fmt.Println(string(statedb.Dump()))
}
vm.StdErrFormat(logger.StructLogs())
@@ -251,7 +251,7 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg
return env
}
// ruleSet implements vm.RuleSet and will always default to the homestead rule set.
// ruleSet implements vm.ChainConfig and will always default to the homestead rule set.
type ruleSet struct{}
func (ruleSet) IsHomestead(*big.Int) bool { return true }
@@ -259,22 +259,22 @@ func (ruleSet) GasTable(*big.Int) params.GasTable {
return params.GasTableHomesteadGasRepriceFork
}
func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Db() vm.Database { return self.state }
func (self *VMEnv) SnapshotDatabase() int { return self.state.Snapshot() }
func (self *VMEnv) RevertToSnapshot(snap int) { self.state.RevertToSnapshot(snap) }
func (self *VMEnv) Origin() common.Address { return *self.transactor }
func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
func (self *VMEnv) Time() *big.Int { return self.time }
func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
func (self *VMEnv) Value() *big.Int { return self.value }
func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) }
func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy }
func (self *VMEnv) Depth() int { return 0 }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) ChainConfig() *params.ChainConfig { return params.TestChainConfig }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Db() vm.Database { return self.state }
func (self *VMEnv) SnapshotDatabase() int { return self.state.Snapshot() }
func (self *VMEnv) RevertToSnapshot(snap int) { self.state.RevertToSnapshot(snap) }
func (self *VMEnv) Origin() common.Address { return *self.transactor }
func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
func (self *VMEnv) Time() *big.Int { return self.time }
func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
func (self *VMEnv) Value() *big.Int { return self.value }
func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) }
func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy }
func (self *VMEnv) Depth() int { return 0 }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) GetHash(n uint64) common.Hash {
if self.block.Number().Cmp(big.NewInt(int64(n))) == 0 {
return self.block.Hash()
+1 -2
View File
@@ -23,7 +23,6 @@ import (
"os"
"os/signal"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
@@ -122,7 +121,7 @@ func MakeSystemNode(privkey string, test *tests.BlockTest) (*node.Node, error) {
ethConf := &eth.Config{
TestGenesisState: db,
TestGenesisBlock: test.Genesis,
ChainConfig: &core.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock},
ChainConfig: &params.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock},
}
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ethConf) }); err != nil {
return nil, err
+29 -9
View File
@@ -801,7 +801,7 @@ func SetupNetwork(ctx *cli.Context) {
}
// MakeChainConfig reads the chain configuration from the database in ctx.Datadir.
func MakeChainConfig(ctx *cli.Context, stack *node.Node) *core.ChainConfig {
func MakeChainConfig(ctx *cli.Context, stack *node.Node) *params.ChainConfig {
db := MakeChainDatabase(ctx, stack)
defer db.Close()
@@ -809,9 +809,9 @@ func MakeChainConfig(ctx *cli.Context, stack *node.Node) *core.ChainConfig {
}
// MakeChainConfigFromDb reads the chain configuration from the given database.
func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfig {
func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *params.ChainConfig {
// If the chain is already initialized, use any existing chain configs
config := new(core.ChainConfig)
config := new(params.ChainConfig)
genesis := core.GetBlock(db, core.GetCanonicalHash(db, 0), 0)
if genesis != nil {
@@ -825,6 +825,10 @@ func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfi
Fatalf("Could not make chain configuration: %v", err)
}
}
// set chain id in case it's zero.
if config.ChainId == nil {
config.ChainId = new(big.Int)
}
// Check whether we are allowed to set default config params or not:
// - If no genesis is set, we're running either mainnet or testnet (private nets use `geth init`)
// - If a genesis is already set, ensure we have a configuration for it (mainnet or testnet)
@@ -849,21 +853,37 @@ func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfi
}
config.DAOForkSupport = true
}
if config.HomesteadGasRepriceBlock == nil {
if config.EIP150Block == nil {
if ctx.GlobalBool(TestNetFlag.Name) {
config.HomesteadGasRepriceBlock = params.TestNetHomesteadGasRepriceBlock
config.EIP150Block = params.TestNetHomesteadGasRepriceBlock
} else {
config.HomesteadGasRepriceBlock = params.MainNetHomesteadGasRepriceBlock
config.EIP150Block = params.MainNetHomesteadGasRepriceBlock
}
}
if config.HomesteadGasRepriceHash == (common.Hash{}) {
if config.EIP150Hash == (common.Hash{}) {
if ctx.GlobalBool(TestNetFlag.Name) {
config.HomesteadGasRepriceHash = params.TestNetHomesteadGasRepriceHash
config.EIP150Hash = params.TestNetHomesteadGasRepriceHash
} else {
config.HomesteadGasRepriceHash = params.MainNetHomesteadGasRepriceHash
config.EIP150Hash = params.MainNetHomesteadGasRepriceHash
}
}
if config.EIP155Block == nil {
if ctx.GlobalBool(TestNetFlag.Name) {
config.EIP150Block = params.TestNetSpuriousDragon
} else {
config.EIP155Block = params.MainNetSpuriousDragon
}
}
if config.EIP158Block == nil {
if ctx.GlobalBool(TestNetFlag.Name) {
config.EIP158Block = params.TestNetSpuriousDragon
} else {
config.EIP158Block = params.MainNetSpuriousDragon
}
}
config.DAOForkSupport = true
}
// Force override any existing configs if explicitly requested
switch {
case ctx.GlobalBool(SupportDAOFork.Name):
+16 -19
View File
@@ -32,11 +32,12 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
)
// registryAPIBackend is a backend for an Ethereum Registry.
type registryAPIBackend struct {
config *core.ChainConfig
config *params.ChainConfig
bc *core.BlockChain
chainDb ethdb.Database
txPool *core.TxPool
@@ -45,12 +46,12 @@ type registryAPIBackend struct {
// PrivateRegistarAPI offers various functions to access the Ethereum registry.
type PrivateRegistarAPI struct {
config *core.ChainConfig
config *params.ChainConfig
be *registryAPIBackend
}
// NewPrivateRegistarAPI creates a new PrivateRegistarAPI instance.
func NewPrivateRegistarAPI(config *core.ChainConfig, bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI {
func NewPrivateRegistarAPI(config *params.ChainConfig, bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI {
return &PrivateRegistarAPI{
config: config,
be: &registryAPIBackend{
@@ -173,25 +174,20 @@ func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr
from.SetBalance(common.MaxBig)
msg := callmsg{
from: from,
gas: common.Big(gasStr),
gasPrice: common.Big(gasPriceStr),
value: common.Big(valueStr),
data: common.FromHex(dataStr),
}
var to *common.Address
if len(toStr) > 0 {
addr := common.HexToAddress(toStr)
msg.to = &addr
to = &addr
}
if msg.gas.Cmp(big.NewInt(0)) == 0 {
msg.gas = big.NewInt(50000000)
gas := common.Big(gasStr)
if gas.BitLen() == 0 {
gas = big.NewInt(50000000)
}
if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
gasPrice := common.Big(gasPriceStr)
if gasPrice.BitLen() == 0 {
gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
}
msg := types.NewMessage(from.Address(), to, 0, common.Big(valueStr), gas, gasPrice, common.FromHex(dataStr))
header := be.bc.CurrentBlock().Header()
vmenv := core.NewEnv(statedb, be.config, be.bc, msg, header, vm.Config{})
@@ -257,11 +253,12 @@ func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasSt
tx = types.NewTransaction(nonce, to, value, gas, price, data)
}
signature, err := be.am.SignEthereum(from, tx.SigHash().Bytes())
sigHash := (types.HomesteadSigner{}).Hash(tx)
signature, err := be.am.SignEthereum(from, sigHash.Bytes())
if err != nil {
return "", err
}
signedTx, err := tx.WithSignature(signature)
signedTx, err := tx.WithSignature(types.HomesteadSigner{}, signature)
if err != nil {
return "", err
}
+2 -2
View File
@@ -28,10 +28,10 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/internal/jsre"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
)
const (
@@ -97,7 +97,7 @@ func newTester(t *testing.T, confOverride func(*eth.Config)) *tester {
t.Fatalf("failed to create node: %v", err)
}
ethConf := &eth.Config{
ChainConfig: &core.ChainConfig{HomesteadBlock: new(big.Int)},
ChainConfig: &params.ChainConfig{HomesteadBlock: new(big.Int), ChainId: new(big.Int)},
Etherbase: common.HexToAddress(testAddress),
PowTest: true,
}
+4 -4
View File
@@ -83,7 +83,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
toaddr := common.Address{}
data := make([]byte, nbytes)
gas := IntrinsicGas(data, false, false)
tx, _ := types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data).SignECDSA(benchRootKey)
tx, _ := types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data).SignECDSA(types.HomesteadSigner{}, benchRootKey)
gen.AddTx(tx)
}
}
@@ -123,7 +123,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
nil,
nil,
)
tx, _ = tx.SignECDSA(ringKeys[from])
tx, _ = tx.SignECDSA(types.HomesteadSigner{}, ringKeys[from])
gen.AddTx(tx)
from = to
}
@@ -163,12 +163,12 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Generate a chain of b.N blocks using the supplied block
// generator function.
genesis := WriteGenesisBlockForTesting(db, GenesisAccount{benchRootAddr, benchRootFunds})
chain, _ := GenerateChain(nil, genesis, db, b.N, gen)
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, b.N, gen)
// Time the insertion of the new chain.
// State and blocks are stored in the same DB.
evmux := new(event.TypeMux)
chainman, _ := NewBlockChain(db, &ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux)
chainman, _ := NewBlockChain(db, &params.ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux)
defer chainman.Stop()
b.ReportAllocs()
b.ResetTimer()
+10 -10
View File
@@ -41,13 +41,13 @@ var (
//
// BlockValidator implements Validator.
type BlockValidator struct {
config *ChainConfig // Chain configuration options
bc *BlockChain // Canonical block chain
Pow pow.PoW // Proof of work used for validating
config *params.ChainConfig // Chain configuration options
bc *BlockChain // Canonical block chain
Pow pow.PoW // Proof of work used for validating
}
// NewBlockValidator returns a new block validator which is safe for re-use
func NewBlockValidator(config *ChainConfig, blockchain *BlockChain, pow pow.PoW) *BlockValidator {
func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, pow pow.PoW) *BlockValidator {
validator := &BlockValidator{
config: config,
Pow: pow,
@@ -128,7 +128,7 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat
}
// Validate the state root against the received state root and throw
// an error if they don't match.
if root := statedb.IntermediateRoot(); header.Root != root {
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
return fmt.Errorf("invalid merkle root: header=%x computed=%x", header.Root, root)
}
return nil
@@ -203,7 +203,7 @@ func (v *BlockValidator) ValidateHeader(header, parent *types.Header, checkPow b
// Validates a header. Returns an error if the header is invalid.
//
// See YP section 4.3.4. "Block Header Validity"
func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error {
func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error {
if big.NewInt(int64(len(header.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
return fmt.Errorf("Header extra data too long (%d)", len(header.Extra))
}
@@ -251,9 +251,9 @@ func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, pare
if err := ValidateDAOHeaderExtraData(config, header); err != nil {
return err
}
if config.HomesteadGasRepriceBlock != nil && config.HomesteadGasRepriceBlock.Cmp(header.Number) == 0 {
if config.HomesteadGasRepriceHash != (common.Hash{}) && config.HomesteadGasRepriceHash != header.Hash() {
return ValidationError("Homestead gas reprice fork hash mismatch: have 0x%x, want 0x%x", header.Hash(), config.HomesteadGasRepriceHash)
if config.EIP150Block != nil && config.EIP150Block.Cmp(header.Number) == 0 {
if config.EIP150Hash != (common.Hash{}) && config.EIP150Hash != header.Hash() {
return ValidationError("Homestead gas reprice fork hash mismatch: have 0x%x, want 0x%x", header.Hash(), config.EIP150Hash)
}
}
return nil
@@ -262,7 +262,7 @@ func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, pare
// CalcDifficulty is the difficulty adjustment algorithm. It returns
// the difficulty that a new block should have when created at time
// given the parent block's time and difficulty.
func CalcDifficulty(config *ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
func CalcDifficulty(config *params.ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
if config.IsHomestead(new(big.Int).Add(parentNumber, common.Big1)) {
return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff)
} else {
+7 -5
View File
@@ -27,11 +27,13 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow/ezp"
)
func testChainConfig() *ChainConfig {
return &ChainConfig{HomesteadBlock: big.NewInt(0)}
func testChainConfig() *params.ChainConfig {
return params.TestChainConfig
//return &params.ChainConfig{HomesteadBlock: big.NewInt(0)}
}
func proc() (Validator, *BlockChain) {
@@ -51,15 +53,15 @@ func TestNumber(t *testing.T) {
_, chain := proc()
statedb, _ := state.New(chain.Genesis().Root(), chain.chainDb)
header := makeHeader(chain.Genesis(), statedb)
header.Number = big.NewInt(3)
cfg := testChainConfig()
header := makeHeader(cfg, chain.Genesis(), statedb)
header.Number = big.NewInt(3)
err := ValidateHeader(cfg, pow, header, chain.Genesis().Header(), false, false)
if err != BlockNumberErr {
t.Errorf("expected block number error, got %q", err)
}
header = makeHeader(chain.Genesis(), statedb)
header = makeHeader(cfg, chain.Genesis(), statedb)
err = ValidateHeader(cfg, pow, header, chain.Genesis().Header(), false, false)
if err == BlockNumberErr {
t.Errorf("didn't expect block number error")
+14 -10
View File
@@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
@@ -78,7 +79,7 @@ const (
// included in the canonical one where as GetBlockByNumber always represents the
// canonical chain.
type BlockChain struct {
config *ChainConfig // chain & network configuration
config *params.ChainConfig // chain & network configuration
hc *HeaderChain
chainDb ethdb.Database
@@ -113,7 +114,7 @@ type BlockChain struct {
// NewBlockChain returns a fully initialised block chain using information
// available in the database. It initialiser the default Ethereum Validator and
// Processor.
func NewBlockChain(chainDb ethdb.Database, config *ChainConfig, pow pow.PoW, mux *event.TypeMux) (*BlockChain, error) {
func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.PoW, mux *event.TypeMux) (*BlockChain, error) {
bodyCache, _ := lru.New(bodyCacheLimit)
bodyRLPCache, _ := lru.New(bodyCacheLimit)
blockCache, _ := lru.New(blockCacheLimit)
@@ -633,17 +634,19 @@ func (self *BlockChain) Rollback(chain []common.Hash) {
}
// SetReceiptsData computes all the non-consensus fields of the receipts
func SetReceiptsData(block *types.Block, receipts types.Receipts) {
func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts types.Receipts) {
signer := types.MakeSigner(config, block.Number())
transactions, logIndex := block.Transactions(), uint(0)
for j := 0; j < len(receipts); j++ {
// The transaction hash can be retrieved from the transaction itself
receipts[j].TxHash = transactions[j].Hash()
tx, _ := transactions[j].AsMessage(signer)
// The contract address can be derived from the transaction itself
if MessageCreatesContract(transactions[j]) {
from, _ := transactions[j].From()
receipts[j].ContractAddress = crypto.CreateAddress(from, transactions[j].Nonce())
if MessageCreatesContract(tx) {
receipts[j].ContractAddress = crypto.CreateAddress(tx.From(), tx.Nonce())
}
// The used gas can be calculated based on previous receipts
if j == 0 {
@@ -665,6 +668,7 @@ func SetReceiptsData(block *types.Block, receipts types.Receipts) {
// InsertReceiptChain attempts to complete an already existing header chain with
// transaction and receipt data.
// XXX should this be moved to the test?
func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
self.wg.Add(1)
defer self.wg.Done()
@@ -704,7 +708,7 @@ func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain
continue
}
// Compute all the non-consensus fields of the receipts
SetReceiptsData(block, receipts)
SetReceiptsData(self.config, block, receipts)
// Write all the data out into the database
if err := WriteBody(self.chainDb, block.Hash(), block.NumberU64(), block.Body()); err != nil {
errs[index] = fmt.Errorf("failed to write block body: %v", err)
@@ -924,7 +928,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
return i, err
}
// Process block using the parent state as reference point.
receipts, logs, usedGas, err := self.processor.Process(block, self.stateCache, self.config.VmConfig)
receipts, logs, usedGas, err := self.processor.Process(block, self.stateCache, vm.Config{})
if err != nil {
reportBlock(block, err)
return i, err
@@ -936,7 +940,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
return i, err
}
// Write state changes to database
_, err = self.stateCache.Commit()
_, err = self.stateCache.Commit(self.config.IsEIP158(block.Number()))
if err != nil {
return i, err
}
@@ -1309,4 +1313,4 @@ func (self *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
}
// Config retrieves the blockchain's chain configuration.
func (self *BlockChain) Config() *ChainConfig { return self.config }
func (self *BlockChain) Config() *params.ChainConfig { return self.config }
+127 -21
View File
@@ -154,7 +154,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
blockchain.mu.Lock()
WriteTd(blockchain.chainDb, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash())))
WriteBlock(blockchain.chainDb, block)
statedb.Commit()
statedb.Commit(false)
blockchain.mu.Unlock()
}
return nil
@@ -711,14 +711,15 @@ func TestFastVsFullChains(t *testing.T) {
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
genesis = GenesisBlockForTesting(gendb, address, funds)
signer = types.NewEIP155Signer(big.NewInt(1))
)
blocks, receipts := GenerateChain(nil, genesis, gendb, 1024, func(i int, block *BlockGen) {
blocks, receipts := GenerateChain(params.TestChainConfig, genesis, gendb, 1024, func(i int, block *BlockGen) {
block.SetCoinbase(common.Address{0x00})
// If the block number is multiple of 3, send a few bonus transactions to the miner
if i%3 == 2 {
for j := 0; j < i%4+1; j++ {
tx, err := types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key)
tx, err := types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key)
if err != nil {
panic(err)
}
@@ -795,7 +796,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
genesis = GenesisBlockForTesting(gendb, address, funds)
)
height := uint64(1024)
blocks, receipts := GenerateChain(nil, genesis, gendb, int(height), nil)
blocks, receipts := GenerateChain(params.TestChainConfig, genesis, gendb, int(height), nil)
// Configure a subchain to roll back
remove := []common.Hash{}
@@ -872,6 +873,7 @@ func TestChainTxReorgs(t *testing.T) {
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
db, _ = ethdb.NewMemDatabase()
signer = types.NewEIP155Signer(big.NewInt(1))
)
genesis := WriteGenesisBlockForTesting(db,
GenesisAccount{addr1, big.NewInt(1000000)},
@@ -881,8 +883,8 @@ func TestChainTxReorgs(t *testing.T) {
// Create two transactions shared between the chains:
// - postponed: transaction included at a later block in the forked chain
// - swapped: transaction included at the same block number in the forked chain
postponed, _ := types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key1)
swapped, _ := types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key1)
postponed, _ := types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key1)
swapped, _ := types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key1)
// Create two transactions that will be dropped by the forked chain:
// - pastDrop: transaction dropped retroactively from a past block
@@ -895,16 +897,16 @@ func TestChainTxReorgs(t *testing.T) {
// - futureAdd: transaction added after the reorg has already finished
var pastAdd, freshAdd, futureAdd *types.Transaction
chain, _ := GenerateChain(nil, genesis, db, 3, func(i int, gen *BlockGen) {
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {
switch i {
case 0:
pastDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key2)
pastDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key2)
gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point
gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork
case 2:
freshDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key2)
freshDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key2)
gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point
gen.AddTx(swapped) // This transaction will be swapped out at the exact height
@@ -920,21 +922,21 @@ func TestChainTxReorgs(t *testing.T) {
}
// overwrite the old chain
chain, _ = GenerateChain(nil, genesis, db, 5, func(i int, gen *BlockGen) {
chain, _ = GenerateChain(params.TestChainConfig, genesis, db, 5, func(i int, gen *BlockGen) {
switch i {
case 0:
pastAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key3)
pastAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key3)
gen.AddTx(pastAdd) // This transaction needs to be injected during reorg
case 2:
gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain
gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain
freshAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key3)
freshAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key3)
gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time
case 3:
futureAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key3)
futureAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key3)
gen.AddTx(futureAdd) // This transaction will be added after a full reorg
}
})
@@ -980,7 +982,8 @@ func TestLogReorgs(t *testing.T) {
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
db, _ = ethdb.NewMemDatabase()
// this code generates a log
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
signer = types.NewEIP155Signer(big.NewInt(1))
)
genesis := WriteGenesisBlockForTesting(db,
GenesisAccount{addr1, big.NewInt(10000000000000)},
@@ -990,9 +993,9 @@ func TestLogReorgs(t *testing.T) {
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
subs := evmux.Subscribe(RemovedLogsEvent{})
chain, _ := GenerateChain(nil, genesis, db, 2, func(i int, gen *BlockGen) {
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 2, func(i int, gen *BlockGen) {
if i == 1 {
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code).SignECDSA(key1)
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code).SignECDSA(signer, key1)
if err != nil {
t.Fatalf("failed to create tx: %v", err)
}
@@ -1003,7 +1006,7 @@ func TestLogReorgs(t *testing.T) {
t.Fatalf("failed to insert chain: %v", err)
}
chain, _ = GenerateChain(nil, genesis, db, 3, func(i int, gen *BlockGen) {})
chain, _ = GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {})
if _, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert forked chain: %v", err)
}
@@ -1020,18 +1023,19 @@ func TestReorgSideEvent(t *testing.T) {
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
genesis = WriteGenesisBlockForTesting(db, GenesisAccount{addr1, big.NewInt(10000000000000)})
signer = types.NewEIP155Signer(big.NewInt(1))
)
evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
chain, _ := GenerateChain(nil, genesis, db, 3, func(i int, gen *BlockGen) {})
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {})
if _, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert chain: %v", err)
}
replacementBlocks, _ := GenerateChain(nil, genesis, db, 4, func(i int, gen *BlockGen) {
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil).SignECDSA(key1)
replacementBlocks, _ := GenerateChain(params.TestChainConfig, genesis, db, 4, func(i int, gen *BlockGen) {
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil).SignECDSA(signer, key1)
if i == 2 {
gen.OffsetTime(-1)
}
@@ -1101,7 +1105,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
chain, _ := GenerateChain(nil, genesis, db, 10, func(i int, gen *BlockGen) {})
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *BlockGen) {})
for i, _ := range chain {
go func(block *types.Block) {
@@ -1128,3 +1132,105 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
blockchain.InsertChain(types.Blocks{chain[i]})
}
}
func TestEIP155Transition(t *testing.T) {
// Configure and generate a sample block chain
var (
db, _ = ethdb.NewMemDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
genesis = WriteGenesisBlockForTesting(db, GenesisAccount{address, funds})
config = &params.ChainConfig{ChainId: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
mux event.TypeMux
)
blockchain, _ := NewBlockChain(db, config, FakePow{}, &mux)
blocks, _ := GenerateChain(config, genesis, db, 4, func(i int, block *BlockGen) {
var (
tx *types.Transaction
err error
basicTx = func(signer types.Signer) (*types.Transaction, error) {
return types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil).SignECDSA(signer, key)
}
)
switch i {
case 0:
tx, err = basicTx(types.HomesteadSigner{})
if err != nil {
t.Fatal(err)
}
block.AddTx(tx)
case 2:
tx, err = basicTx(types.HomesteadSigner{})
if err != nil {
t.Fatal(err)
}
block.AddTx(tx)
tx, err = basicTx(types.NewEIP155Signer(config.ChainId))
if err != nil {
t.Fatal(err)
}
block.AddTx(tx)
case 3:
tx, err = basicTx(types.HomesteadSigner{})
if err != nil {
t.Fatal(err)
}
block.AddTx(tx)
tx, err = basicTx(types.NewEIP155Signer(config.ChainId))
if err != nil {
t.Fatal(err)
}
block.AddTx(tx)
}
})
if _, err := blockchain.InsertChain(blocks); err != nil {
t.Fatal(err)
}
block := blockchain.GetBlockByNumber(1)
if block.Transactions()[0].Protected() {
t.Error("Expected block[0].txs[0] to not be replay protected")
}
block = blockchain.GetBlockByNumber(3)
if block.Transactions()[0].Protected() {
t.Error("Expected block[3].txs[0] to not be replay protected")
}
if !block.Transactions()[1].Protected() {
t.Error("Expected block[3].txs[1] to be replay protected")
}
if _, err := blockchain.InsertChain(blocks[4:]); err != nil {
t.Fatal(err)
}
// generate an invalid chain id transaction
config = &params.ChainConfig{ChainId: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
blocks, _ = GenerateChain(config, blocks[len(blocks)-1], db, 4, func(i int, block *BlockGen) {
var (
tx *types.Transaction
err error
basicTx = func(signer types.Signer) (*types.Transaction, error) {
return types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil).SignECDSA(signer, key)
}
)
switch i {
case 0:
tx, err = basicTx(types.NewEIP155Signer(big.NewInt(2)))
if err != nil {
t.Fatal(err)
}
block.AddTx(tx)
}
})
errExp := "Invalid transaction chain id. Current chain id: 1 tx chain id: 2"
_, err := blockchain.InsertChain(blocks)
if err == nil {
t.Error("expected transaction chain id error")
} else if err.Error() != errExp {
t.Error("expected:", errExp, "got:", err)
}
}
+12 -10
View File
@@ -35,8 +35,8 @@ import (
*/
// MakeChainConfig returns a new ChainConfig with the ethereum default chain settings.
func MakeChainConfig() *ChainConfig {
return &ChainConfig{
func MakeChainConfig() *params.ChainConfig {
return &params.ChainConfig{
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: true,
@@ -73,6 +73,8 @@ type BlockGen struct {
txs []*types.Transaction
receipts []*types.Receipt
uncles []*types.Header
config *params.ChainConfig
}
// SetCoinbase sets the coinbase of the generated block.
@@ -106,7 +108,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
b.SetCoinbase(common.Address{})
}
b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs))
receipt, _, _, err := ApplyTransaction(MakeChainConfig(), nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
receipt, _, _, err := ApplyTransaction(b.config, nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
if err != nil {
panic(err)
}
@@ -178,10 +180,10 @@ func (b *BlockGen) OffsetTime(seconds int64) {
// Blocks created by GenerateChain do not contain valid proof of work
// values. Inserting them into BlockChain requires use of FakePow or
// a similar non-validating proof of work implementation.
func GenerateChain(config *ChainConfig, parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
func GenerateChain(config *params.ChainConfig, parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
genblock := func(i int, h *types.Header, statedb *state.StateDB) (*types.Block, types.Receipts) {
b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb}
b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb, config: config}
// Mutate the state and block according to any hard-fork specs
if config == nil {
@@ -203,7 +205,7 @@ func GenerateChain(config *ChainConfig, parent *types.Block, db ethdb.Database,
gen(i, b)
}
AccumulateRewards(statedb, h, b.uncles)
root, err := statedb.Commit()
root, err := statedb.Commit(config.IsEIP158(h.Number))
if err != nil {
panic(fmt.Sprintf("state write error: %v", err))
}
@@ -215,7 +217,7 @@ func GenerateChain(config *ChainConfig, parent *types.Block, db ethdb.Database,
if err != nil {
panic(err)
}
header := makeHeader(parent, statedb)
header := makeHeader(config, parent, statedb)
block, receipt := genblock(i, header, statedb)
blocks[i] = block
receipts[i] = receipt
@@ -224,7 +226,7 @@ func GenerateChain(config *ChainConfig, parent *types.Block, db ethdb.Database,
return blocks, receipts
}
func makeHeader(parent *types.Block, state *state.StateDB) *types.Header {
func makeHeader(config *params.ChainConfig, parent *types.Block, state *state.StateDB) *types.Header {
var time *big.Int
if parent.Time() == nil {
time = big.NewInt(10)
@@ -232,7 +234,7 @@ func makeHeader(parent *types.Block, state *state.StateDB) *types.Header {
time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds
}
return &types.Header{
Root: state.IntermediateRoot(),
Root: state.IntermediateRoot(config.IsEIP158(parent.Number())),
ParentHash: parent.Hash(),
Coinbase: parent.Coinbase(),
Difficulty: CalcDifficulty(MakeChainConfig(), time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
@@ -283,7 +285,7 @@ func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) [
// makeBlockChain creates a deterministic chain of blocks rooted at parent.
func makeBlockChain(parent *types.Block, n int, db ethdb.Database, seed int) []*types.Block {
blocks, _ := GenerateChain(nil, parent, db, n, func(i int, b *BlockGen) {
blocks, _ := GenerateChain(params.TestChainConfig, parent, db, n, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
})
return blocks
+9 -5
View File
@@ -39,25 +39,29 @@ func ExampleGenerateChain() {
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
db, _ = ethdb.NewMemDatabase()
signer = types.HomesteadSigner{}
)
chainConfig := &params.ChainConfig{
HomesteadBlock: new(big.Int),
}
// Ensure that key1 has some funds in the genesis block.
genesis := WriteGenesisBlockForTesting(db, GenesisAccount{addr1, big.NewInt(1000000)})
// This call generates a chain of 5 blocks. The function runs for
// each block and adds different features to gen based on the
// block index.
chain, _ := GenerateChain(nil, genesis, db, 5, func(i int, gen *BlockGen) {
chain, _ := GenerateChain(chainConfig, genesis, db, 5, func(i int, gen *BlockGen) {
switch i {
case 0:
// In block 1, addr1 sends addr2 some ether.
tx, _ := types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(key1)
tx, _ := types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(signer, key1)
gen.AddTx(tx)
case 1:
// In block 2, addr1 sends some more ether to addr2.
// addr2 passes it on to addr3.
tx1, _ := types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key1)
tx2, _ := types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key2)
tx1, _ := types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key1)
tx2, _ := types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key2)
gen.AddTx(tx1)
gen.AddTx(tx2)
case 2:
@@ -77,7 +81,7 @@ func ExampleGenerateChain() {
// Import the chain. This runs all block validation rules.
evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux)
blockchain, _ := NewBlockChain(db, chainConfig, FakePow{}, evmux)
if i, err := blockchain.InsertChain(chain); err != nil {
fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err)
return
+4 -3
View File
@@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
)
@@ -60,7 +61,7 @@ func TestPowVerification(t *testing.T) {
var (
testdb, _ = ethdb.NewMemDatabase()
genesis = GenesisBlockForTesting(testdb, common.Address{}, new(big.Int))
blocks, _ = GenerateChain(nil, genesis, testdb, 8, nil)
blocks, _ = GenerateChain(params.TestChainConfig, genesis, testdb, 8, nil)
)
headers := make([]*types.Header, len(blocks))
for i, block := range blocks {
@@ -115,7 +116,7 @@ func testPowConcurrentVerification(t *testing.T, threads int) {
var (
testdb, _ = ethdb.NewMemDatabase()
genesis = GenesisBlockForTesting(testdb, common.Address{}, new(big.Int))
blocks, _ = GenerateChain(nil, genesis, testdb, 8, nil)
blocks, _ = GenerateChain(params.TestChainConfig, genesis, testdb, 8, nil)
)
headers := make([]*types.Header, len(blocks))
for i, block := range blocks {
@@ -186,7 +187,7 @@ func testPowConcurrentAbortion(t *testing.T, threads int) {
var (
testdb, _ = ethdb.NewMemDatabase()
genesis = GenesisBlockForTesting(testdb, common.Address{}, new(big.Int))
blocks, _ = GenerateChain(nil, genesis, testdb, 1024, nil)
blocks, _ = GenerateChain(params.TestChainConfig, genesis, testdb, 1024, nil)
)
headers := make([]*types.Header, len(blocks))
for i, block := range blocks {
-63
View File
@@ -1,63 +0,0 @@
// Copyright 2016 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 core
import (
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
)
var ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
// ChainConfig is the core config which determines the blockchain settings.
//
// ChainConfig is stored in the database on a per block basis. This means
// that any network, identified by its genesis block, can have its own
// set of configuration options.
type ChainConfig struct {
HomesteadBlock *big.Int `json:"homesteadBlock"` // Homestead switch block (nil = no fork, 0 = already homestead)
DAOForkBlock *big.Int `json:"daoForkBlock"` // TheDAO hard-fork switch block (nil = no fork)
DAOForkSupport bool `json:"daoForkSupport"` // Whether the nodes supports or opposes the DAO hard-fork
HomesteadGasRepriceBlock *big.Int `json:"homesteadGasRepriceBlock"` // Homestead gas reprice switch block (nil = no fork)
HomesteadGasRepriceHash common.Hash `json:"homesteadGasRepriceHash"` // Homestead gas reprice switch block hash (fast sync aid)
VmConfig vm.Config `json:"-"`
}
// IsHomestead returns whether num is either equal to the homestead block or greater.
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
if c.HomesteadBlock == nil || num == nil {
return false
}
return num.Cmp(c.HomesteadBlock) >= 0
}
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
//
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
func (c *ChainConfig) GasTable(num *big.Int) params.GasTable {
if c.HomesteadGasRepriceBlock == nil || num == nil || num.Cmp(c.HomesteadGasRepriceBlock) < 0 {
return params.GasTableHomestead
}
return params.GasTableHomesteadGasRepriceFork
}
+1 -1
View File
@@ -33,7 +33,7 @@ import (
// with the fork specific extra-data set
// b) if the node is pro-fork, require blocks in the specific range to have the
// unique extra-data set.
func ValidateDAOHeaderExtraData(config *ChainConfig, header *types.Header) error {
func ValidateDAOHeaderExtraData(config *params.ChainConfig, header *types.Header) error {
// Short circuit validation if the node doesn't care about the DAO fork
if config.DAOForkBlock == nil {
return nil
+3 -3
View File
@@ -33,17 +33,17 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Generate a common prefix for both pro-forkers and non-forkers
db, _ := ethdb.NewMemDatabase()
genesis := WriteGenesisBlockForTesting(db)
prefix, _ := GenerateChain(nil, genesis, db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {})
prefix, _ := GenerateChain(params.TestChainConfig, genesis, db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {})
// Create the concurrent, conflicting two nodes
proDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(proDb)
proConf := &ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: true}
proConf := &params.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: true}
proBc, _ := NewBlockChain(proDb, proConf, new(FakePow), new(event.TypeMux))
conDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(conDb)
conConf := &ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: false}
conConf := &params.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: false}
conBc, _ := NewBlockChain(conDb, conConf, new(FakePow), new(event.TypeMux))
if _, err := proBc.InsertChain(prefix); err != nil {
+7 -3
View File
@@ -20,6 +20,7 @@ import (
"bytes"
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"math/big"
@@ -28,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -59,6 +61,8 @@ var (
oldBlockNumPrefix = []byte("block-num-")
oldBlockReceiptsPrefix = []byte("receipts-block-")
oldBlockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
)
// encodeBlockNumber encodes a block number as big endian uint64
@@ -600,7 +604,7 @@ func WriteBlockChainVersion(db ethdb.Database, vsn int) {
}
// WriteChainConfig writes the chain config settings to the database.
func WriteChainConfig(db ethdb.Database, hash common.Hash, cfg *ChainConfig) error {
func WriteChainConfig(db ethdb.Database, hash common.Hash, cfg *params.ChainConfig) error {
// short circuit and ignore if nil config. GetChainConfig
// will return a default.
if cfg == nil {
@@ -616,13 +620,13 @@ func WriteChainConfig(db ethdb.Database, hash common.Hash, cfg *ChainConfig) err
}
// GetChainConfig will fetch the network settings based on the given hash.
func GetChainConfig(db ethdb.Database, hash common.Hash) (*ChainConfig, error) {
func GetChainConfig(db ethdb.Database, hash common.Hash) (*params.ChainConfig, error) {
jsonChainConfig, _ := db.Get(append(configPrefix, hash[:]...))
if len(jsonChainConfig) == 0 {
return nil, ChainConfigNotFoundErr
}
var config ChainConfig
var config params.ChainConfig
if err := json.Unmarshal(jsonChainConfig, &config); err != nil {
return nil, err
}
+3 -2
View File
@@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -75,7 +76,7 @@ func TestCalcDifficulty(t *testing.T) {
t.Fatal(err)
}
config := &ChainConfig{HomesteadBlock: big.NewInt(1150000)}
config := &params.ChainConfig{HomesteadBlock: big.NewInt(1150000)}
for name, test := range tests {
number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1))
diff := CalcDifficulty(config, test.CurrentTimestamp, test.ParentTimestamp, number, test.ParentDifficulty)
@@ -562,7 +563,7 @@ func TestMipmapChain(t *testing.T) {
defer db.Close()
genesis := WriteGenesisBlockForTesting(db, GenesisAccount{addr, big.NewInt(1000000)})
chain, receipts := GenerateChain(nil, genesis, db, 1010, func(i int, gen *BlockGen) {
chain, receipts := GenerateChain(params.TestChainConfig, genesis, db, 1010, func(i int, gen *BlockGen) {
var receipts types.Receipts
switch i {
case 1:
+117 -75
View File
@@ -27,62 +27,17 @@ import (
// Call executes within the given contract
func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
ret, _, err = exec(env, caller, &addr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, value)
return ret, err
}
// CallCode executes the given address' code as the given contract address
func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
callerAddr := caller.Address()
ret, _, err = exec(env, caller, &callerAddr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, value)
return ret, err
}
// DelegateCall is equivalent to CallCode except that sender and value propagates from parent scope to child scope
func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice *big.Int) (ret []byte, err error) {
callerAddr := caller.Address()
originAddr := env.Origin()
callerValue := caller.Value()
ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, callerValue)
return ret, err
}
// Create creates a new contract with the given code
func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) {
ret, address, err = exec(env, caller, nil, nil, crypto.Keccak256Hash(code), nil, code, gas, gasPrice, value)
// Here we get an error if we run into maximum stack depth,
// See: https://github.com/ethereum/yellowpaper/pull/131
// and YP definitions for CREATE instruction
if err != nil {
return nil, address, err
}
return ret, address, err
}
func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, vm.DepthError
return nil, vm.DepthError
}
if !env.CanTransfer(caller.Address(), value) {
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.Db().GetBalance(caller.Address()))
}
var createAccount bool
if address == nil {
// Create a new account on the state
nonce := env.Db().GetNonce(caller.Address())
env.Db().SetNonce(caller.Address(), nonce+1)
addr = crypto.CreateAddress(caller.Address(), nonce)
address = &addr
createAccount = true
return nil, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.Db().GetBalance(caller.Address()))
}
snapshotPreTransfer := env.SnapshotDatabase()
@@ -90,14 +45,15 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
from = env.Db().GetAccount(caller.Address())
to vm.Account
)
if createAccount {
to = env.Db().CreateAccount(*address)
} else {
if !env.Db().Exist(*address) {
to = env.Db().CreateAccount(*address)
} else {
to = env.Db().GetAccount(*address)
if !env.Db().Exist(addr) {
if vm.Precompiled[addr.Str()] == nil && env.ChainConfig().IsEIP158(env.BlockNumber()) && value.BitLen() == 0 {
caller.ReturnGas(gas, gasPrice)
return nil, nil
}
to = env.Db().CreateAccount(addr)
} else {
to = env.Db().GetAccount(addr)
}
env.Transfer(from, to, value)
@@ -105,19 +61,106 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
// EVM. The contract is a scoped environment for this execution context
// only.
contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(codeAddr, codeHash, code)
contract.SetCallCode(&addr, env.Db().GetCodeHash(addr), env.Db().GetCode(addr))
defer contract.Finalise()
ret, err = evm.Run(contract, input)
ret, err = env.Vm().Run(contract, input)
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in homestead this also counts for code storage gas errors.
if err != nil {
contract.UseGas(contract.Gas)
env.RevertToSnapshot(snapshotPreTransfer)
}
return ret, err
}
// CallCode executes the given address' code as the given contract address
func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(gas, gasPrice)
return nil, vm.DepthError
}
if !env.CanTransfer(caller.Address(), value) {
caller.ReturnGas(gas, gasPrice)
return nil, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.Db().GetBalance(caller.Address()))
}
var (
snapshotPreTransfer = env.SnapshotDatabase()
to = env.Db().GetAccount(caller.Address())
)
// initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped environment for this execution context
// only.
contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(&addr, env.Db().GetCodeHash(addr), env.Db().GetCode(addr))
defer contract.Finalise()
ret, err = env.Vm().Run(contract, input)
if err != nil {
contract.UseGas(contract.Gas)
env.RevertToSnapshot(snapshotPreTransfer)
}
return ret, err
}
// Create creates a new contract with the given code
func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, vm.DepthError
}
if !env.CanTransfer(caller.Address(), value) {
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.Db().GetBalance(caller.Address()))
}
// Create a new account on the state
nonce := env.Db().GetNonce(caller.Address())
env.Db().SetNonce(caller.Address(), nonce+1)
snapshotPreTransfer := env.SnapshotDatabase()
var (
addr = crypto.CreateAddress(caller.Address(), nonce)
from = env.Db().GetAccount(caller.Address())
to = env.Db().CreateAccount(addr)
)
if env.ChainConfig().IsEIP158(env.BlockNumber()) {
env.Db().SetNonce(addr, 1)
}
env.Transfer(from, to, value)
// initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped environment for this execution context
// only.
contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(&addr, crypto.Keccak256Hash(code), code)
defer contract.Finalise()
ret, err = env.Vm().Run(contract, nil)
// check whether the max code size has been exceeded
maxCodeSizeExceeded := len(ret) > params.MaxCodeSize
// if the contract creation ran successfully and no errors were returned
// calculate the gas required to store the code. If the code could not
// be stored due to not enough gas set an error and let it be handled
// by the error checking condition below.
if err == nil && createAccount {
if err == nil && !maxCodeSizeExceeded {
dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, params.CreateDataGas)
if contract.UseGas(dataGas) {
env.Db().SetCode(*address, ret)
env.Db().SetCode(addr, ret)
} else {
err = vm.CodeStoreOutOfGasError
}
@@ -126,46 +169,45 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in homestead this also counts for code storage gas errors.
if err != nil && (env.RuleSet().IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError) {
if maxCodeSizeExceeded ||
(err != nil && (env.ChainConfig().IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError)) {
contract.UseGas(contract.Gas)
env.RevertToSnapshot(snapshotPreTransfer)
// Nothing should be returned when an error is thrown.
return nil, addr, err
}
return ret, addr, err
}
func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
evm := env.Vm()
// DelegateCall is equivalent to CallCode except that sender and value propagates from parent scope to child scope
func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice *big.Int) (ret []byte, err error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, vm.DepthError
return nil, vm.DepthError
}
snapshot := env.SnapshotDatabase()
var to vm.Account
if !env.Db().Exist(*toAddr) {
to = env.Db().CreateAccount(*toAddr)
} else {
to = env.Db().GetAccount(*toAddr)
}
var (
snapshot = env.SnapshotDatabase()
to = env.Db().GetAccount(caller.Address())
)
// Iinitialise a new contract and make initialise the delegate values
contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate()
contract.SetCallCode(codeAddr, codeHash, code)
contract := vm.NewContract(caller, to, caller.Value(), gas, gasPrice).AsDelegate()
contract.SetCallCode(&addr, env.Db().GetCodeHash(addr), env.Db().GetCode(addr))
defer contract.Finalise()
ret, err = evm.Run(contract, input)
ret, err = env.Vm().Run(contract, input)
if err != nil {
contract.UseGas(contract.Gas)
env.RevertToSnapshot(snapshot)
}
return ret, addr, err
return ret, err
}
// generic transfer method
+3 -3
View File
@@ -43,7 +43,7 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
}
var genesis struct {
ChainConfig *ChainConfig `json:"config"`
ChainConfig *params.ChainConfig `json:"config"`
Nonce string
Timestamp string
ParentHash string
@@ -73,7 +73,7 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block,
statedb.SetState(address, common.HexToHash(key), common.HexToHash(value))
}
}
root, stateBatch := statedb.CommitBatch()
root, stateBatch := statedb.CommitBatch(false)
difficulty := common.String2Big(genesis.Difficulty)
block := types.NewBlock(&types.Header{
@@ -128,7 +128,7 @@ func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big
statedb, _ := state.New(common.Hash{}, db)
obj := statedb.GetOrNewStateObject(addr)
obj.SetBalance(balance)
root, err := statedb.Commit()
root, err := statedb.Commit(false)
if err != nil {
panic(fmt.Sprintf("cannot write state: %v", err))
}
+5 -4
View File
@@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/hashicorp/golang-lru"
)
@@ -48,7 +49,7 @@ const (
// It is not thread safe either, the encapsulating chain structures should do
// the necessary mutex locking/unlocking.
type HeaderChain struct {
config *ChainConfig
config *params.ChainConfig
chainDb ethdb.Database
genesisHeader *types.Header
@@ -73,7 +74,7 @@ type getHeaderValidatorFn func() HeaderValidator
// getValidator should return the parent's validator
// procInterrupt points to the parent's interrupt semaphore
// wg points to the parent's shutdown wait group
func NewHeaderChain(chainDb ethdb.Database, config *ChainConfig, getValidator getHeaderValidatorFn, procInterrupt func() bool) (*HeaderChain, error) {
func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, getValidator getHeaderValidatorFn, procInterrupt func() bool) (*HeaderChain, error) {
headerCache, _ := lru.New(headerCacheLimit)
tdCache, _ := lru.New(tdCacheLimit)
numberCache, _ := lru.New(numberCacheLimit)
@@ -490,13 +491,13 @@ func (hc *HeaderChain) SetGenesis(head *types.Header) {
//
// headerValidator implements HeaderValidator.
type headerValidator struct {
config *ChainConfig
config *params.ChainConfig
hc *HeaderChain // Canonical header chain
Pow pow.PoW // Proof of work used for validating
}
// NewBlockValidator returns a new block validator which is safe for re-use
func NewHeaderValidator(config *ChainConfig, chain *HeaderChain, pow pow.PoW) HeaderValidator {
func NewHeaderValidator(config *params.ChainConfig, chain *HeaderChain, pow pow.PoW) HeaderValidator {
return &headerValidator{
config: config,
Pow: pow,
+12 -1
View File
@@ -91,6 +91,11 @@ type StateObject struct {
onDirty func(addr common.Address) // Callback method to mark a state object newly dirty
}
// empty returns whether the account is considered empty.
func (s *StateObject) empty() bool {
return s.data.Nonce == 0 && s.data.Balance.BitLen() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash)
}
// Account is the Ethereum consensus representation of accounts.
// These objects are stored in the main account trie.
type Account struct {
@@ -221,8 +226,12 @@ func (self *StateObject) CommitTrie(db trie.Database, dbw trie.DatabaseWriter) e
return err
}
// AddBalance removes amount from c's balance.
// It is used to add funds to the destination account of a transfer.
func (c *StateObject) AddBalance(amount *big.Int) {
if amount.Cmp(common.Big0) == 0 {
// EIP158: We must check emptiness for the objects such that the account
// clearing (0,0,0 objects) can take effect.
if amount.Cmp(common.Big0) == 0 && !c.empty() {
return
}
c.SetBalance(new(big.Int).Add(c.Balance(), amount))
@@ -232,6 +241,8 @@ func (c *StateObject) AddBalance(amount *big.Int) {
}
}
// SubBalance removes amount from c's balance.
// It is used to remove funds from the origin account of a transfer.
func (c *StateObject) SubBalance(amount *big.Int) {
if amount.Cmp(common.Big0) == 0 {
return
+3 -3
View File
@@ -48,7 +48,7 @@ func (s *StateSuite) TestDump(c *checker.C) {
// write some of them to the trie
s.state.updateStateObject(obj1)
s.state.updateStateObject(obj2)
s.state.Commit()
s.state.Commit(false)
// check that dump contains the state objects that are in trie
got := string(s.state.Dump())
@@ -100,7 +100,7 @@ func TestNull(t *testing.T) {
//value := common.FromHex("0x823140710bf13990e4500136726d8b55")
var value common.Hash
state.SetState(address, common.Hash{}, value)
state.Commit()
state.Commit(false)
value = state.GetState(address, common.Hash{})
if !common.EmptyHash(value) {
t.Errorf("expected empty hash. got %x", value)
@@ -160,7 +160,7 @@ func TestSnapshot2(t *testing.T) {
so0.deleted = false
state.setStateObject(so0)
root, _ := state.Commit()
root, _ := state.Commit(false)
state.Reset(root)
// and one with deleted == true
+18 -9
View File
@@ -213,6 +213,13 @@ func (self *StateDB) Exist(addr common.Address) bool {
return self.GetStateObject(addr) != nil
}
// Empty returns whether the state object is either non-existant
// or empty according to the EIP161 specification (balance = nonce = code = 0)
func (self *StateDB) Empty(addr common.Address) bool {
so := self.GetStateObject(addr)
return so == nil || so.empty()
}
func (self *StateDB) GetAccount(addr common.Address) vm.Account {
return self.GetStateObject(addr)
}
@@ -516,10 +523,10 @@ func (self *StateDB) GetRefund() *big.Int {
// IntermediateRoot computes the current root hash of the state trie.
// It is called in between transactions to get the root hash that
// goes into transaction receipts.
func (s *StateDB) IntermediateRoot() common.Hash {
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
for addr, _ := range s.stateObjectsDirty {
stateObject := s.stateObjects[addr]
if stateObject.suicided {
if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) {
s.deleteStateObject(stateObject)
} else {
stateObject.updateRoot(s.db)
@@ -553,17 +560,17 @@ func (s *StateDB) DeleteSuicides() {
}
// Commit commits all state changes to the database.
func (s *StateDB) Commit() (root common.Hash, err error) {
root, batch := s.CommitBatch()
func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) {
root, batch := s.CommitBatch(deleteEmptyObjects)
return root, batch.Write()
}
// CommitBatch commits all state changes to a write batch but does not
// execute the batch. It is used to validate state changes against
// the root hash stored in a block.
func (s *StateDB) CommitBatch() (root common.Hash, batch ethdb.Batch) {
func (s *StateDB) CommitBatch(deleteEmptyObjects bool) (root common.Hash, batch ethdb.Batch) {
batch = s.db.NewBatch()
root, _ = s.commit(batch)
root, _ = s.commit(batch, deleteEmptyObjects)
glog.V(logger.Debug).Infof("Trie cache stats: %d misses, %d unloads", trie.CacheMisses(), trie.CacheUnloads())
return root, batch
@@ -575,16 +582,18 @@ func (s *StateDB) clearJournalAndRefund() {
s.refund = new(big.Int)
}
func (s *StateDB) commit(dbw trie.DatabaseWriter) (root common.Hash, err error) {
func (s *StateDB) commit(dbw trie.DatabaseWriter, deleteEmptyObjects bool) (root common.Hash, err error) {
defer s.clearJournalAndRefund()
// Commit objects to the trie.
for addr, stateObject := range s.stateObjects {
if stateObject.suicided {
_, isDirty := s.stateObjectsDirty[addr]
switch {
case stateObject.suicided || (isDirty && deleteEmptyObjects && stateObject.empty()):
// If the object has been removed, don't bother syncing it
// and just mark it for deletion in the trie.
s.deleteStateObject(stateObject)
} else if _, ok := s.stateObjectsDirty[addr]; ok {
case isDirty:
// Write any contract code associated with the state object
if stateObject.code != nil && stateObject.dirtyCode {
if err := dbw.Put(stateObject.CodeHash(), stateObject.code); err != nil {
+4 -4
View File
@@ -51,7 +51,7 @@ func TestUpdateLeaks(t *testing.T) {
if i%3 == 0 {
state.SetCode(addr, []byte{i, i, i, i, i})
}
state.IntermediateRoot()
state.IntermediateRoot(false)
}
// Ensure that no data was leaked into the database
for _, key := range db.Keys() {
@@ -86,7 +86,7 @@ func TestIntermediateLeaks(t *testing.T) {
modify(transState, common.Address{byte(i)}, i, 0)
}
// Write modifications to trie.
transState.IntermediateRoot()
transState.IntermediateRoot(false)
// Overwrite all the data with new values in the transient database.
for i := byte(0); i < 255; i++ {
@@ -95,10 +95,10 @@ func TestIntermediateLeaks(t *testing.T) {
}
// Commit and cross check the databases.
if _, err := transState.Commit(); err != nil {
if _, err := transState.Commit(false); err != nil {
t.Fatalf("failed to commit transition state: %v", err)
}
if _, err := finalState.Commit(); err != nil {
if _, err := finalState.Commit(false); err != nil {
t.Fatalf("failed to commit final state: %v", err)
}
for _, key := range finalDb.Keys() {
+1 -1
View File
@@ -60,7 +60,7 @@ func makeTestState() (ethdb.Database, common.Hash, []*testAccount) {
state.updateStateObject(obj)
accounts = append(accounts, acc)
}
root, _ := state.Commit()
root, _ := state.Commit(false)
// Return the generated state
return db, root, accounts
+19 -9
View File
@@ -17,6 +17,7 @@
package core
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/core/state"
@@ -25,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
)
var (
@@ -37,12 +39,12 @@ var (
//
// StateProcessor implements Processor.
type StateProcessor struct {
config *ChainConfig
config *params.ChainConfig
bc *BlockChain
}
// NewStateProcessor initialises a new StateProcessor.
func NewStateProcessor(config *ChainConfig, bc *BlockChain) *StateProcessor {
func NewStateProcessor(config *params.ChainConfig, bc *BlockChain) *StateProcessor {
return &StateProcessor{
config: config,
bc: bc,
@@ -71,10 +73,14 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
}
// Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
if tx.Protected() && tx.ChainId().Cmp(p.config.ChainId) != 0 {
return nil, nil, nil, fmt.Errorf("Invalid transaction chain id. Current chain id: %v tx chain id: %v", p.config.ChainId, tx.ChainId())
}
statedb.StartRecord(tx.Hash(), block.Hash(), i)
receipt, logs, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
if err != nil {
return nil, nil, totalUsedGas, err
return nil, nil, nil, err
}
receipts = append(receipts, receipt)
allLogs = append(allLogs, logs...)
@@ -89,20 +95,24 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
//
// ApplyTransactions returns the generated receipts and vm logs during the
// execution of the state transition phase.
func ApplyTransaction(config *ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
_, gas, err := ApplyMessage(NewEnv(statedb, config, bc, tx, header, cfg), tx, gp)
func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
if err != nil {
return nil, nil, nil, err
}
_, gas, err := ApplyMessage(NewEnv(statedb, config, bc, msg, header, cfg), msg, gp)
if err != nil {
return nil, nil, nil, err
}
// Update the state with pending changes
usedGas.Add(usedGas, gas)
receipt := types.NewReceipt(statedb.IntermediateRoot().Bytes(), usedGas)
receipt := types.NewReceipt(statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes(), usedGas)
receipt.TxHash = tx.Hash()
receipt.GasUsed = new(big.Int).Set(gas)
if MessageCreatesContract(tx) {
from, _ := tx.From()
receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce())
if MessageCreatesContract(msg) {
receipt.ContractAddress = crypto.CreateAddress(msg.From(), tx.Nonce())
}
logs := statedb.GetLogs(tx.Hash())
+12 -29
View File
@@ -62,8 +62,8 @@ type StateTransition struct {
// Message represents a message sent to a contract.
type Message interface {
From() (common.Address, error)
FromFrontier() (common.Address, error)
From() common.Address
//FromFrontier() (common.Address, error)
To() *common.Address
GasPrice() *big.Int
@@ -134,23 +134,12 @@ func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.In
return ret, gasUsed, err
}
func (self *StateTransition) from() (vm.Account, error) {
var (
f common.Address
err error
)
if self.env.RuleSet().IsHomestead(self.env.BlockNumber()) {
f, err = self.msg.From()
} else {
f, err = self.msg.FromFrontier()
}
if err != nil {
return nil, err
}
func (self *StateTransition) from() vm.Account {
f := self.msg.From()
if !self.state.Exist(f) {
return self.state.CreateAccount(f), nil
return self.state.CreateAccount(f)
}
return self.state.GetAccount(f), nil
return self.state.GetAccount(f)
}
func (self *StateTransition) to() vm.Account {
@@ -185,14 +174,11 @@ func (self *StateTransition) buyGas() error {
mgas := self.msg.Gas()
mgval := new(big.Int).Mul(mgas, self.gasPrice)
sender, err := self.from()
if err != nil {
return err
}
sender := self.from()
if sender.Balance().Cmp(mgval) < 0 {
return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address().Bytes()[:4], mgval, sender.Balance())
}
if err = self.gp.SubGas(mgas); err != nil {
if err := self.gp.SubGas(mgas); err != nil {
return err
}
self.addGas(mgas)
@@ -203,10 +189,7 @@ func (self *StateTransition) buyGas() error {
func (self *StateTransition) preCheck() (err error) {
msg := self.msg
sender, err := self.from()
if err != nil {
return err
}
sender := self.from()
// Make sure this transaction's nonce is correct
if msg.CheckNonce() {
@@ -232,9 +215,9 @@ func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *b
return
}
msg := self.msg
sender, _ := self.from() // err checked in preCheck
sender := self.from() // err checked in preCheck
homestead := self.env.RuleSet().IsHomestead(self.env.BlockNumber())
homestead := self.env.ChainConfig().IsHomestead(self.env.BlockNumber())
contractCreation := MessageCreatesContract(msg)
// Pay intrinsic gas
if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil {
@@ -282,7 +265,7 @@ func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *b
func (self *StateTransition) refundGas() {
// Return eth for remaining gas to the sender account,
// exchanged at the original rate.
sender, _ := self.from() // err already checked
sender := self.from() // err already checked
remaining := new(big.Int).Mul(self.gas, self.gasPrice)
sender.AddBalance(remaining)
+14 -9
View File
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
)
@@ -83,7 +84,7 @@ type stateFn func() (*state.StateDB, error)
// current state) and future transactions. Transactions move between those
// two states over time as they are received and processed.
type TxPool struct {
config *ChainConfig
config *params.ChainConfig
currentState stateFn // The state function which will allow us to do some pre checks
pendingState *state.ManagedState
gasLimit func() *big.Int // The current gas limit function callback
@@ -91,6 +92,7 @@ type TxPool struct {
eventMux *event.TypeMux
events event.Subscription
localTx *txSet
signer types.Signer
mu sync.RWMutex
pending map[common.Address]*txList // All currently processable transactions
@@ -104,9 +106,10 @@ type TxPool struct {
homestead bool
}
func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool {
func NewTxPool(config *params.ChainConfig, eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool {
pool := &TxPool{
config: config,
signer: types.NewEIP155Signer(config.ChainId),
pending: make(map[common.Address]*txList),
queue: make(map[common.Address]*txList),
all: make(map[common.Hash]*types.Transaction),
@@ -138,8 +141,10 @@ func (pool *TxPool) eventLoop() {
switch ev := ev.Data.(type) {
case ChainHeadEvent:
pool.mu.Lock()
if ev.Block != nil && pool.config.IsHomestead(ev.Block.Number()) {
pool.homestead = true
if ev.Block != nil {
if pool.config.IsHomestead(ev.Block.Number()) {
pool.homestead = true
}
}
pool.resetState()
@@ -271,7 +276,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
return err
}
from, err := tx.From()
from, err := types.Sender(pool.signer, tx)
if err != nil {
return ErrInvalidSender
}
@@ -306,7 +311,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
return ErrInsufficientFunds
}
intrGas := IntrinsicGas(tx.Data(), MessageCreatesContract(tx), pool.homestead)
intrGas := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
if tx.Gas().Cmp(intrGas) < 0 {
return ErrIntrinsicGas
}
@@ -335,7 +340,7 @@ func (pool *TxPool) add(tx *types.Transaction) error {
if to := tx.To(); to != nil {
rcpt = common.Bytes2Hex(to[:4])
}
from, _ := tx.From() // from already verified during tx validation
from, _ := types.Sender(pool.signer, tx) // from already verified during tx validation
glog.Infof("(t) 0x%x => %s (%v) %x\n", from[:4], rcpt, tx.Value, hash)
}
return nil
@@ -346,7 +351,7 @@ func (pool *TxPool) add(tx *types.Transaction) error {
// Note, this method assumes the pool lock is held!
func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction) {
// Try to insert the transaction into the future queue
from, _ := tx.From() // already validated
from, _ := types.Sender(pool.signer, tx) // already validated
if pool.queue[from] == nil {
pool.queue[from] = newTxList(false)
}
@@ -458,7 +463,7 @@ func (pool *TxPool) removeTx(hash common.Hash) {
if !ok {
return
}
addr, _ := tx.From() // already validated during insertion
addr, _ := types.Sender(pool.signer, tx) // already validated during insertion
// Remove it from the list of known transactions
delete(pool.all, hash)
+28 -23
View File
@@ -32,7 +32,7 @@ import (
)
func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
tx, _ := types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, big.NewInt(1), nil).SignECDSA(key)
tx, _ := types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, big.NewInt(1), nil).SignECDSA(types.HomesteadSigner{}, key)
return tx
}
@@ -47,6 +47,10 @@ func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
return newPool, key
}
func deriveSender(tx *types.Transaction) (common.Address, error) {
return types.Sender(types.HomesteadSigner{}, tx)
}
func TestInvalidTransactions(t *testing.T) {
pool, key := setupTxPool()
@@ -55,7 +59,7 @@ func TestInvalidTransactions(t *testing.T) {
t.Error("expected", ErrNonExistentAccount)
}
from, _ := tx.From()
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1))
if err := pool.Add(tx); err != ErrInsufficientFunds {
@@ -90,7 +94,7 @@ func TestInvalidTransactions(t *testing.T) {
func TestTransactionQueue(t *testing.T) {
pool, key := setupTxPool()
tx := transaction(0, big.NewInt(100), key)
from, _ := tx.From()
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1000))
pool.enqueueTx(tx.Hash(), tx)
@@ -101,7 +105,7 @@ func TestTransactionQueue(t *testing.T) {
}
tx = transaction(1, big.NewInt(100), key)
from, _ = tx.From()
from, _ = deriveSender(tx)
currentState.SetNonce(from, 2)
pool.enqueueTx(tx.Hash(), tx)
pool.promoteExecutables()
@@ -117,7 +121,7 @@ func TestTransactionQueue(t *testing.T) {
tx1 := transaction(0, big.NewInt(100), key)
tx2 := transaction(10, big.NewInt(100), key)
tx3 := transaction(11, big.NewInt(100), key)
from, _ = tx1.From()
from, _ = deriveSender(tx1)
currentState, _ = pool.currentState()
currentState.AddBalance(from, big.NewInt(1000))
pool.enqueueTx(tx1.Hash(), tx1)
@@ -137,7 +141,7 @@ func TestTransactionQueue(t *testing.T) {
func TestRemoveTx(t *testing.T) {
pool, key := setupTxPool()
tx := transaction(0, big.NewInt(100), key)
from, _ := tx.From()
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1))
@@ -161,8 +165,8 @@ func TestRemoveTx(t *testing.T) {
func TestNegativeValue(t *testing.T) {
pool, key := setupTxPool()
tx, _ := types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil).SignECDSA(key)
from, _ := tx.From()
tx, _ := types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil).SignECDSA(types.HomesteadSigner{}, key)
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1))
if err := pool.Add(tx); err != ErrNegativeValue {
@@ -209,9 +213,10 @@ func TestTransactionDoubleNonce(t *testing.T) {
}
resetState()
tx1, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), nil).SignECDSA(key)
tx2, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(2), nil).SignECDSA(key)
tx3, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(1), nil).SignECDSA(key)
signer := types.HomesteadSigner{}
tx1, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), nil).SignECDSA(signer, key)
tx2, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(2), nil).SignECDSA(signer, key)
tx3, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(1), nil).SignECDSA(signer, key)
// Add the first two transaction, ensure higher priced stays only
if err := pool.add(tx1); err != nil {
@@ -287,7 +292,7 @@ func TestNonceRecovery(t *testing.T) {
func TestRemovedTxEvent(t *testing.T) {
pool, key := setupTxPool()
tx := transaction(0, big.NewInt(1000000), key)
from, _ := tx.From()
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1000000000000))
pool.eventMux.Post(RemovedTransactionEvent{types.Transactions{tx}})
@@ -305,7 +310,7 @@ func TestRemovedTxEvent(t *testing.T) {
func TestTransactionDropping(t *testing.T) {
// Create a test account and fund it
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := deriveSender(transaction(0, big.NewInt(0), key))
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000))
@@ -369,7 +374,7 @@ func TestTransactionDropping(t *testing.T) {
func TestTransactionPostponing(t *testing.T) {
// Create a test account and fund it
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := deriveSender(transaction(0, big.NewInt(0), key))
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000))
@@ -443,7 +448,7 @@ func TestTransactionPostponing(t *testing.T) {
func TestTransactionQueueAccountLimiting(t *testing.T) {
// Create a test account and fund it
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := deriveSender(transaction(0, big.NewInt(0), key))
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
@@ -531,7 +536,7 @@ func TestTransactionQueueTimeLimiting(t *testing.T) {
// Create a test account and fund it
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := deriveSender(transaction(0, big.NewInt(0), key))
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
@@ -555,7 +560,7 @@ func TestTransactionQueueTimeLimiting(t *testing.T) {
func TestTransactionPendingLimiting(t *testing.T) {
// Create a test account and fund it
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := deriveSender(transaction(0, big.NewInt(0), key))
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
@@ -585,7 +590,7 @@ func TestTransactionPendingLimitingEquivalency(t *testing.T) { testTransactionLi
func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
// Add a batch of transactions to a pool one by one
pool1, key1 := setupTxPool()
account1, _ := transaction(0, big.NewInt(0), key1).From()
account1, _ := deriveSender(transaction(0, big.NewInt(0), key1))
state1, _ := pool1.currentState()
state1.AddBalance(account1, big.NewInt(1000000))
@@ -596,7 +601,7 @@ func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
}
// Add a batch of transactions to a pool in one big batch
pool2, key2 := setupTxPool()
account2, _ := transaction(0, big.NewInt(0), key2).From()
account2, _ := deriveSender(transaction(0, big.NewInt(0), key2))
state2, _ := pool2.currentState()
state2.AddBalance(account2, big.NewInt(1000000))
@@ -717,7 +722,7 @@ func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 1
func benchmarkPendingDemotion(b *testing.B, size int) {
// Add a batch of transactions to a pool one by one
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := deriveSender(transaction(0, big.NewInt(0), key))
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
@@ -741,7 +746,7 @@ func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 1
func benchmarkFuturePromotion(b *testing.B, size int) {
// Add a batch of transactions to a pool one by one
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := deriveSender(transaction(0, big.NewInt(0), key))
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
@@ -760,7 +765,7 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
func BenchmarkPoolInsert(b *testing.B) {
// Generate a batch of transactions to enqueue into the pool
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := deriveSender(transaction(0, big.NewInt(0), key))
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
@@ -783,7 +788,7 @@ func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 1
func benchmarkPoolBatchInsert(b *testing.B, size int) {
// Generate a batch of transactions to enqueue into the pool
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := deriveSender(transaction(0, big.NewInt(0), key))
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
+6 -1
View File
@@ -18,6 +18,7 @@ package types
import (
"bytes"
"fmt"
"math/big"
"reflect"
"testing"
@@ -51,7 +52,11 @@ func TestBlockEncoding(t *testing.T) {
check("Size", block.Size(), common.StorageSize(len(blockEnc)))
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), big.NewInt(50000), big.NewInt(10), nil)
tx1, _ = tx1.WithSignature(common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b11b"))
tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b11b"))
fmt.Println(block.Transactions()[0].Hash())
fmt.Println(tx1.data)
fmt.Println(tx1.Hash())
check("len(Transactions)", len(block.Transactions()), 1)
check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash())
+4 -1
View File
@@ -97,10 +97,12 @@ var unmarshalTransactionTests = map[string]struct {
wantHash: common.HexToHash("0xd91c08f1e27c5ce7e1f57d78d7c56a9ee446be07b9635d84d0475660ea8905e9"),
wantFrom: common.HexToAddress("0xf36c3f6c4a2ce8d353fb92d5cd10d19ce69ae689"),
},
/* TODO skipping this test as this type can not be tested with the current signing approach
"bad signature fields": {
input: `{"blockHash":"0x0188a05dcc825bd1a05dab91bea0c03622542683446e56302eabb46097d4ae11","blockNumber":"0x1e478d","from":"0xf36c3f6c4a2ce8d353fb92d5cd10d19ce69ae689","gas":"0x15f90","gasPrice":"0x4a817c800","hash":"0xd91c08f1e27c5ce7e1f57d78d7c56a9ee446be07b9635d84d0475660ea8905e9","input":"0x","nonce":"0x58d","to":"0x88f252f674ac755feff877abf957d4aa05adce86","transactionIndex":"0x1","value":"0x19f0ec3ed71ec00","v":"0x58","r":"0x53829f206c99b866672f987909d556cd1c2eb60e990a3425f65083977c14187b","s":"0x5cc52383e41c923ec7d63749c1f13a7236b540527ee5b9a78b3fb869a66f60e"}`,
wantError: ErrInvalidSig,
},
*/
"missing signature v": {
input: `{"blockHash":"0x0188a05dcc825bd1a05dab91bea0c03622542683446e56302eabb46097d4ae11","blockNumber":"0x1e478d","from":"0xf36c3f6c4a2ce8d353fb92d5cd10d19ce69ae689","gas":"0x15f90","gasPrice":"0x4a817c800","hash":"0xd91c08f1e27c5ce7e1f57d78d7c56a9ee446be07b9635d84d0475660ea8905e9","input":"0x","nonce":"0x58d","to":"0x88f252f674ac755feff877abf957d4aa05adce86","transactionIndex":"0x1","value":"0x19f0ec3ed71ec00","r":"0x53829f206c99b866672f987909d556cd1c2eb60e990a3425f65083977c14187b","s":"0x5cc52383e41c923ec7d63749c1f13a7236b540527ee5b9a78b3fb869a66f60e"}`,
wantError: errMissingTxSignatureFields,
@@ -122,11 +124,12 @@ func TestUnmarshalTransaction(t *testing.T) {
if !checkError(t, name, err, test.wantError) {
continue
}
if tx.Hash() != test.wantHash {
t.Errorf("test %q: got hash %x, want %x", name, tx.Hash(), test.wantHash)
continue
}
from, err := tx.From()
from, err := Sender(HomesteadSigner{}, tx)
if err != nil {
t.Errorf("test %q: From error %v", name, err)
}
+164 -108
View File
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -36,8 +37,18 @@ var ErrInvalidSig = errors.New("invalid transaction v, r, s values")
var (
errMissingTxSignatureFields = errors.New("missing required JSON transaction signature fields")
errMissingTxFields = errors.New("missing required JSON transaction fields")
errNoSigner = errors.New("missing signing methods")
)
// deriveSigner makes a *best* guess about which signer to use.
func deriveSigner(V *big.Int) Signer {
if V.BitLen() > 0 && isProtectedV(V) {
return EIP155Signer{chainId: deriveChainId(V)}
} else {
return HomesteadSigner{}
}
}
type Transaction struct {
data txdata
// caches
@@ -52,7 +63,7 @@ type txdata struct {
Recipient *common.Address `rlp:"nil"` // nil means contract creation
Amount *big.Int
Payload []byte
V byte // signature
V *big.Int // signature
R, S *big.Int // signature
}
@@ -64,40 +75,31 @@ type jsonTransaction struct {
Recipient *common.Address `json:"to"`
Amount *hexBig `json:"value"`
Payload *hexBytes `json:"input"`
V *hexUint64 `json:"v"`
V *hexBig `json:"v"`
R *hexBig `json:"r"`
S *hexBig `json:"s"`
}
// NewContractCreation creates a new transaction with no recipient.
func NewContractCreation(nonce uint64, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
if len(data) > 0 {
data = common.CopyBytes(data)
}
return &Transaction{data: txdata{
AccountNonce: nonce,
Recipient: nil,
Amount: new(big.Int).Set(amount),
GasLimit: new(big.Int).Set(gasLimit),
Price: new(big.Int).Set(gasPrice),
Payload: data,
R: new(big.Int),
S: new(big.Int),
}}
func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
return newTransaction(nonce, &to, amount, gasLimit, gasPrice, data)
}
// NewTransaction creates a new transaction with the given fields.
func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
func NewContractCreation(nonce uint64, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
return newTransaction(nonce, nil, amount, gasLimit, gasPrice, data)
}
func newTransaction(nonce uint64, to *common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
if len(data) > 0 {
data = common.CopyBytes(data)
}
d := txdata{
AccountNonce: nonce,
Recipient: &to,
Recipient: to,
Payload: data,
Amount: new(big.Int),
GasLimit: new(big.Int),
Price: new(big.Int),
V: new(big.Int),
R: new(big.Int),
S: new(big.Int),
}
@@ -110,9 +112,42 @@ func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice
if gasPrice != nil {
d.Price.Set(gasPrice)
}
return &Transaction{data: d}
}
func pickSigner(rules params.Rules) Signer {
var signer Signer
switch {
case rules.IsEIP155:
signer = NewEIP155Signer(rules.ChainId)
case rules.IsHomestead:
signer = HomesteadSigner{}
default:
signer = FrontierSigner{}
}
return signer
}
// ChainId returns which chain id this transaction was signed for (if at all)
func (tx *Transaction) ChainId() *big.Int {
return deriveChainId(tx.data.V)
}
// Protected returns whether the transaction is pretected from replay protection
func (tx *Transaction) Protected() bool {
return isProtectedV(tx.data.V)
}
func isProtectedV(V *big.Int) bool {
if V.BitLen() <= 8 {
v := V.Uint64()
return v != 27 && v != 28
}
// anything not 27 or 28 are considered unprotected
return true
}
// DecodeRLP implements rlp.Encoder
func (tx *Transaction) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, &tx.data)
@@ -125,12 +160,13 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error {
if err == nil {
tx.size.Store(common.StorageSize(rlp.ListSize(size)))
}
return err
}
// MarshalJSON encodes transactions into the web3 RPC response block format.
func (tx *Transaction) MarshalJSON() ([]byte, error) {
hash, v := tx.Hash(), uint64(tx.data.V)
hash := tx.Hash()
return json.Marshal(&jsonTransaction{
Hash: &hash,
@@ -140,7 +176,7 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
Recipient: tx.data.Recipient,
Amount: (*hexBig)(tx.data.Amount),
Payload: (*hexBytes)(&tx.data.Payload),
V: (*hexUint64)(&v),
V: (*hexBig)(tx.data.V),
R: (*hexBig)(tx.data.R),
S: (*hexBig)(tx.data.S),
})
@@ -159,9 +195,17 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
if dec.V == nil || dec.R == nil || dec.S == nil {
return errMissingTxSignatureFields
}
if !crypto.ValidateSignatureValues(byte(*dec.V), (*big.Int)(dec.R), (*big.Int)(dec.S), false) {
var V byte
if isProtectedV((*big.Int)(dec.V)) {
V = normaliseV(NewEIP155Signer(deriveChainId((*big.Int)(dec.V))), (*big.Int)(dec.V))
} else {
V = byte(((*big.Int)(dec.V)).Uint64())
}
if !crypto.ValidateSignatureValues(V, (*big.Int)(dec.R), (*big.Int)(dec.S), false) {
return ErrInvalidSig
}
if dec.AccountNonce == nil || dec.Price == nil || dec.GasLimit == nil || dec.Amount == nil || dec.Payload == nil {
return errMissingTxFields
}
@@ -175,7 +219,7 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
GasLimit: (*big.Int)(dec.GasLimit),
Price: (*big.Int)(dec.Price),
Payload: *dec.Payload,
V: byte(*dec.V),
V: (*big.Int)(dec.V),
R: (*big.Int)(dec.R),
S: (*big.Int)(dec.S),
}
@@ -211,15 +255,8 @@ func (tx *Transaction) Hash() common.Hash {
// SigHash returns the hash to be signed by the sender.
// It does not uniquely identify the transaction.
func (tx *Transaction) SigHash() common.Hash {
return rlpHash([]interface{}{
tx.data.AccountNonce,
tx.data.Price,
tx.data.GasLimit,
tx.data.Recipient,
tx.data.Amount,
tx.data.Payload,
})
func (tx *Transaction) SigHash(signer Signer) common.Hash {
return signer.Hash(tx)
}
func (tx *Transaction) Size() common.StorageSize {
@@ -232,6 +269,7 @@ func (tx *Transaction) Size() common.StorageSize {
return common.StorageSize(c)
}
/*
// From returns the address derived from the signature (V, R, S) using secp256k1
// elliptic curve and an error if it failed deriving or upon an incorrect
// signature.
@@ -247,32 +285,15 @@ func (tx *Transaction) Size() common.StorageSize {
// both txs before and after the first homestead block. Signatures
// valid in homestead are a subset of valid ones in Frontier)
func (tx *Transaction) From() (common.Address, error) {
return doFrom(tx, true)
}
if tx.signer == nil {
return common.Address{}, errNoSigner
}
// FromFrontier returns the address derived from the signature (V, R, S) using
// secp256k1 elliptic curve and an error if it failed deriving or upon an
// incorrect signature.
//
// FromFrantier uses the frontier consensus rules to determine whether the
// signature is valid.
//
// FromFrontier caches the address, allowing it to be used regardless of
// Frontier / Homestead. however, the first time called it runs
// signature validations, so we need two versions. This makes it
// easier to ensure backwards compatibility of things like package rpc
// where eth_getblockbynumber uses tx.From() and needs to work for
// both txs before and after the first homestead block. Signatures
// valid in homestead are a subset of valid ones in Frontier)
func (tx *Transaction) FromFrontier() (common.Address, error) {
return doFrom(tx, false)
}
func doFrom(tx *Transaction, homestead bool) (common.Address, error) {
if from := tx.from.Load(); from != nil {
return from.(common.Address), nil
}
pubkey, err := tx.publicKey(homestead)
pubkey, err := tx.signer.PublicKey(tx)
if err != nil {
return common.Address{}, err
}
@@ -282,6 +303,51 @@ func doFrom(tx *Transaction, homestead bool) (common.Address, error) {
return addr, nil
}
// SignatureValues returns the ECDSA signature values contained in the transaction.
func (tx *Transaction) SignatureValues() (v byte, r *big.Int, s *big.Int, err error) {
if tx.signer == nil {
return 0, nil, nil,errNoSigner
}
return normaliseV(tx.signer, tx.data.V), new(big.Int).Set(tx.data.R),new(big.Int).Set(tx.data.S), nil
}
*/
// AsMessage returns the transaction as a core.Message.
//
// AsMessage requires a signer to derive the sender.
//
// XXX Rename message to something less arbitrary?
func (tx *Transaction) AsMessage(s Signer) (Message, error) {
msg := Message{
nonce: tx.data.AccountNonce,
price: new(big.Int).Set(tx.data.Price),
gasLimit: new(big.Int).Set(tx.data.GasLimit),
to: tx.data.Recipient,
amount: tx.data.Amount,
data: tx.data.Payload,
}
var err error
msg.from, err = Sender(s, tx)
return msg, err
}
// SignECDSA signs the transaction using the given signer and private key
//
// XXX This only makes for a nice API: NewTx(...).SignECDSA(signer, prv). Should
// we keep this?
func (tx *Transaction) SignECDSA(signer Signer, prv *ecdsa.PrivateKey) (*Transaction, error) {
return signer.SignECDSA(tx, prv)
}
// WithSignature returns a new transaction with the given signature.
// This signature needs to be formatted as described in the yellow paper (v+27).
func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, error) {
return signer.WithSignature(tx, sig)
}
// Cost returns amount + gasprice * gaslimit.
func (tx *Transaction) Cost() *big.Int {
total := new(big.Int).Mul(tx.data.Price, tx.data.GasLimit)
@@ -289,61 +355,18 @@ func (tx *Transaction) Cost() *big.Int {
return total
}
// SignatureValues returns the ECDSA signature values contained in the transaction.
func (tx *Transaction) SignatureValues() (v byte, r *big.Int, s *big.Int) {
return tx.data.V, new(big.Int).Set(tx.data.R), new(big.Int).Set(tx.data.S)
}
func (tx *Transaction) publicKey(homestead bool) ([]byte, error) {
if !crypto.ValidateSignatureValues(tx.data.V, tx.data.R, tx.data.S, homestead) {
return nil, ErrInvalidSig
}
// encode the signature in uncompressed format
r, s := tx.data.R.Bytes(), tx.data.S.Bytes()
sig := make([]byte, 65)
copy(sig[32-len(r):32], r)
copy(sig[64-len(s):64], s)
sig[64] = tx.data.V - 27
// recover the public key from the signature
hash := tx.SigHash()
pub, err := crypto.Ecrecover(hash[:], sig)
if err != nil {
return nil, err
}
if len(pub) == 0 || pub[0] != 4 {
return nil, errors.New("invalid public key")
}
return pub, nil
}
// WithSignature returns a new transaction with the given signature.
// This signature needs to be formatted as described in the yellow paper (v+27).
func (tx *Transaction) WithSignature(sig []byte) (*Transaction, error) {
if len(sig) != 65 {
panic(fmt.Sprintf("wrong size for signature: got %d, want 65", len(sig)))
}
cpy := &Transaction{data: tx.data}
cpy.data.R = new(big.Int).SetBytes(sig[:32])
cpy.data.S = new(big.Int).SetBytes(sig[32:64])
cpy.data.V = sig[64]
return cpy, nil
}
func (tx *Transaction) SignECDSA(prv *ecdsa.PrivateKey) (*Transaction, error) {
h := tx.SigHash()
sig, err := crypto.SignEthereum(h[:], prv)
if err != nil {
return nil, err
}
return tx.WithSignature(sig)
func (tx *Transaction) RawSignatureValues() (*big.Int, *big.Int, *big.Int) {
return tx.data.V, tx.data.R, tx.data.S
}
func (tx *Transaction) String() string {
// make a best guess about the signer and use that to derive
// the sender.
signer := deriveSigner(tx.data.V)
var from, to string
if f, err := tx.From(); err != nil {
from = "[invalid sender]"
if f, err := Sender(signer, tx); err != nil { // derive but don't cache
from = "[invalid sender: invalid sig]"
} else {
from = fmt.Sprintf("%x", f[:])
}
@@ -485,8 +508,9 @@ func (t *TransactionsByPriceAndNonce) Peek() *Transaction {
// Shift replaces the current best head with the next one from the same account.
func (t *TransactionsByPriceAndNonce) Shift() {
acc, _ := t.heads[0].From() // we only sort valid txs so this cannot fail
signer := deriveSigner(t.heads[0].data.V)
// derive signer but don't cache.
acc, _ := Sender(signer, t.heads[0]) // we only sort valid txs so this cannot fail
if txs, ok := t.txs[acc]; ok && len(txs) > 0 {
t.heads[0], t.txs[acc] = txs[0], txs[1:]
heap.Fix(&t.heads, 0)
@@ -501,3 +525,35 @@ func (t *TransactionsByPriceAndNonce) Shift() {
func (t *TransactionsByPriceAndNonce) Pop() {
heap.Pop(&t.heads)
}
// Message is a fully derived transaction and implements core.Message
//
// NOTE: In a future PR this will be removed.
type Message struct {
to *common.Address
from common.Address
nonce uint64
amount, price, gasLimit *big.Int
data []byte
}
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount, gasLimit, price *big.Int, data []byte) Message {
return Message{
from: from,
to: to,
nonce: nonce,
amount: amount,
price: price,
gasLimit: gasLimit,
data: data,
}
}
func (m Message) From() common.Address { return m.from }
func (m Message) To() *common.Address { return m.to }
func (m Message) GasPrice() *big.Int { return m.price }
func (m Message) Value() *big.Int { return m.amount }
func (m Message) Gas() *big.Int { return m.gasLimit }
func (m Message) Nonce() uint64 { return m.nonce }
func (m Message) Data() []byte { return m.data }
func (m Message) CheckNonce() bool { return true }
+340
View File
@@ -0,0 +1,340 @@
// Copyright 2016 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 (
"crypto/ecdsa"
"errors"
"fmt"
"math/big"
"reflect"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
// sigCache is used to cache the derived sender and contains
// the signer used to derive it.
type sigCache struct {
signer Signer
from common.Address
}
// MakeSigner returns a Signer based on the given chain config and block number.
func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
var signer Signer
switch {
case config.IsEIP155(blockNumber):
signer = NewEIP155Signer(config.ChainId)
case config.IsHomestead(blockNumber):
signer = HomesteadSigner{}
default:
signer = FrontierSigner{}
}
return signer
}
// SignECDSA signs the transaction using the given signer and private key
func SignECDSA(s Signer, tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
h := s.Hash(tx)
sig, err := crypto.SignEthereum(h[:], prv)
if err != nil {
return nil, err
}
return s.WithSignature(tx, sig)
}
// Sender derives the sender from the tx using the signer derivation
// functions.
// Sender returns the address derived from the signature (V, R, S) using secp256k1
// elliptic curve and an error if it failed deriving or upon an incorrect
// signature.
//
// Sender may cache the address, allowing it to be used regardless of
// signing method. The cache is invalidated if the cached signer does
// not match the signer used in the current call.
func Sender(signer Signer, tx *Transaction) (common.Address, error) {
if sc := tx.from.Load(); sc != nil {
sigCache := sc.(sigCache)
// If the signer used to derive from in a previous
// call is not the same as used current, invalidate
// the cache.
if reflect.TypeOf(sigCache.signer) == reflect.TypeOf(signer) {
return sigCache.from, nil
}
}
pubkey, err := signer.PublicKey(tx)
if err != nil {
return common.Address{}, err
}
var addr common.Address
copy(addr[:], crypto.Keccak256(pubkey[1:])[12:])
tx.from.Store(sigCache{signer: signer, from: addr})
return addr, nil
}
// SignatureValues returns the ECDSA signature values contained in the transaction.
func SignatureValues(signer Signer, tx *Transaction) (v byte, r *big.Int, s *big.Int) {
return normaliseV(signer, tx.data.V), new(big.Int).Set(tx.data.R), new(big.Int).Set(tx.data.S)
}
type Signer interface {
// Hash returns the rlp encoded hash for signatures
Hash(tx *Transaction) common.Hash
// PubilcKey returns the public key derived from the signature
PublicKey(tx *Transaction) ([]byte, error)
// SignECDSA signs the transaction with the given and returns a copy of the tx
SignECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error)
// WithSignature returns a copy of the transaction with the given signature
WithSignature(tx *Transaction, sig []byte) (*Transaction, error)
}
// EIP155Transaction implements TransactionInterface using the
// EIP155 rules
type EIP155Signer struct {
HomesteadSigner
chainId, chainIdMul *big.Int
}
func NewEIP155Signer(chainId *big.Int) EIP155Signer {
return EIP155Signer{
chainId: chainId,
chainIdMul: new(big.Int).Mul(chainId, big.NewInt(2)),
}
}
func (s EIP155Signer) SignECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
return SignECDSA(s, tx, prv)
}
func (s EIP155Signer) PublicKey(tx *Transaction) ([]byte, error) {
// if the transaction is not protected fall back to homestead signer
if !tx.Protected() {
return (HomesteadSigner{}).PublicKey(tx)
}
V := normaliseV(s, tx.data.V)
if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, true) {
return nil, ErrInvalidSig
}
// encode the signature in uncompressed format
R, S := tx.data.R.Bytes(), tx.data.S.Bytes()
sig := make([]byte, 65)
copy(sig[32-len(R):32], R)
copy(sig[64-len(S):64], S)
sig[64] = V - 27
// recover the public key from the signature
hash := s.Hash(tx)
pub, err := crypto.Ecrecover(hash[:], sig)
if err != nil {
return nil, err
}
if len(pub) == 0 || pub[0] != 4 {
return nil, errors.New("invalid public key")
}
return pub, nil
}
// WithSignature returns a new transaction with the given signature.
// This signature needs to be formatted as described in the yellow paper (v+27).
func (s EIP155Signer) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
if len(sig) != 65 {
panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig)))
}
cpy := &Transaction{data: tx.data}
cpy.data.R = new(big.Int).SetBytes(sig[:32])
cpy.data.S = new(big.Int).SetBytes(sig[32:64])
cpy.data.V = new(big.Int).SetBytes([]byte{sig[64]})
if s.chainId.BitLen() > 0 {
cpy.data.V = big.NewInt(int64(sig[64] - 27 + 35))
cpy.data.V.Add(cpy.data.V, s.chainIdMul)
}
return cpy, nil
}
// Hash returns the hash to be signed by the sender.
// It does not uniquely identify the transaction.
func (s EIP155Signer) Hash(tx *Transaction) common.Hash {
return rlpHash([]interface{}{
tx.data.AccountNonce,
tx.data.Price,
tx.data.GasLimit,
tx.data.Recipient,
tx.data.Amount,
tx.data.Payload,
s.chainId, uint(0), uint(0),
})
}
func (s EIP155Signer) SigECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
h := s.Hash(tx)
sig, err := crypto.SignEthereum(h[:], prv)
if err != nil {
return nil, err
}
return s.WithSignature(tx, sig)
}
// HomesteadTransaction implements TransactionInterface using the
// homestead rules.
type HomesteadSigner struct{ FrontierSigner }
// WithSignature returns a new transaction with the given snature.
// This snature needs to be formatted as described in the yellow paper (v+27).
func (hs HomesteadSigner) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
if len(sig) != 65 {
panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig)))
}
cpy := &Transaction{data: tx.data}
cpy.data.R = new(big.Int).SetBytes(sig[:32])
cpy.data.S = new(big.Int).SetBytes(sig[32:64])
cpy.data.V = new(big.Int).SetBytes([]byte{sig[64]})
return cpy, nil
}
func (hs HomesteadSigner) SignECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
h := hs.Hash(tx)
sig, err := crypto.SignEthereum(h[:], prv)
if err != nil {
return nil, err
}
return hs.WithSignature(tx, sig)
}
func (hs HomesteadSigner) PublicKey(tx *Transaction) ([]byte, error) {
if tx.data.V.BitLen() > 8 {
return nil, ErrInvalidSig
}
V := byte(tx.data.V.Uint64())
if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, true) {
return nil, ErrInvalidSig
}
// encode the snature in uncompressed format
r, s := tx.data.R.Bytes(), tx.data.S.Bytes()
sig := make([]byte, 65)
copy(sig[32-len(r):32], r)
copy(sig[64-len(s):64], s)
sig[64] = V - 27
// recover the public key from the snature
hash := hs.Hash(tx)
pub, err := crypto.Ecrecover(hash[:], sig)
if err != nil {
return nil, err
}
if len(pub) == 0 || pub[0] != 4 {
return nil, errors.New("invalid public key")
}
return pub, nil
}
type FrontierSigner struct{}
// WithSignature returns a new transaction with the given snature.
// This snature needs to be formatted as described in the yellow paper (v+27).
func (fs FrontierSigner) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
if len(sig) != 65 {
panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig)))
}
cpy := &Transaction{data: tx.data}
cpy.data.R = new(big.Int).SetBytes(sig[:32])
cpy.data.S = new(big.Int).SetBytes(sig[32:64])
cpy.data.V = new(big.Int).SetBytes([]byte{sig[64]})
return cpy, nil
}
func (fs FrontierSigner) SignECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
h := fs.Hash(tx)
sig, err := crypto.SignEthereum(h[:], prv)
if err != nil {
return nil, err
}
return fs.WithSignature(tx, sig)
}
// Hash returns the hash to be sned by the sender.
// It does not uniquely identify the transaction.
func (fs FrontierSigner) Hash(tx *Transaction) common.Hash {
return rlpHash([]interface{}{
tx.data.AccountNonce,
tx.data.Price,
tx.data.GasLimit,
tx.data.Recipient,
tx.data.Amount,
tx.data.Payload,
})
}
func (fs FrontierSigner) PublicKey(tx *Transaction) ([]byte, error) {
if tx.data.V.BitLen() > 8 {
return nil, ErrInvalidSig
}
V := byte(tx.data.V.Uint64())
if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, false) {
return nil, ErrInvalidSig
}
// encode the snature in uncompressed format
r, s := tx.data.R.Bytes(), tx.data.S.Bytes()
sig := make([]byte, 65)
copy(sig[32-len(r):32], r)
copy(sig[64-len(s):64], s)
sig[64] = V - 27
// recover the public key from the snature
hash := fs.Hash(tx)
pub, err := crypto.Ecrecover(hash[:], sig)
if err != nil {
return nil, err
}
if len(pub) == 0 || pub[0] != 4 {
return nil, errors.New("invalid public key")
}
return pub, nil
}
// normaliseV returns the Ethereum version of the V parameter
func normaliseV(s Signer, v *big.Int) byte {
if s, ok := s.(EIP155Signer); ok {
stdV := v.BitLen() <= 8 && (v.Uint64() == 27 || v.Uint64() == 28)
if s.chainId.BitLen() > 0 && !stdV {
nv := byte((new(big.Int).Sub(v, s.chainIdMul).Uint64()) - 35 + 27)
return nv
}
}
return byte(v.Uint64())
}
// deriveChainId derives the chain id from the given v parameter
func deriveChainId(v *big.Int) *big.Int {
if v.BitLen() <= 64 {
v := v.Uint64()
if v == 27 || v == 28 {
return new(big.Int)
}
return new(big.Int).SetUint64((v - 35) / 2)
}
v = new(big.Int).Sub(v, big.NewInt(35))
return v.Div(v, big.NewInt(2))
}
+116
View File
@@ -0,0 +1,116 @@
// Copyright 2016 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"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
)
func TestEIP155Signing(t *testing.T) {
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
signer := NewEIP155Signer(big.NewInt(18))
tx, err := NewTransaction(0, addr, new(big.Int), new(big.Int), new(big.Int), nil).SignECDSA(signer, key)
if err != nil {
t.Fatal(err)
}
from, err := Sender(signer, tx)
if err != nil {
t.Fatal(err)
}
if from != addr {
t.Errorf("exected from and address to be equal. Got %x want %x", from, addr)
}
}
func TestEIP155ChainId(t *testing.T) {
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
signer := NewEIP155Signer(big.NewInt(18))
tx, err := NewTransaction(0, addr, new(big.Int), new(big.Int), new(big.Int), nil).SignECDSA(signer, key)
if err != nil {
t.Fatal(err)
}
if !tx.Protected() {
t.Fatal("expected tx to be protected")
}
if tx.ChainId().Cmp(signer.chainId) != 0 {
t.Error("expected chainId to be", signer.chainId, "got", tx.ChainId())
}
tx = NewTransaction(0, addr, new(big.Int), new(big.Int), new(big.Int), nil)
tx, err = tx.SignECDSA(HomesteadSigner{}, key)
if err != nil {
t.Fatal(err)
}
if tx.Protected() {
t.Error("didn't expect tx to be protected")
}
if tx.ChainId().BitLen() > 0 {
t.Error("expected chain id to be 0 got", tx.ChainId())
}
}
func TestEIP155SigningVitalik(t *testing.T) {
// Test vectors come from http://vitalik.ca/files/eip155_testvec.txt
for i, test := range []struct {
txRlp, addr string
}{
{"f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce"},
{"f864018504a817c80182a410943535353535353535353535353535353535353535018025a0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bcaa0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", "0x23ef145a395ea3fa3deb533b8a9e1b4c6c25d112"},
{"f864028504a817c80282f618943535353535353535353535353535353535353535088025a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", "0x2e485e0c23b4c3c542628a5f672eeab0ad4888be"},
{"f865038504a817c803830148209435353535353535353535353535353535353535351b8025a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", "0x82a88539669a3fd524d669e858935de5e5410cf0"},
{"f865048504a817c80483019a28943535353535353535353535353535353535353535408025a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", "0xf9358f2538fd5ccfeb848b64a96b743fcc930554"},
{"f865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", "0xa8f7aba377317440bc5b26198a363ad22af1f3a4"},
{"f866068504a817c80683023e3894353535353535353535353535353535353535353581d88025a06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2fa06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", "0xf1f571dc362a0e5b2696b8e775f8491d3e50de35"},
{"f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "0xd37922162ab7cea97c97a87551ed02c9a38b7332"},
{"f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "0x9bddad43f934d313c2b79ca28a432dd2b7281029"},
{"f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "0x3c24d7329e92f84f08556ceb6df1cdb0104ca49f"},
} {
signer := NewEIP155Signer(big.NewInt(1))
var tx *Transaction
err := rlp.DecodeBytes(common.Hex2Bytes(test.txRlp), &tx)
if err != nil {
t.Errorf("%d: %v", i, err)
continue
}
from, err := Sender(signer, tx)
if err != nil {
t.Errorf("%d: %v", i, err)
continue
}
addr := common.HexToAddress(test.addr)
if from != addr {
t.Errorf("%d: expected %x got %x", i, addr, from)
}
}
}
+17 -11
View File
@@ -46,15 +46,16 @@ var (
big.NewInt(1),
common.FromHex("5544"),
).WithSignature(
HomesteadSigner{},
common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a31c"),
)
)
func TestTransactionSigHash(t *testing.T) {
if emptyTx.SigHash() != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") {
if emptyTx.SigHash(HomesteadSigner{}) != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") {
t.Errorf("empty transaction hash mismatch, got %x", emptyTx.Hash())
}
if rightvrsTx.SigHash() != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") {
if rightvrsTx.SigHash(HomesteadSigner{}) != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") {
t.Errorf("RightVRS transaction hash mismatch, got %x", rightvrsTx.Hash())
}
}
@@ -72,7 +73,9 @@ func TestTransactionEncode(t *testing.T) {
func decodeTx(data []byte) (*Transaction, error) {
var tx Transaction
return &tx, rlp.Decode(bytes.NewReader(data), &tx)
t, err := &tx, rlp.Decode(bytes.NewReader(data), &tx)
return t, err
}
func defaultTestKey() (*ecdsa.PrivateKey, common.Address) {
@@ -88,7 +91,8 @@ func TestRecipientEmpty(t *testing.T) {
t.Error(err)
t.FailNow()
}
from, err := tx.From()
from, err := Sender(HomesteadSigner{}, tx)
if err != nil {
t.Error(err)
t.FailNow()
@@ -107,7 +111,7 @@ func TestRecipientNormal(t *testing.T) {
t.FailNow()
}
from, err := tx.From()
from, err := Sender(HomesteadSigner{}, tx)
if err != nil {
t.Error(err)
t.FailNow()
@@ -127,12 +131,14 @@ func TestTransactionPriceNonceSort(t *testing.T) {
for i := 0; i < len(keys); i++ {
keys[i], _ = crypto.GenerateKey()
}
signer := HomesteadSigner{}
// Generate a batch of transactions with overlapping values, but shifted nonces
groups := map[common.Address]Transactions{}
for start, key := range keys {
addr := crypto.PubkeyToAddress(key.PublicKey)
for i := 0; i < 25; i++ {
tx, _ := NewTransaction(uint64(start+i), common.Address{}, big.NewInt(100), big.NewInt(100), big.NewInt(int64(start+i)), nil).SignECDSA(key)
tx, _ := NewTransaction(uint64(start+i), common.Address{}, big.NewInt(100), big.NewInt(100), big.NewInt(int64(start+i)), nil).SignECDSA(signer, key)
groups[addr] = append(groups[addr], tx)
}
}
@@ -148,11 +154,11 @@ func TestTransactionPriceNonceSort(t *testing.T) {
break
}
for i, txi := range txs {
fromi, _ := txi.From()
fromi, _ := Sender(signer, txi)
// Make sure the nonce order is valid
for j, txj := range txs[i+1:] {
fromj, _ := txj.From()
fromj, _ := Sender(signer, txj)
if fromi == fromj && txi.Nonce() > txj.Nonce() {
t.Errorf("invalid nonce ordering: tx #%d (A=%x N=%v) < tx #%d (A=%x N=%v)", i, fromi[:4], txi.Nonce(), i+j, fromj[:4], txj.Nonce())
@@ -161,20 +167,20 @@ func TestTransactionPriceNonceSort(t *testing.T) {
// Find the previous and next nonce of this account
prev, next := i-1, i+1
for j := i - 1; j >= 0; j-- {
if fromj, _ := txs[j].From(); fromi == fromj {
if fromj, _ := Sender(signer, txs[j]); fromi == fromj {
prev = j
break
}
}
for j := i + 1; j < len(txs); j++ {
if fromj, _ := txs[j].From(); fromi == fromj {
if fromj, _ := Sender(signer, txs[j]); fromi == fromj {
next = j
break
}
}
// Make sure that in between the neighbor nonces, the transaction is correctly positioned price wise
for j := prev + 1; j < next; j++ {
fromj, _ := txs[j].From()
fromj, _ := Sender(signer, txs[j])
if j < i && txs[j].GasPrice().Cmp(txi.GasPrice()) < 0 {
t.Errorf("invalid gasprice ordering: tx #%d (A=%x P=%v) < tx #%d (A=%x P=%v)", j, fromj[:4], txs[j].GasPrice(), i, fromi[:4], txi.GasPrice())
}
+4 -10
View File
@@ -23,20 +23,11 @@ import (
"github.com/ethereum/go-ethereum/params"
)
// RuleSet is an interface that defines the current rule set during the
// execution of the EVM instructions (e.g. whether it's homestead)
type RuleSet interface {
IsHomestead(*big.Int) bool
// GasTable returns the gas prices for this phase, which is based on
// block number passed in.
GasTable(*big.Int) params.GasTable
}
// Environment is an EVM requirement and helper which allows access to outside
// information such as states.
type Environment interface {
// The current ruleset
RuleSet() RuleSet
ChainConfig() *params.ChainConfig
// The state database
Db() Database
// Creates a restorable snapshot
@@ -115,6 +106,9 @@ type Database interface {
// Exist reports whether the given account exists in state.
// Notably this should also return true for suicided accounts.
Exist(common.Address) bool
// Empty returns whether the given account is empty. Empty
// is defined according to EIP161 (balance = nonce = code = 0).
Empty(common.Address) bool
}
// Account represents a contract or basic ethereum account.
+2 -2
View File
@@ -515,7 +515,7 @@ func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract
input = memory.Get(offset.Int64(), size.Int64())
gas = new(big.Int).Set(contract.Gas)
)
if env.RuleSet().GasTable(env.BlockNumber()).CreateBySuicide != nil {
if env.ChainConfig().IsEIP150(env.BlockNumber()) {
gas.Div(gas, n64)
gas = gas.Sub(contract.Gas, gas)
}
@@ -526,7 +526,7 @@ func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract
// homestead we must check for CodeStoreOutOfGasError (homestead only
// rule) and treat as an error, if the ruleset is frontier we must
// ignore this error and pretend the operation was successful.
if env.RuleSet().IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
if env.ChainConfig().IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
stack.push(new(big.Int))
} else if suberr != nil && suberr != CodeStoreOutOfGasError {
stack.push(new(big.Int))
+1 -1
View File
@@ -319,7 +319,7 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *Stack, env
}()
}
homestead := env.RuleSet().IsHomestead(env.BlockNumber())
homestead := env.ChainConfig().IsHomestead(env.BlockNumber())
for pc < uint64(len(program.instructions)) {
instrCount++
+4 -1
View File
@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
const maxRun = 1000
@@ -172,7 +173,9 @@ func NewEnv(config *Config) *Env {
return env
}
func (self *Env) RuleSet() RuleSet { return ruleSet{new(big.Int)} }
func (self *Env) ChainConfig() *params.ChainConfig {
return params.TestChainConfig
}
func (self *Env) Vm() Vm { return self.evm }
func (self *Env) Origin() common.Address { return common.Address{} }
func (self *Env) BlockNumber() *big.Int { return big.NewInt(0) }
+6 -2
View File
@@ -16,7 +16,11 @@
package vm
import "math/big"
import (
"math/big"
"github.com/ethereum/go-ethereum/params"
)
type jumpPtr struct {
fn instrFn
@@ -25,7 +29,7 @@ type jumpPtr struct {
type vmJumpTable [256]jumpPtr
func newJumpTable(ruleset RuleSet, blockNumber *big.Int) vmJumpTable {
func newJumpTable(ruleset *params.ChainConfig, blockNumber *big.Int) vmJumpTable {
var jumpTable vmJumpTable
// when initialising a new VM execution we must first check the homestead
+4 -2
View File
@@ -19,16 +19,18 @@ package vm
import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/params"
)
func TestInit(t *testing.T) {
jumpTable := newJumpTable(ruleSet{big.NewInt(1)}, big.NewInt(0))
jumpTable := newJumpTable(&params.ChainConfig{HomesteadBlock: big.NewInt(1)}, big.NewInt(0))
if jumpTable[DELEGATECALL].valid {
t.Error("Expected DELEGATECALL not to be present")
}
for _, n := range []int64{1, 2, 100} {
jumpTable := newJumpTable(ruleSet{big.NewInt(1)}, big.NewInt(n))
jumpTable := newJumpTable(&params.ChainConfig{HomesteadBlock: big.NewInt(1)}, big.NewInt(n))
if !jumpTable[DELEGATECALL].valid {
t.Error("Expected DELEGATECALL to be present for block", n)
}
+22 -21
View File
@@ -23,13 +23,14 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
)
// Env is a basic runtime environment required for running the EVM.
type Env struct {
ruleSet vm.RuleSet
depth int
state *state.StateDB
chainConfig *params.ChainConfig
depth int
state *state.StateDB
origin common.Address
coinbase common.Address
@@ -47,14 +48,14 @@ type Env struct {
// NewEnv returns a new vm.Environment
func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
env := &Env{
ruleSet: cfg.RuleSet,
state: state,
origin: cfg.Origin,
coinbase: cfg.Coinbase,
number: cfg.BlockNumber,
time: cfg.Time,
difficulty: cfg.Difficulty,
gasLimit: cfg.GasLimit,
chainConfig: cfg.ChainConfig,
state: state,
origin: cfg.Origin,
coinbase: cfg.Coinbase,
number: cfg.BlockNumber,
time: cfg.Time,
difficulty: cfg.Difficulty,
gasLimit: cfg.GasLimit,
}
env.evm = vm.New(env, vm.Config{
Debug: cfg.Debug,
@@ -65,16 +66,16 @@ func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
return env
}
func (self *Env) RuleSet() vm.RuleSet { return self.ruleSet }
func (self *Env) Vm() vm.Vm { return self.evm }
func (self *Env) Origin() common.Address { return self.origin }
func (self *Env) BlockNumber() *big.Int { return self.number }
func (self *Env) Coinbase() common.Address { return self.coinbase }
func (self *Env) Time() *big.Int { return self.time }
func (self *Env) Difficulty() *big.Int { return self.difficulty }
func (self *Env) Db() vm.Database { return self.state }
func (self *Env) GasLimit() *big.Int { return self.gasLimit }
func (self *Env) VmType() vm.Type { return vm.StdVmTy }
func (self *Env) ChainConfig() *params.ChainConfig { return self.chainConfig }
func (self *Env) Vm() vm.Vm { return self.evm }
func (self *Env) Origin() common.Address { return self.origin }
func (self *Env) BlockNumber() *big.Int { return self.number }
func (self *Env) Coinbase() common.Address { return self.coinbase }
func (self *Env) Time() *big.Int { return self.time }
func (self *Env) Difficulty() *big.Int { return self.difficulty }
func (self *Env) Db() vm.Database { return self.state }
func (self *Env) GasLimit() *big.Int { return self.gasLimit }
func (self *Env) VmType() vm.Type { return vm.StdVmTy }
func (self *Env) GetHash(n uint64) common.Hash {
return self.getHashFn(n)
}
+11 -4
View File
@@ -22,7 +22,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
@@ -39,7 +38,7 @@ func (ruleSet) GasTable(*big.Int) params.GasTable {
// Config is a basic type specifying certain configuration flags for running
// the EVM.
type Config struct {
RuleSet vm.RuleSet
ChainConfig *params.ChainConfig
Difficulty *big.Int
Origin common.Address
Coinbase common.Address
@@ -57,8 +56,16 @@ type Config struct {
// sets defaults on the config
func setDefaults(cfg *Config) {
if cfg.RuleSet == nil {
cfg.RuleSet = ruleSet{}
if cfg.ChainConfig == nil {
cfg.ChainConfig = &params.ChainConfig{
ChainId: big.NewInt(1),
HomesteadBlock: new(big.Int),
DAOForkBlock: new(big.Int),
DAOForkSupport: false,
EIP150Block: new(big.Int),
EIP155Block: new(big.Int),
EIP158Block: new(big.Int),
}
}
if cfg.Difficulty == nil {
+28 -7
View File
@@ -51,9 +51,9 @@ type EVM struct {
func New(env Environment, cfg Config) *EVM {
return &EVM{
env: env,
jumpTable: newJumpTable(env.RuleSet(), env.BlockNumber()),
jumpTable: newJumpTable(env.ChainConfig(), env.BlockNumber()),
cfg: cfg,
gasTable: env.RuleSet().GasTable(env.BlockNumber()),
gasTable: env.ChainConfig().GasTable(env.BlockNumber()),
}
}
@@ -172,6 +172,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
// Get the memory location of pc
op = contract.GetOp(pc)
//fmt.Printf("OP %d %v\n", op, op)
// calculate the new memory size and gas price for the current executing opcode
newMemSize, cost, err = calculateGasAndSize(evm.gasTable, evm.env, contract, caller, op, statedb, mem, stack)
if err != nil {
@@ -254,10 +255,20 @@ func calculateGasAndSize(gasTable params.GasTable, env Environment, contract *Co
// stack Check, memory resize & gas phase
switch op {
case SUICIDE:
// if suicide is not nil: homestead gas fork
// EIP150 homestead gas reprice fork:
if gasTable.CreateBySuicide != nil {
gas.Set(gasTable.Suicide)
if !env.Db().Exist(common.BigToAddress(stack.data[len(stack.data)-1])) {
var (
address = common.BigToAddress(stack.data[len(stack.data)-1])
eip158 = env.ChainConfig().IsEIP158(env.BlockNumber())
)
if eip158 {
// if empty and transfers value
if env.Db().Empty(address) && statedb.GetBalance(contract.Address()).BitLen() > 0 {
gas.Add(gas, gasTable.CreateBySuicide)
}
} else if !env.Db().Exist(address) {
gas.Add(gas, gasTable.CreateBySuicide)
}
}
@@ -302,7 +313,8 @@ func calculateGasAndSize(gasTable params.GasTable, env Environment, contract *Co
quadMemGas(mem, newMemSize, gas)
case EXP:
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas))
expByteLen := int64((stack.data[stack.len()-2].BitLen() + 7) / 8)
gas.Add(gas, new(big.Int).Mul(big.NewInt(expByteLen), gasTable.ExpByte))
case SSTORE:
err := stack.require(2)
if err != nil {
@@ -378,12 +390,21 @@ func calculateGasAndSize(gasTable params.GasTable, env Environment, contract *Co
case CALL, CALLCODE:
gas.Set(gasTable.Calls)
transfersValue := stack.data[len(stack.data)-3].BitLen() > 0
if op == CALL {
if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) {
var (
address = common.BigToAddress(stack.data[len(stack.data)-2])
eip158 = env.ChainConfig().IsEIP158(env.BlockNumber())
)
if eip158 {
if env.Db().Empty(address) && transfersValue {
gas.Add(gas, params.CallNewAccountGas)
}
} else if !env.Db().Exist(address) {
gas.Add(gas, params.CallNewAccountGas)
}
}
if len(stack.data[stack.len()-3].Bytes()) > 0 {
if transfersValue {
gas.Add(gas, params.CallValueTransferGas)
}
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
+19 -18
View File
@@ -23,6 +23,7 @@ import (
"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/params"
)
// GetHashFn returns a function for which the VM env can query block hashes through
@@ -41,18 +42,18 @@ func GetHashFn(ref common.Hash, chain *BlockChain) func(n uint64) common.Hash {
}
type VMEnv struct {
chainConfig *ChainConfig // Chain configuration
state *state.StateDB // State to use for executing
evm *vm.EVM // The Ethereum Virtual Machine
depth int // Current execution depth
msg Message // Message appliod
chainConfig *params.ChainConfig // Chain configuration
state *state.StateDB // State to use for executing
evm *vm.EVM // The Ethereum Virtual Machine
depth int // Current execution depth
msg Message // Message appliod
header *types.Header // Header information
chain *BlockChain // Blockchain handle
getHashFn func(uint64) common.Hash // getHashFn callback is used to retrieve block hashes
}
func NewEnv(state *state.StateDB, chainConfig *ChainConfig, chain *BlockChain, msg Message, header *types.Header, cfg vm.Config) *VMEnv {
func NewEnv(state *state.StateDB, chainConfig *params.ChainConfig, chain *BlockChain, msg Message, header *types.Header, cfg vm.Config) *VMEnv {
env := &VMEnv{
chainConfig: chainConfig,
chain: chain,
@@ -66,18 +67,18 @@ func NewEnv(state *state.StateDB, chainConfig *ChainConfig, chain *BlockChain, m
return env
}
func (self *VMEnv) RuleSet() vm.RuleSet { return self.chainConfig }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f }
func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number }
func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase }
func (self *VMEnv) Time() *big.Int { return self.header.Time }
func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty }
func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit }
func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
func (self *VMEnv) Db() vm.Database { return self.state }
func (self *VMEnv) Depth() int { return self.depth }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) ChainConfig() *params.ChainConfig { return self.chainConfig }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Origin() common.Address { return self.msg.From() }
func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number }
func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase }
func (self *VMEnv) Time() *big.Int { return self.header.Time }
func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty }
func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit }
func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
func (self *VMEnv) Db() vm.Database { return self.state }
func (self *VMEnv) Depth() int { return self.depth }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) GetHash(n uint64) common.Hash {
return self.getHashFn(n)
}
+6 -11
View File
@@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"golang.org/x/net/context"
@@ -303,13 +304,13 @@ func (api *PublicDebugAPI) DumpBlock(number uint64) (state.Dump, error) {
// PrivateDebugAPI is the collection of Etheruem full node APIs exposed over
// the private debugging endpoint.
type PrivateDebugAPI struct {
config *core.ChainConfig
config *params.ChainConfig
eth *Ethereum
}
// NewPrivateDebugAPI creates a new API definition for the full node-related
// private debug methods of the Ethereum service.
func NewPrivateDebugAPI(config *core.ChainConfig, eth *Ethereum) *PrivateDebugAPI {
func NewPrivateDebugAPI(config *params.ChainConfig, eth *Ethereum) *PrivateDebugAPI {
return &PrivateDebugAPI{config: config, eth: eth}
}
@@ -505,21 +506,15 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
if err != nil {
return nil, err
}
signer := types.MakeSigner(api.config, block.Number())
// Mutate the state and trace the selected transaction
for idx, tx := range block.Transactions() {
// Assemble the transaction call message
from, err := tx.FromFrontier()
msg, err := tx.AsMessage(signer)
if err != nil {
return nil, fmt.Errorf("sender retrieval failed: %v", err)
}
msg := callmsg{
addr: from,
to: tx.To(),
gas: tx.Gas(),
gasPrice: tx.GasPrice(),
value: tx.Value(),
data: tx.Data(),
}
// Mutate the state if we haven't reached the tracing transaction yet
if uint64(idx) < txIndex {
vmenv := core.NewEnv(stateDb, api.config, api.eth.BlockChain(), msg, block.Header(), vm.Config{})
+11 -3
View File
@@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/params"
rpc "github.com/ethereum/go-ethereum/rpc"
"golang.org/x/net/context"
)
@@ -40,6 +41,14 @@ type EthApiBackend struct {
gpo *gasprice.GasPriceOracle
}
func (b *EthApiBackend) ChainConfig() *params.ChainConfig {
return b.eth.chainConfig
}
func (b *EthApiBackend) CurrentBlock() *types.Block {
return b.eth.blockchain.CurrentBlock()
}
func (b *EthApiBackend) SetHead(number uint64) {
b.eth.blockchain.SetHead(number)
}
@@ -99,11 +108,10 @@ func (b *EthApiBackend) GetTd(blockHash common.Hash) *big.Int {
func (b *EthApiBackend) GetVMEnv(ctx context.Context, msg core.Message, state ethapi.State, header *types.Header) (vm.Environment, func() error, error) {
statedb := state.(EthApiState).state
addr, _ := msg.From()
from := statedb.GetOrNewStateObject(addr)
from := statedb.GetOrNewStateObject(msg.From())
from.SetBalance(common.MaxBig)
vmError := func() error { return nil }
return core.NewEnv(statedb, b.eth.chainConfig, b.eth.blockchain, msg, header, b.eth.chainConfig.VmConfig), vmError, nil
return core.NewEnv(statedb, b.eth.chainConfig, b.eth.blockchain, msg, header, vm.Config{}), vmError, nil
}
func (b *EthApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
+3 -7
View File
@@ -35,7 +35,6 @@ import (
"github.com/ethereum/go-ethereum/common/registrar/ethreg"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/eth/gasprice"
@@ -47,6 +46,7 @@ import (
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
)
@@ -64,7 +64,7 @@ var (
)
type Config struct {
ChainConfig *core.ChainConfig // chain configuration
ChainConfig *params.ChainConfig // chain configuration
NetworkId int // Network ID to use for selecting peers to connect to
Genesis string // Genesis JSON to seed the chain database with
@@ -112,7 +112,7 @@ type LesServer interface {
// Ethereum implements the Ethereum full node service.
type Ethereum struct {
chainConfig *core.ChainConfig
chainConfig *params.ChainConfig
// Channel for shutting down the service
shutdownChan chan bool // Channel for shutting down the ethereum
stopDbUpgrade func() // stop chain db sequential key upgrade
@@ -217,10 +217,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
core.WriteChainConfig(chainDb, genesis.Hash(), config.ChainConfig)
eth.chainConfig = config.ChainConfig
eth.chainConfig.VmConfig = vm.Config{
EnableJit: config.EnableJit,
ForceJit: config.ForceJit,
}
eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.EventMux())
if err != nil {
+2 -1
View File
@@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
func TestMipmapUpgrade(t *testing.T) {
@@ -32,7 +33,7 @@ func TestMipmapUpgrade(t *testing.T) {
addr := common.BytesToAddress([]byte("jeff"))
genesis := core.WriteGenesisBlockForTesting(db)
chain, receipts := core.GenerateChain(nil, genesis, db, 10, func(i int, gen *core.BlockGen) {
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *core.BlockGen) {
var receipts types.Receipts
switch i {
case 1:
+3 -2
View File
@@ -109,7 +109,7 @@ func newTester() *downloadTester {
// reassembly.
func (dl *downloadTester) makeChain(n int, seed byte, parent *types.Block, parentReceipts types.Receipts, heavy bool) ([]common.Hash, map[common.Hash]*types.Header, map[common.Hash]*types.Block, map[common.Hash]types.Receipts) {
// Generate the block chain
blocks, receipts := core.GenerateChain(nil, parent, dl.peerDb, n, func(i int, block *core.BlockGen) {
blocks, receipts := core.GenerateChain(params.TestChainConfig, parent, dl.peerDb, n, func(i int, block *core.BlockGen) {
block.SetCoinbase(common.Address{seed})
// If a heavy chain is requested, delay blocks to raise difficulty
@@ -118,7 +118,8 @@ func (dl *downloadTester) makeChain(n int, seed byte, parent *types.Block, paren
}
// If the block number is multiple of 3, send a bonus transaction to the miner
if parent == dl.genesis && i%3 == 0 {
tx, err := types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testKey)
signer := types.MakeSigner(params.TestChainConfig, block.Number())
tx, err := types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, testKey)
if err != nil {
panic(err)
}
+3 -2
View File
@@ -45,12 +45,13 @@ var (
// contains a transaction and every 5th an uncle to allow testing correct block
// reassembly.
func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common.Hash]*types.Block) {
blocks, _ := core.GenerateChain(nil, parent, testdb, n, func(i int, block *core.BlockGen) {
blocks, _ := core.GenerateChain(params.TestChainConfig, parent, testdb, n, func(i int, block *core.BlockGen) {
block.SetCoinbase(common.Address{seed})
// If the block number is multiple of 3, send a bonus transaction to the miner
if parent == genesis && i%3 == 0 {
tx, err := types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testKey)
signer := types.MakeSigner(params.TestChainConfig, block.Number())
tx, err := types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, testKey)
if err != nil {
panic(err)
}
+2 -1
View File
@@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
)
@@ -81,7 +82,7 @@ func TestBlockSubscription(t *testing.T) {
var (
genesis = core.WriteGenesisBlockForTesting(db)
chain, _ = core.GenerateChain(nil, genesis, db, 10, func(i int, gen *core.BlockGen) {})
chain, _ = core.GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *core.BlockGen) {})
chainEvents = []core.ChainEvent{}
)
+3 -2
View File
@@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
func makeReceipt(addr common.Address) *types.Receipt {
@@ -60,7 +61,7 @@ func BenchmarkMipmaps(b *testing.B) {
defer db.Close()
genesis := core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: addr1, Balance: big.NewInt(1000000)})
chain, receipts := core.GenerateChain(nil, genesis, db, 100010, func(i int, gen *core.BlockGen) {
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 100010, func(i int, gen *core.BlockGen) {
var receipts types.Receipts
switch i {
case 2403:
@@ -137,7 +138,7 @@ func TestFilters(t *testing.T) {
defer db.Close()
genesis := core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: addr, Balance: big.NewInt(1000000)})
chain, receipts := core.GenerateChain(nil, genesis, db, 1000, func(i int, gen *core.BlockGen) {
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 1000, func(i int, gen *core.BlockGen) {
var receipts types.Receipts
switch i {
case 1:
+3 -2
View File
@@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -67,7 +68,7 @@ type ProtocolManager struct {
txpool txPool
blockchain *core.BlockChain
chaindb ethdb.Database
chainconfig *core.ChainConfig
chainconfig *params.ChainConfig
maxPeers int
downloader *downloader.Downloader
@@ -95,7 +96,7 @@ type ProtocolManager struct {
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
// with the ethereum network.
func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int, maxPeers int, mux *event.TypeMux, txpool txPool, pow pow.PoW, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) {
func NewProtocolManager(config *params.ChainConfig, fastSync bool, networkId int, maxPeers int, mux *event.TypeMux, txpool txPool, pow pow.PoW, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) {
// Create the protocol manager with the base fields
manager := &ProtocolManager{
networkId: networkId,
+10 -8
View File
@@ -305,18 +305,19 @@ func testGetNodeData(t *testing.T, protocol int) {
acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
signer := types.HomesteadSigner{}
// Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_markets_test)
generator := func(i int, block *core.BlockGen) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx, _ := types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
tx1, _ := types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx2, _ := types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(acc1Key)
tx1, _ := types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, testBankKey)
tx2, _ := types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:
@@ -396,18 +397,19 @@ func testGetReceipt(t *testing.T, protocol int) {
acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
signer := types.HomesteadSigner{}
// Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_markets_test)
generator := func(i int, block *core.BlockGen) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx, _ := types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
tx1, _ := types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx2, _ := types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(acc1Key)
tx1, _ := types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, testBankKey)
tx2, _ := types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:
@@ -466,7 +468,7 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool
pow = new(core.FakePow)
db, _ = ethdb.NewMemDatabase()
genesis = core.WriteGenesisBlockForTesting(db)
config = &core.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
config = &params.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
blockchain, _ = core.NewBlockChain(db, config, pow, evmux)
)
pm, err := NewProtocolManager(config, false, NetworkId, 1000, evmux, new(testTxPool), pow, blockchain, db)
@@ -491,7 +493,7 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool
}
// Create a block to reply to the challenge if no timeout is simualted
if !timeout {
blocks, _ := core.GenerateChain(nil, genesis, db, 1, func(i int, block *core.BlockGen) {
blocks, _ := core.GenerateChain(&params.ChainConfig{}, genesis, db, 1, func(i int, block *core.BlockGen) {
if remoteForked {
block.SetExtra(params.DAOForkBlockExtra)
}
+5 -4
View File
@@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/params"
)
var (
@@ -54,10 +55,10 @@ func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core
pow = new(core.FakePow)
db, _ = ethdb.NewMemDatabase()
genesis = core.WriteGenesisBlockForTesting(db, testBank)
chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
chainConfig = &params.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux)
)
chain, _ := core.GenerateChain(nil, genesis, db, blocks, generator)
chain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
if _, err := blockchain.InsertChain(chain); err != nil {
panic(err)
}
@@ -109,7 +110,7 @@ func (p *testTxPool) Pending() map[common.Address]types.Transactions {
batches := make(map[common.Address]types.Transactions)
for _, tx := range p.pool {
from, _ := tx.From()
from, _ := types.Sender(types.HomesteadSigner{}, tx)
batches[from] = append(batches[from], tx)
}
for _, batch := range batches {
@@ -121,7 +122,7 @@ func (p *testTxPool) Pending() map[common.Address]types.Transactions {
// newTestTransaction create a new dummy transaction.
func newTestTransaction(from *ecdsa.PrivateKey, nonce uint64, datasize int) *types.Transaction {
tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), big.NewInt(100000), big.NewInt(0), make([]byte, datasize))
tx, _ = tx.SignECDSA(from)
tx, _ = tx.SignECDSA(types.HomesteadSigner{}, from)
return tx
}
+6 -2
View File
@@ -147,7 +147,7 @@ func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (*typ
var tx *types.Transaction
err := ec.c.CallContext(ctx, &tx, "eth_getTransactionByHash", hash)
if err == nil {
if _, r, _ := tx.SignatureValues(); r == nil {
if _, r, _ := tx.RawSignatureValues(); r == nil {
return nil, fmt.Errorf("server returned transaction without signature")
}
}
@@ -166,7 +166,11 @@ func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash,
var tx *types.Transaction
err := ec.c.CallContext(ctx, &tx, "eth_getTransactionByBlockHashAndIndex", blockHash, index)
if err == nil {
if _, r, _ := tx.SignatureValues(); r == nil {
var signer types.Signer = types.HomesteadSigner{}
if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainId())
}
if _, r, _ := types.SignatureValues(signer, tx); r == nil {
return nil, fmt.Errorf("server returned transaction without signature")
}
}
+52 -34
View File
@@ -279,7 +279,8 @@ func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
}
signature, err := s.am.SignWithPassphrase(args.From, passwd, tx.SigHash().Bytes())
signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number())
signature, err := s.am.SignWithPassphrase(args.From, passwd, signer.Hash(tx).Bytes())
if err != nil {
return common.Hash{}, err
}
@@ -537,22 +538,14 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
}
// Assemble the CALL invocation
msg := callmsg{
addr: addr,
to: args.To,
gas: args.Gas.BigInt(),
gasPrice: args.GasPrice.BigInt(),
value: args.Value.BigInt(),
data: common.FromHex(args.Data),
gas, gasPrice := args.Gas.BigInt(), args.GasPrice.BigInt()
if gas.Cmp(common.Big0) == 0 {
gas = big.NewInt(50000000)
}
if msg.gas.Cmp(common.Big0) == 0 {
msg.gas = big.NewInt(50000000)
}
if msg.gasPrice.Cmp(common.Big0) == 0 {
msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
if gasPrice.Cmp(common.Big0) == 0 {
gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
}
msg := types.NewMessage(addr, args.To, 0, args.Value.BigInt(), gas, gasPrice, common.FromHex(args.Data))
// Execute the call and return
vmenv, vmError, err := s.b.GetVMEnv(ctx, msg, state, header)
@@ -714,8 +707,12 @@ type RPCTransaction struct {
// newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation
func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction {
from, _ := tx.FromFrontier()
v, r, s := tx.SignatureValues()
var signer types.Signer = types.FrontierSigner{}
if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainId())
}
from, _ := types.Sender(signer, tx)
v, r, s := types.SignatureValues(signer, tx)
return &RPCTransaction{
From: from,
Gas: rpc.NewHexNumber(tx.Gas()),
@@ -735,11 +732,12 @@ func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction {
func newRPCTransactionFromBlockIndex(b *types.Block, txIndex int) (*RPCTransaction, error) {
if txIndex >= 0 && txIndex < len(b.Transactions()) {
tx := b.Transactions()[txIndex]
from, err := tx.FromFrontier()
if err != nil {
return nil, err
var signer types.Signer = types.FrontierSigner{}
if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainId())
}
v, r, s := tx.SignatureValues()
from, _ := types.Sender(signer, tx)
v, r, s := tx.RawSignatureValues()
return &RPCTransaction{
BlockHash: b.Hash(),
BlockNumber: rpc.NewHexNumber(b.Number()),
@@ -958,11 +956,11 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma
return nil, nil
}
from, err := tx.FromFrontier()
if err != nil {
glog.V(logger.Debug).Infof("%v\n", err)
return nil, nil
var signer types.Signer = types.FrontierSigner{}
if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainId())
}
from, _ := types.Sender(signer, tx)
fields := map[string]interface{}{
"root": rpc.HexBytes(receipt.PostState),
@@ -990,11 +988,13 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma
// sign is a helper function that signs a transaction with the private key of the given address.
func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
signature, err := s.b.AccountManager().SignEthereum(addr, tx.SigHash().Bytes())
signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number())
signature, err := s.b.AccountManager().SignEthereum(addr, signer.Hash(tx).Bytes())
if err != nil {
return nil, err
}
return tx.WithSignature(signature)
return tx.WithSignature(signer, signature)
}
// SendTxArgs represents the arguments to sumbit a new transaction into the transaction pool.
@@ -1028,7 +1028,9 @@ func prepareSendTxArgs(ctx context.Context, args SendTxArgs, b Backend) (SendTxA
// submitTransaction is a helper function that submits tx to txPool and creates a log entry.
func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction, signature []byte) (common.Hash, error) {
signedTx, err := tx.WithSignature(signature)
signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number())
signedTx, err := tx.WithSignature(signer, signature)
if err != nil {
return common.Hash{}, err
}
@@ -1038,7 +1040,7 @@ func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction, si
}
if signedTx.To() == nil {
from, _ := signedTx.From()
from, _ := types.Sender(signer, signedTx)
addr := crypto.CreateAddress(from, signedTx.Nonce())
glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex())
} else {
@@ -1072,7 +1074,8 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
}
signature, err := s.b.AccountManager().SignEthereum(args.From, tx.SigHash().Bytes())
signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number())
signature, err := s.b.AccountManager().SignEthereum(args.From, signer.Hash(tx).Bytes())
if err != nil {
return common.Hash{}, err
}
@@ -1092,8 +1095,9 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod
return "", err
}
signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number())
if tx.To() == nil {
from, err := tx.FromFrontier()
from, err := types.Sender(signer, tx)
if err != nil {
return "", err
}
@@ -1202,7 +1206,12 @@ type SignTransactionResult struct {
}
func newTx(t *types.Transaction) *Tx {
from, _ := t.FromFrontier()
var signer types.Signer = types.HomesteadSigner{}
if t.Protected() {
signer = types.NewEIP155Signer(t.ChainId())
}
from, _ := types.Sender(signer, t)
return &Tx{
tx: t,
To: t.To(),
@@ -1268,7 +1277,11 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() []*RPCTransaction {
pending := s.b.GetPoolTransactions()
transactions := make([]*RPCTransaction, 0, len(pending))
for _, tx := range pending {
from, _ := tx.FromFrontier()
var signer types.Signer = types.HomesteadSigner{}
if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainId())
}
from, _ := types.Sender(signer, tx)
if s.b.AccountManager().HasAddress(from) {
transactions = append(transactions, newRPCPendingTransaction(tx))
}
@@ -1281,7 +1294,12 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() []*RPCTransaction {
func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, tx Tx, gasPrice, gasLimit *rpc.HexNumber) (common.Hash, error) {
pending := s.b.GetPoolTransactions()
for _, p := range pending {
if pFrom, err := p.FromFrontier(); err == nil && pFrom == tx.From && p.SigHash() == tx.tx.SigHash() {
var signer types.Signer = types.HomesteadSigner{}
if p.Protected() {
signer = types.NewEIP155Signer(p.ChainId())
}
if pFrom, err := types.Sender(signer, p); err == nil && pFrom == tx.From && signer.Hash(p) == signer.Hash(tx.tx) {
if gasPrice == nil {
gasPrice = rpc.NewHexNumber(tx.tx.GasPrice())
}
+4
View File
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"golang.org/x/net/context"
)
@@ -59,6 +60,9 @@ type Backend interface {
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
Stats() (pending int, queued int)
TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions)
ChainConfig() *params.ChainConfig
CurrentBlock() *types.Block
}
type State interface {
+3 -6
View File
@@ -29,11 +29,6 @@ import (
"github.com/ethereum/go-ethereum/params"
)
type ruleSet struct{}
func (self *ruleSet) IsHomestead(*big.Int) bool { return true }
func (*ruleSet) GasTable(*big.Int) params.GasTable { return params.GasTableHomesteadGasRepriceFork }
type Env struct {
gasLimit *big.Int
depth int
@@ -46,7 +41,9 @@ func NewEnv(config *vm.Config) *Env {
return env
}
func (self *Env) RuleSet() vm.RuleSet { return &ruleSet{} }
func (self *Env) ChainConfig() *params.ChainConfig {
return params.TestChainConfig
}
func (self *Env) Vm() vm.Vm { return self.evm }
func (self *Env) Origin() common.Address { return common.Address{} }
func (self *Env) BlockNumber() *big.Int { return big.NewInt(0) }
+11 -2
View File
@@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/params"
rpc "github.com/ethereum/go-ethereum/rpc"
"golang.org/x/net/context"
)
@@ -39,6 +40,14 @@ type LesApiBackend struct {
gpo *gasprice.LightPriceOracle
}
func (b *LesApiBackend) ChainConfig() *params.ChainConfig {
return b.eth.chainConfig
}
func (b *LesApiBackend) CurrentBlock() *types.Block {
return types.NewBlockWithHeader(b.eth.BlockChain().CurrentHeader())
}
func (b *LesApiBackend) SetHead(number uint64) {
b.eth.blockchain.SetHead(number)
}
@@ -81,13 +90,13 @@ func (b *LesApiBackend) GetTd(blockHash common.Hash) *big.Int {
func (b *LesApiBackend) GetVMEnv(ctx context.Context, msg core.Message, state ethapi.State, header *types.Header) (vm.Environment, func() error, error) {
stateDb := state.(*light.LightState).Copy()
addr, _ := msg.From()
addr := msg.From()
from, err := stateDb.GetOrNewStateObject(ctx, addr)
if err != nil {
return nil, nil, err
}
from.SetBalance(common.MaxBig)
env := light.NewEnv(ctx, stateDb, b.eth.chainConfig, b.eth.blockchain, msg, header, b.eth.chainConfig.VmConfig)
env := light.NewEnv(ctx, stateDb, b.eth.chainConfig, b.eth.blockchain, msg, header, vm.Config{})
return env, env.Error, nil
}
+2 -6
View File
@@ -29,7 +29,6 @@ import (
"github.com/ethereum/go-ethereum/common/httpclient"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/filters"
@@ -42,13 +41,14 @@ import (
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params"
rpc "github.com/ethereum/go-ethereum/rpc"
)
type LightEthereum struct {
odr *LesOdr
relay *LesTxRelay
chainConfig *core.ChainConfig
chainConfig *params.ChainConfig
// Channel for shutting down the service
shutdownChan chan bool
// Handlers
@@ -107,10 +107,6 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
return nil, errors.New("missing chain config")
}
eth.chainConfig = config.ChainConfig
eth.chainConfig.VmConfig = vm.Config{
EnableJit: config.EnableJit,
ForceJit: config.ForceJit,
}
eth.blockchain, err = light.NewLightChain(odr, eth.chainConfig, eth.pow, eth.eventMux)
if err != nil {
if err == core.ErrNoGenesis {
+3 -2
View File
@@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/discv5"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
@@ -95,7 +96,7 @@ type ProtocolManager struct {
txpool txPool
txrelay *LesTxRelay
networkId int
chainConfig *core.ChainConfig
chainConfig *params.ChainConfig
blockchain BlockChain
chainDb ethdb.Database
odr *LesOdr
@@ -129,7 +130,7 @@ type ProtocolManager struct {
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
// with the ethereum network.
func NewProtocolManager(chainConfig *core.ChainConfig, lightSync bool, networkId int, mux *event.TypeMux, pow pow.PoW, blockchain BlockChain, txpool txPool, chainDb ethdb.Database, odr *LesOdr, txrelay *LesTxRelay) (*ProtocolManager, error) {
func NewProtocolManager(chainConfig *params.ChainConfig, lightSync bool, networkId int, mux *event.TypeMux, pow pow.PoW, blockchain BlockChain, txpool txPool, chainDb ethdb.Database, odr *LesOdr, txrelay *LesTxRelay) (*ProtocolManager, error) {
// Create the protocol manager with the base fields
manager := &ProtocolManager{
lightSync: lightSync,
+11 -9
View File
@@ -73,20 +73,22 @@ contract test {
*/
func testChainGen(i int, block *core.BlockGen) {
signer := types.HomesteadSigner{}
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
// acc1Addr creates a test contract.
tx1, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx1, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, testBankKey)
nonce := block.TxNonce(acc1Addr)
tx2, _ := types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(acc1Key)
tx2, _ := types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, acc1Key)
nonce++
tx3, _ := types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(200000), big.NewInt(0), testContractCode).SignECDSA(acc1Key)
tx3, _ := types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(200000), big.NewInt(0), testContractCode).SignECDSA(signer, acc1Key)
testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
block.AddTx(tx1)
block.AddTx(tx2)
@@ -96,7 +98,7 @@ func testChainGen(i int, block *core.BlockGen) {
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(testBankKey)
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(signer, testBankKey)
block.AddTx(tx)
case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
@@ -107,7 +109,7 @@ func testChainGen(i int, block *core.BlockGen) {
b3.Extra = []byte("foo")
block.AddUncle(b3)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(testBankKey)
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(signer, testBankKey)
block.AddTx(tx)
}
}
@@ -131,7 +133,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
pow = new(core.FakePow)
db, _ = ethdb.NewMemDatabase()
genesis = core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
chainConfig = &params.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
odr *LesOdr
chain BlockChain
)
@@ -141,7 +143,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
chain, _ = light.NewLightChain(odr, chainConfig, pow, evmux)
} else {
blockchain, _ := core.NewBlockChain(db, chainConfig, pow, evmux)
gchain, _ := core.GenerateChain(nil, genesis, db, blocks, generator)
gchain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
if _, err := blockchain.InsertChain(gchain); err != nil {
panic(err)
}
@@ -214,7 +216,7 @@ func (p *testTxPool) GetTransactions() types.Transactions {
// newTestTransaction create a new dummy transaction.
func newTestTransaction(from *ecdsa.PrivateKey, nonce uint64, datasize int) *types.Transaction {
tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), big.NewInt(100000), big.NewInt(0), make([]byte, datasize))
tx, _ = tx.SignECDSA(from)
tx, _ = tx.SignECDSA(types.HomesteadSigner{}, from)
return tx
}
+14 -61
View File
@@ -26,17 +26,19 @@ import (
"github.com/ethereum/go-ethereum/core"
"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/ethdb"
"github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/net/context"
)
type odrTestFn func(ctx context.Context, db ethdb.Database, config *core.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte
type odrTestFn func(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte
func TestOdrGetBlockLes1(t *testing.T) { testOdr(t, 1, 1, odrGetBlock) }
func odrGetBlock(ctx context.Context, db ethdb.Database, config *core.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
func odrGetBlock(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
var block *types.Block
if bc != nil {
block = bc.GetBlockByHash(bhash)
@@ -52,7 +54,7 @@ func odrGetBlock(ctx context.Context, db ethdb.Database, config *core.ChainConfi
func TestOdrGetReceiptsLes1(t *testing.T) { testOdr(t, 1, 1, odrGetReceipts) }
func odrGetReceipts(ctx context.Context, db ethdb.Database, config *core.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
func odrGetReceipts(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
var receipts types.Receipts
if bc != nil {
receipts = core.GetBlockReceipts(db, bhash, core.GetBlockNumber(db, bhash))
@@ -68,7 +70,7 @@ func odrGetReceipts(ctx context.Context, db ethdb.Database, config *core.ChainCo
func TestOdrAccountsLes1(t *testing.T) { testOdr(t, 1, 1, odrAccounts) }
func odrAccounts(ctx context.Context, db ethdb.Database, config *core.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
func odrAccounts(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
dummyAddr := common.HexToAddress("1234567812345678123456781234567812345678")
acc := []common.Address{testBankAddress, acc1Addr, acc2Addr, dummyAddr}
@@ -98,47 +100,13 @@ func odrAccounts(ctx context.Context, db ethdb.Database, config *core.ChainConfi
func TestOdrContractCallLes1(t *testing.T) { testOdr(t, 1, 2, odrContractCall) }
// fullcallmsg is the message type used for call transations.
type fullcallmsg struct {
from *state.StateObject
to *common.Address
gas, gasPrice *big.Int
value *big.Int
data []byte
type callmsg struct {
types.Message
}
// accessor boilerplate to implement core.Message
func (m fullcallmsg) From() (common.Address, error) { return m.from.Address(), nil }
func (m fullcallmsg) FromFrontier() (common.Address, error) { return m.from.Address(), nil }
func (m fullcallmsg) Nonce() uint64 { return 0 }
func (m fullcallmsg) CheckNonce() bool { return false }
func (m fullcallmsg) To() *common.Address { return m.to }
func (m fullcallmsg) GasPrice() *big.Int { return m.gasPrice }
func (m fullcallmsg) Gas() *big.Int { return m.gas }
func (m fullcallmsg) Value() *big.Int { return m.value }
func (m fullcallmsg) Data() []byte { return m.data }
func (callmsg) CheckNonce() bool { return false }
// callmsg is the message type used for call transations.
type lightcallmsg struct {
from *light.StateObject
to *common.Address
gas, gasPrice *big.Int
value *big.Int
data []byte
}
// accessor boilerplate to implement core.Message
func (m lightcallmsg) From() (common.Address, error) { return m.from.Address(), nil }
func (m lightcallmsg) FromFrontier() (common.Address, error) { return m.from.Address(), nil }
func (m lightcallmsg) Nonce() uint64 { return 0 }
func (m lightcallmsg) CheckNonce() bool { return false }
func (m lightcallmsg) To() *common.Address { return m.to }
func (m lightcallmsg) GasPrice() *big.Int { return m.gasPrice }
func (m lightcallmsg) Gas() *big.Int { return m.gas }
func (m lightcallmsg) Value() *big.Int { return m.value }
func (m lightcallmsg) Data() []byte { return m.data }
func odrContractCall(ctx context.Context, db ethdb.Database, config *core.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
func odrContractCall(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
data := common.Hex2Bytes("60CD26850000000000000000000000000000000000000000000000000000000000000000")
var res []byte
@@ -151,16 +119,8 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *core.ChainC
from := statedb.GetOrNewStateObject(testBankAddress)
from.SetBalance(common.MaxBig)
msg := fullcallmsg{
from: from,
gas: big.NewInt(100000),
gasPrice: big.NewInt(0),
value: big.NewInt(0),
data: data,
to: &testContractAddr,
}
vmenv := core.NewEnv(statedb, config, bc, msg, header, config.VmConfig)
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data)}
vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{})
gp := new(core.GasPool).AddGas(common.MaxBig)
ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...)
@@ -172,16 +132,9 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *core.ChainC
if err == nil {
from.SetBalance(common.MaxBig)
msg := lightcallmsg{
from: from,
gas: big.NewInt(100000),
gasPrice: big.NewInt(0),
value: big.NewInt(0),
data: data,
to: &testContractAddr,
}
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data)}
vmenv := light.NewEnv(ctx, state, config, lc, msg, header, config.VmConfig)
vmenv := light.NewEnv(ctx, state, config, lc, msg, header, vm.Config{})
gp := new(core.GasPool).AddGas(common.MaxBig)
ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
if vmenv.Error() == nil {
+2 -1
View File
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
"github.com/hashicorp/golang-lru"
@@ -71,7 +72,7 @@ type LightChain struct {
// NewLightChain returns a fully initialised light chain using information
// available in the database. It initialises the default Ethereum header
// validator.
func NewLightChain(odr OdrBackend, config *core.ChainConfig, pow pow.PoW, mux *event.TypeMux) (*LightChain, error) {
func NewLightChain(odr OdrBackend, config *params.ChainConfig, pow pow.PoW, mux *event.TypeMux) (*LightChain, error) {
bodyCache, _ := lru.New(bodyCacheLimit)
bodyRLPCache, _ := lru.New(bodyCacheLimit)
blockCache, _ := lru.New(blockCacheLimit)
+4 -3
View File
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/hashicorp/golang-lru"
"golang.org/x/net/context"
@@ -41,7 +42,7 @@ var (
// makeHeaderChain creates a deterministic chain of headers rooted at parent.
func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) []*types.Header {
blocks, _ := core.GenerateChain(nil, types.NewBlockWithHeader(parent), db, n, func(i int, b *core.BlockGen) {
blocks, _ := core.GenerateChain(params.TestChainConfig, types.NewBlockWithHeader(parent), db, n, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
})
headers := make([]*types.Header, len(blocks))
@@ -51,8 +52,8 @@ func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) [
return headers
}
func testChainConfig() *core.ChainConfig {
return &core.ChainConfig{HomesteadBlock: big.NewInt(0)}
func testChainConfig() *params.ChainConfig {
return &params.ChainConfig{HomesteadBlock: big.NewInt(0)}
}
// newCanonical creates a chain database, and injects a deterministic canonical
+14 -62
View File
@@ -148,45 +148,11 @@ func odrAccounts(ctx context.Context, db ethdb.Database, bc *core.BlockChain, lc
func TestOdrContractCallLes1(t *testing.T) { testChainOdr(t, 1, 2, odrContractCall) }
// fullcallmsg is the message type used for call transations.
type fullcallmsg struct {
from *state.StateObject
to *common.Address
gas, gasPrice *big.Int
value *big.Int
data []byte
type callmsg struct {
types.Message
}
// accessor boilerplate to implement core.Message
func (m fullcallmsg) From() (common.Address, error) { return m.from.Address(), nil }
func (m fullcallmsg) FromFrontier() (common.Address, error) { return m.from.Address(), nil }
func (m fullcallmsg) Nonce() uint64 { return 0 }
func (m fullcallmsg) CheckNonce() bool { return false }
func (m fullcallmsg) To() *common.Address { return m.to }
func (m fullcallmsg) GasPrice() *big.Int { return m.gasPrice }
func (m fullcallmsg) Gas() *big.Int { return m.gas }
func (m fullcallmsg) Value() *big.Int { return m.value }
func (m fullcallmsg) Data() []byte { return m.data }
// callmsg is the message type used for call transations.
type lightcallmsg struct {
from *StateObject
to *common.Address
gas, gasPrice *big.Int
value *big.Int
data []byte
}
// accessor boilerplate to implement core.Message
func (m lightcallmsg) From() (common.Address, error) { return m.from.Address(), nil }
func (m lightcallmsg) FromFrontier() (common.Address, error) { return m.from.Address(), nil }
func (m lightcallmsg) Nonce() uint64 { return 0 }
func (m lightcallmsg) CheckNonce() bool { return false }
func (m lightcallmsg) To() *common.Address { return m.to }
func (m lightcallmsg) GasPrice() *big.Int { return m.gasPrice }
func (m lightcallmsg) Gas() *big.Int { return m.gas }
func (m lightcallmsg) Value() *big.Int { return m.value }
func (m lightcallmsg) Data() []byte { return m.data }
func (callmsg) CheckNonce() bool { return false }
func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain, lc *LightChain, bhash common.Hash) []byte {
data := common.Hex2Bytes("60CD26850000000000000000000000000000000000000000000000000000000000000000")
@@ -201,15 +167,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
from := statedb.GetOrNewStateObject(testBankAddress)
from.SetBalance(common.MaxBig)
msg := fullcallmsg{
from: from,
gas: big.NewInt(100000),
gasPrice: big.NewInt(0),
value: big.NewInt(0),
data: data,
to: &testContractAddr,
}
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data)}
vmenv := core.NewEnv(statedb, testChainConfig(), bc, msg, header, vm.Config{})
gp := new(core.GasPool).AddGas(common.MaxBig)
ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
@@ -222,15 +180,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
if err == nil {
from.SetBalance(common.MaxBig)
msg := lightcallmsg{
from: from,
gas: big.NewInt(100000),
gasPrice: big.NewInt(0),
value: big.NewInt(0),
data: data,
to: &testContractAddr,
}
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data)}
vmenv := NewEnv(ctx, state, testChainConfig(), lc, msg, header, vm.Config{})
gp := new(core.GasPool).AddGas(common.MaxBig)
ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
@@ -244,20 +194,21 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
}
func testChainGen(i int, block *core.BlockGen) {
signer := types.HomesteadSigner{}
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
// acc1Addr creates a test contract.
tx1, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx1, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, testBankKey)
nonce := block.TxNonce(acc1Addr)
tx2, _ := types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(acc1Key)
tx2, _ := types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, acc1Key)
nonce++
tx3, _ := types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(1000000), big.NewInt(0), testContractCode).SignECDSA(acc1Key)
tx3, _ := types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(1000000), big.NewInt(0), testContractCode).SignECDSA(signer, acc1Key)
testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
block.AddTx(tx1)
block.AddTx(tx2)
@@ -267,7 +218,7 @@ func testChainGen(i int, block *core.BlockGen) {
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(testBankKey)
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(signer, testBankKey)
block.AddTx(tx)
case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
@@ -278,7 +229,7 @@ func testChainGen(i int, block *core.BlockGen) {
b3.Extra = []byte("foo")
block.AddUncle(b3)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(testBankKey)
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(signer, testBankKey)
block.AddTx(tx)
}
}
@@ -294,7 +245,8 @@ func testChainOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
// Assemble the test environment
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux)
gchain, _ := core.GenerateChain(nil, genesis, sdb, 4, testChainGen)
chainConfig := &params.ChainConfig{HomesteadBlock: new(big.Int)}
gchain, _ := core.GenerateChain(chainConfig, genesis, sdb, 4, testChainGen)
if _, err := blockchain.InsertChain(gchain); err != nil {
panic(err)
}
+1 -1
View File
@@ -41,7 +41,7 @@ func makeTestState() (common.Hash, ethdb.Database) {
st.AddBalance(addr, big.NewInt(int64(i)))
st.SetCode(addr, []byte{i, i, i})
}
root, _ := st.Commit()
root, _ := st.Commit(false)
return root, sdb
}
+13 -8
View File
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/net/context"
)
@@ -42,7 +43,8 @@ var txPermanent = uint64(500)
// always receive all locally signed transactions in the same order as they are
// created.
type TxPool struct {
config *core.ChainConfig
config *params.ChainConfig
signer types.Signer
quit chan bool
eventMux *event.TypeMux
events event.Subscription
@@ -76,9 +78,10 @@ type TxRelayBackend interface {
}
// NewTxPool creates a new light transaction pool
func NewTxPool(config *core.ChainConfig, eventMux *event.TypeMux, chain *LightChain, relay TxRelayBackend) *TxPool {
func NewTxPool(config *params.ChainConfig, eventMux *event.TypeMux, chain *LightChain, relay TxRelayBackend) *TxPool {
pool := &TxPool{
config: config,
signer: types.HomesteadSigner{},
nonce: make(map[common.Address]uint64),
pending: make(map[common.Hash]*types.Transaction),
mined: make(map[common.Hash][]*types.Transaction),
@@ -197,7 +200,7 @@ func (pool *TxPool) checkMinedTxs(ctx context.Context, hash common.Hash, idx uin
if len(receipts) != len(block.Transactions()) {
panic(nil) // should never happen if hashes did match
}
core.SetReceiptsData(block, receipts)
core.SetReceiptsData(pool.config, block, receipts)
}
//fmt.Println("WriteReceipt", receipts[i].TxHash)
core.WriteReceipt(pool.chainDb, receipts[i])
@@ -308,6 +311,7 @@ func (pool *TxPool) eventLoop() {
m, r := txc.getLists()
pool.relay.NewHead(pool.head, m, r)
pool.homestead = pool.config.IsHomestead(head.Number)
pool.signer = types.MakeSigner(pool.config, head.Number)
pool.mu.Unlock()
}
}
@@ -339,7 +343,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
// Validate the transaction sender and it's sig. Throw
// if the from fields is invalid.
if from, err = tx.From(); err != nil {
if from, err = types.Sender(pool.signer, tx); err != nil {
return core.ErrInvalidSender
}
@@ -388,7 +392,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
}
// Should supply enough intrinsic gas
if tx.Gas().Cmp(core.IntrinsicGas(tx.Data(), core.MessageCreatesContract(tx), pool.homestead)) < 0 {
if tx.Gas().Cmp(core.IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)) < 0 {
return core.ErrIntrinsicGas
}
@@ -412,7 +416,8 @@ func (self *TxPool) add(ctx context.Context, tx *types.Transaction) error {
self.pending[hash] = tx
nonce := tx.Nonce() + 1
addr, _ := tx.From()
addr, _ := types.Sender(self.signer, tx)
if nonce > self.nonce[addr] {
self.nonce[addr] = nonce
}
@@ -432,7 +437,7 @@ func (self *TxPool) add(ctx context.Context, tx *types.Transaction) error {
}
// we can ignore the error here because From is
// verified in ValidateTransaction.
f, _ := tx.From()
f, _ := types.Sender(self.signer, tx)
from := common.Bytes2Hex(f[:4])
glog.Infof("(t) %x => %s (%v) %x\n", from, toname, tx.Value, hash)
}
@@ -517,7 +522,7 @@ func (self *TxPool) Content() (map[common.Address]types.Transactions, map[common
// Retrieve all the pending transactions and sort by account and by nonce
pending := make(map[common.Address]types.Transactions)
for _, tx := range self.pending {
account, _ := tx.From()
account, _ := types.Sender(self.signer, tx)
pending[account] = append(pending[account], tx)
}
// There are no queued transactions in a light pool, just return an empty map
+3 -2
View File
@@ -74,7 +74,7 @@ func txPoolTestChainGen(i int, block *core.BlockGen) {
func TestTxPool(t *testing.T) {
for i, _ := range testTx {
testTx[i], _ = types.NewTransaction(uint64(i), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey)
testTx[i], _ = types.NewTransaction(uint64(i), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(types.HomesteadSigner{}, testBankKey)
}
var (
@@ -87,7 +87,8 @@ func TestTxPool(t *testing.T) {
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
// Assemble the test environment
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux)
gchain, _ := core.GenerateChain(nil, genesis, sdb, poolTestBlocks, txPoolTestChainGen)
chainConfig := &params.ChainConfig{HomesteadBlock: new(big.Int)}
gchain, _ := core.GenerateChain(chainConfig, genesis, sdb, poolTestBlocks, txPoolTestChainGen)
if _, err := blockchain.InsertChain(gchain); err != nil {
panic(err)
}
+14 -13
View File
@@ -24,6 +24,7 @@ import (
"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"
"golang.org/x/net/context"
)
@@ -34,7 +35,7 @@ import (
type VMEnv struct {
vm.Environment
ctx context.Context
chainConfig *core.ChainConfig
chainConfig *params.ChainConfig
evm *vm.EVM
state *VMState
header *types.Header
@@ -45,7 +46,7 @@ type VMEnv struct {
}
// NewEnv creates a new execution environment based on an ODR capable light state
func NewEnv(ctx context.Context, state *LightState, chainConfig *core.ChainConfig, chain *LightChain, msg core.Message, header *types.Header, cfg vm.Config) *VMEnv {
func NewEnv(ctx context.Context, state *LightState, chainConfig *params.ChainConfig, chain *LightChain, msg core.Message, header *types.Header, cfg vm.Config) *VMEnv {
env := &VMEnv{
chainConfig: chainConfig,
chain: chain,
@@ -58,17 +59,17 @@ func NewEnv(ctx context.Context, state *LightState, chainConfig *core.ChainConfi
return env
}
func (self *VMEnv) RuleSet() vm.RuleSet { return self.chainConfig }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f }
func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number }
func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase }
func (self *VMEnv) Time() *big.Int { return self.header.Time }
func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty }
func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit }
func (self *VMEnv) Db() vm.Database { return self.state }
func (self *VMEnv) Depth() int { return self.depth }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) ChainConfig() *params.ChainConfig { return self.chainConfig }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Origin() common.Address { return self.msg.From() }
func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number }
func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase }
func (self *VMEnv) Time() *big.Int { return self.header.Time }
func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty }
func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit }
func (self *VMEnv) Db() vm.Database { return self.state }
func (self *VMEnv) Depth() int { return self.depth }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) GetHash(n uint64) common.Hash {
for header := self.chain.GetHeader(self.header.ParentHash, self.header.Number.Uint64()-1); header != nil; header = self.chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) {
if header.Number.Uint64() == n {
+1 -1
View File
@@ -62,7 +62,7 @@ type Miner struct {
shouldStart int32 // should start indicates whether we should start after sync
}
func New(eth Backend, config *core.ChainConfig, mux *event.TypeMux, pow pow.PoW) *Miner {
func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, pow pow.PoW) *Miner {
miner := &Miner{
eth: eth,
mux: mux,
+21 -15
View File
@@ -63,7 +63,9 @@ type uint64RingBuffer struct {
// Work is the workers current environment and holds
// all of the current state information
type Work struct {
config *core.ChainConfig
config *params.ChainConfig
signer types.Signer
state *state.StateDB // apply state changes here
ancestors *set.Set // ancestor set (used for checking uncle parent validity)
family *set.Set // family set (used for checking uncle invalidity)
@@ -90,7 +92,7 @@ type Result struct {
// worker is the main object which takes care of applying messages to the new state
type worker struct {
config *core.ChainConfig
config *params.ChainConfig
mu sync.Mutex
@@ -128,7 +130,7 @@ type worker struct {
fullValidation bool
}
func newWorker(config *core.ChainConfig, coinbase common.Address, eth Backend, mux *event.TypeMux) *worker {
func newWorker(config *params.ChainConfig, coinbase common.Address, eth Backend, mux *event.TypeMux) *worker {
worker := &worker{
config: config,
eth: eth,
@@ -235,7 +237,7 @@ func (self *worker) update() {
if atomic.LoadInt32(&self.mining) == 0 {
self.currentMu.Lock()
acc, _ := ev.Tx.From()
acc, _ := types.Sender(self.current.signer, ev.Tx)
txs := map[common.Address]types.Transactions{acc: types.Transactions{ev.Tx}}
txset := types.NewTransactionsByPriceAndNonce(txs)
@@ -276,7 +278,7 @@ func (self *worker) wait() {
}
go self.mux.Post(core.NewMinedBlockEvent{Block: block})
} else {
work.state.Commit()
work.state.Commit(self.config.IsEIP158(block.Number()))
parent := self.chain.GetBlock(block.ParentHash(), block.NumberU64()-1)
if parent == nil {
glog.V(logger.Error).Infoln("Invalid block found during mining")
@@ -367,6 +369,7 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error
}
work := &Work{
config: self.config,
signer: types.NewEIP155Signer(self.config.ChainId),
state: state,
ancestors: set.New(),
family: set.New(),
@@ -528,7 +531,7 @@ func (self *worker) commitNewWork() {
if atomic.LoadInt32(&self.mining) == 1 {
// commit state root after all state transitions.
core.AccumulateRewards(work.state, header, uncles)
header.Root = work.state.IntermediateRoot()
header.Root = work.state.IntermediateRoot(self.config.IsEIP158(header.Number))
}
// create the new block whose nonce will be mined.
@@ -570,7 +573,17 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
}
// Error may be ignored here. The error has already been checked
// during transaction acceptance is the transaction pool.
from, _ := tx.From()
//
// We use the eip155 signer regardless of the current hf.
from, _ := types.Sender(env.signer, tx)
// Check whether the tx is replay protected. If we're not in the EIP155 hf
// phase, start ignoring the sender until we do.
if tx.Protected() && !env.config.IsEIP155(env.header.Number) {
glog.V(logger.Detail).Infof("Transaction (%x) is replay protected, but we haven't yet hardforked. Transaction will be ignored until we hardfork.\n", tx.Hash())
txs.Pop()
continue
}
// Ignore any transactions (and accounts subsequently) with low gas limits
if tx.GasPrice().Cmp(gasPrice) < 0 && !env.ownedAccounts.Has(from) {
@@ -620,14 +633,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
func (env *Work) commitTransaction(tx *types.Transaction, bc *core.BlockChain, gp *core.GasPool) (error, vm.Logs) {
snap := env.state.Snapshot()
// this is a bit of a hack to force jit for the miners
config := env.config.VmConfig
if !(config.EnableJit && config.ForceJit) {
config.EnableJit = false
}
config.ForceJit = false // disable forcing jit
receipt, logs, _, err := core.ApplyTransaction(env.config, bc, gp, env.state, env.header, tx, env.header.GasUsed, config)
receipt, logs, _, err := core.ApplyTransaction(env.config, bc, gp, env.state, env.header, tx, env.header.GasUsed, vm.Config{})
if err != nil {
env.state.RevertToSnapshot(snap)
return err, nil
+112
View File
@@ -0,0 +1,112 @@
// Copyright 2016 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 params
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
)
// ChainConfig is the core config which determines the blockchain settings.
//
// ChainConfig is stored in the database on a per block basis. This means
// that any network, identified by its genesis block, can have its own
// set of configuration options.
type ChainConfig struct {
ChainId *big.Int `json:"chainId"` // Chain id identifies the current chain and is used for replay protection
HomesteadBlock *big.Int `json:"homesteadBlock"` // Homestead switch block (nil = no fork, 0 = already homestead)
DAOForkBlock *big.Int `json:"daoForkBlock"` // TheDAO hard-fork switch block (nil = no fork)
DAOForkSupport bool `json:"daoForkSupport"` // Whether the nodes supports or opposes the DAO hard-fork
// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
EIP150Block *big.Int `json:"eip150Block"` // EIP150 HF block (nil = no fork)
EIP150Hash common.Hash `json:"eip150Hash"` // EIP150 HF hash (fast sync aid)
EIP155Block *big.Int `json:"eip155Block"` // EIP155 HF block
EIP158Block *big.Int `json:"eip158Block"` // EIP158 HF block
}
var (
TestChainConfig = &ChainConfig{big.NewInt(1), new(big.Int), new(big.Int), true, new(big.Int), common.Hash{}, new(big.Int), new(big.Int)}
TestRules = TestChainConfig.Rules(new(big.Int))
)
// IsHomestead returns whether num is either equal to the homestead block or greater.
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
if c.HomesteadBlock == nil || num == nil {
return false
}
return num.Cmp(c.HomesteadBlock) >= 0
}
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
//
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
func (c *ChainConfig) GasTable(num *big.Int) GasTable {
if num == nil {
return GasTableHomestead
}
switch {
case c.EIP158Block != nil && num.Cmp(c.EIP158Block) >= 0:
return GasTableEIP158
case c.EIP150Block != nil && num.Cmp(c.EIP150Block) >= 0:
return GasTableHomesteadGasRepriceFork
default:
return GasTableHomestead
}
}
func (c *ChainConfig) IsEIP150(num *big.Int) bool {
if c.EIP150Block == nil || num == nil {
return false
}
return num.Cmp(c.EIP150Block) >= 0
}
func (c *ChainConfig) IsEIP155(num *big.Int) bool {
if c.EIP155Block == nil || num == nil {
return false
}
return num.Cmp(c.EIP155Block) >= 0
}
func (c *ChainConfig) IsEIP158(num *big.Int) bool {
if c.EIP158Block == nil || num == nil {
return false
}
return num.Cmp(c.EIP158Block) >= 0
}
// Rules wraps ChainConfig and is merely syntatic sugar or can be used for functions
// that do not have or require information about the block.
//
// Rules is a one time interface meaning that it shouldn't be used in between transition
// phases.
type Rules struct {
ChainId *big.Int
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
}
func (c *ChainConfig) Rules(num *big.Int) Rules {
return Rules{ChainId: new(big.Int).Set(c.ChainId), IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), IsEIP155: c.IsEIP155(num), IsEIP158: c.IsEIP158(num)}
}
+18
View File
@@ -26,6 +26,8 @@ type GasTable struct {
Calls *big.Int
Suicide *big.Int
ExpByte *big.Int
// CreateBySuicide occurs when the
// refunded account is one that does
// not exist. This logic is similar
@@ -44,6 +46,7 @@ var (
SLoad: big.NewInt(50),
Calls: big.NewInt(40),
Suicide: big.NewInt(0),
ExpByte: big.NewInt(10),
// explicitly set to nil to indicate
// this rule does not apply to homestead.
@@ -52,6 +55,8 @@ var (
// GasTableHomestead contain the gas re-prices for
// the homestead phase.
//
// TODO rename to GasTableEIP150
GasTableHomesteadGasRepriceFork = GasTable{
ExtcodeSize: big.NewInt(700),
ExtcodeCopy: big.NewInt(700),
@@ -59,6 +64,19 @@ var (
SLoad: big.NewInt(200),
Calls: big.NewInt(700),
Suicide: big.NewInt(5000),
ExpByte: big.NewInt(10),
CreateBySuicide: big.NewInt(25000),
}
GasTableEIP158 = GasTable{
ExtcodeSize: big.NewInt(700),
ExtcodeCopy: big.NewInt(700),
Balance: big.NewInt(400),
SLoad: big.NewInt(200),
Calls: big.NewInt(700),
Suicide: big.NewInt(5000),
ExpByte: big.NewInt(50),
CreateBySuicide: big.NewInt(25000),
}
+1 -3
View File
@@ -14,9 +14,6 @@
// 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/>.
// DO NOT EDIT!!!
// AUTOGENERATED FROM generators/defaults.go
package params
import "math/big"
@@ -72,4 +69,5 @@ var (
MemoryGas = big.NewInt(3) // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
TxDataNonZeroGas = big.NewInt(68) // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
MaxCodeSize = 24576
)
+3
View File
@@ -34,4 +34,7 @@ var (
TestNetHomesteadGasRepriceHash = common.HexToHash("0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145") // Testnet gas reprice block hash (used by fast sync)
MainNetHomesteadGasRepriceHash = common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0") // Mainnet gas reprice block hash (used by fast sync)
TestNetSpuriousDragon = big.NewInt(3000000)
MainNetSpuriousDragon = big.NewInt(3000000)
)
+3 -2
View File
@@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -170,7 +171,7 @@ func runBlockTest(homesteadBlock, daoForkBlock, gasPriceFork *big.Int, test *Blo
core.WriteCanonicalHash(db, test.Genesis.Hash(), test.Genesis.NumberU64())
core.WriteHeadBlockHash(db, test.Genesis.Hash())
evmux := new(event.TypeMux)
config := &core.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true, HomesteadGasRepriceBlock: gasPriceFork}
config := &params.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true, EIP150Block: gasPriceFork}
chain, err := core.NewBlockChain(db, config, ethash.NewShared(), evmux)
if err != nil {
return err
@@ -228,7 +229,7 @@ func (t *BlockTest) InsertPreState(db ethdb.Database) (*state.StateDB, error) {
}
}
root, err := statedb.Commit()
root, err := statedb.Commit(false)
if err != nil {
return nil, fmt.Errorf("error writing state: %v", err)
}
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
@@ -0,0 +1,4 @@
Rules for .json tests execution in this folder:
All blocks starting from #0 are on Homestead+EIP150 rules
No Dao Transition rules applied
@@ -0,0 +1,644 @@
{
"GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideFirst" : {
"blocks" : [
{
"blockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x",
"gasLimit" : "0x0573e3",
"gasUsed" : "0x021efa",
"hash" : "8086802b019efc2bca969f14c1ced66661ff0250481dcfbaa609c60f0d490c34",
"mixHash" : "0f3f1d2ad01778b1b2c6c307df2f89dfc670b5efc82c0f8aef87a509e602997b",
"nonce" : "c29fac11db33446c",
"number" : "0x01",
"parentHash" : "6b68d5db45371f617741815045c95862f0fbcb659c1eb25dda1d63b15d7280af",
"receiptTrie" : "bb6c4ae4ebcbc88ae8357320da84cc4e3cbcd7d8e23324b4a2d9646680e65d44",
"stateRoot" : "96860dd0661d97a7f0d394ebc3505f9cb804be725da9a2b7800ab3f73c3e17fc",
"timestamp" : "0x580223b5",
"transactionsTrie" : "7ae056a6d50cfeb8d04816bc1d1e7751f4e054e04d9fde05f5ca200fa0c85b1a",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"rlp" : "0xf904a8f901faa06b68d5db45371f617741815045c95862f0fbcb659c1eb25dda1d63b15d7280afa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a096860dd0661d97a7f0d394ebc3505f9cb804be725da9a2b7800ab3f73c3e17fca07ae056a6d50cfeb8d04816bc1d1e7751f4e054e04d9fde05f5ca200fa0c85b1aa0bb6c4ae4ebcbc88ae8357320da84cc4e3cbcd7d8e23324b4a2d9646680e65d44b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001830573e383021efa84580223b580a00f3f1d2ad01778b1b2c6c307df2f89dfc670b5efc82c0f8aef87a509e602997b88c29fac11db33446cf902a7f85f800a82cb2094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba02609a830fd417f9e998391145c3e00efda383fd5ac9e67154a94c9a58ba57eaea00826134c963655d5f0d3c7b6e66a2978cd4b9e99e555d3d8540e60c0291b35ddf85f010a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca054b220ad38df2c2f927f6db93047e2fd19ed3d4fa3263c64db555529b00caddca0688f6a99a0a02850ebe5015a2bbacd780a236dffc2cf41069c7e9f374e618310f85f020a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0739f7287fe4c8c4d41a9721f7c7dca156a70e07c3bc58ac8680cc03add73cc5da056909c94e76719d959fa30679f1080431395f4b85f1fc011f2176ad9119f7dccf85f030a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca09a6b71ffd5ca40339dc032244b33b9dcee5c6c2f5a6519ccb695a959dde6a579a03003f276fa97709ae630cc53d301441e4527ab9645da02053676990943c0f73ef85f040a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca08070f1c4c61c8a2b8f6f814e08a0460dec7fd337e5fde990ad157239c92a7b8fa051dc860feae88e8851be7c7d9b3665d4185b6b85510bdb9426eb9806d0e3d5f0f85f050a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca016886934bf97dc78307bc6d4ad150255d15531043ac7e8073c599dc7903dbd4aa0413ba95502d806757c7b273f018904f19d5c0d441e3547002a387f0e55c4f406f85f060a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca08cdece94e5a6f5a3ea7b3962db6e623efc3c17b8668b94975657078b436c19f1a04453797459a63ca64d238328d86756995b688b4239e62c686aeb6a4e8003f0b8c0",
"transactions" : [
{
"data" : "0x",
"gasLimit" : "0xcb20",
"gasPrice" : "0x0a",
"nonce" : "0x00",
"r" : "0x2609a830fd417f9e998391145c3e00efda383fd5ac9e67154a94c9a58ba57eae",
"s" : "0x0826134c963655d5f0d3c7b6e66a2978cd4b9e99e555d3d8540e60c0291b35dd",
"to" : "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1b",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x01",
"r" : "0x54b220ad38df2c2f927f6db93047e2fd19ed3d4fa3263c64db555529b00caddc",
"s" : "0x688f6a99a0a02850ebe5015a2bbacd780a236dffc2cf41069c7e9f374e618310",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x02",
"r" : "0x739f7287fe4c8c4d41a9721f7c7dca156a70e07c3bc58ac8680cc03add73cc5d",
"s" : "0x56909c94e76719d959fa30679f1080431395f4b85f1fc011f2176ad9119f7dcc",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1b",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x03",
"r" : "0x9a6b71ffd5ca40339dc032244b33b9dcee5c6c2f5a6519ccb695a959dde6a579",
"s" : "0x3003f276fa97709ae630cc53d301441e4527ab9645da02053676990943c0f73e",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x04",
"r" : "0x8070f1c4c61c8a2b8f6f814e08a0460dec7fd337e5fde990ad157239c92a7b8f",
"s" : "0x51dc860feae88e8851be7c7d9b3665d4185b6b85510bdb9426eb9806d0e3d5f0",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x05",
"r" : "0x16886934bf97dc78307bc6d4ad150255d15531043ac7e8073c599dc7903dbd4a",
"s" : "0x413ba95502d806757c7b273f018904f19d5c0d441e3547002a387f0e55c4f406",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x06",
"r" : "0x8cdece94e5a6f5a3ea7b3962db6e623efc3c17b8668b94975657078b436c19f1",
"s" : "0x4453797459a63ca64d238328d86756995b688b4239e62c686aeb6a4e8003f0b8",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
}
],
"uncleHeaders" : [
]
}
],
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x42",
"gasLimit" : "0x057288",
"gasUsed" : "0x00",
"hash" : "6b68d5db45371f617741815045c95862f0fbcb659c1eb25dda1d63b15d7280af",
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0102030405060708",
"number" : "0x00",
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083057288808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
"lastblockhash" : "8086802b019efc2bca969f14c1ced66661ff0250481dcfbaa609c60f0d490c34",
"postState" : {
"8888f1f195afa192cfee860698584c030f4c9db1" : {
"balance" : "0x45639182450935c4",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x4a723dc6b40b8cedf6ae00",
"code" : "0x",
"nonce" : "0x07",
"storage" : {
}
},
"bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x3c",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x4a723dc6b40b8a9a000000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x02540be400",
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
"nonce" : "0x00",
"storage" : {
}
}
}
},
"GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideFirst2" : {
"blocks" : [
{
"blockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x",
"gasLimit" : "0x023ec6",
"gasUsed" : "0x01f018",
"hash" : "7f7b5aa2c8b0c530c860c294e1c68ce1da99e19f8adc9db3a39650d12e820cc2",
"mixHash" : "067968b01dfe7bd172a87f8380db26a013f8bc37147a406ba2ec67d2400a1265",
"nonce" : "c196d1163d69e2bb",
"number" : "0x01",
"parentHash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
"receiptTrie" : "516f24d9989eb3dec28434a8f1667a42342f98adb2524b980b9f116f9e93e487",
"stateRoot" : "d6c172507a4e3d5977e652d294075e0d35469808ded3843d62daa63f28281236",
"timestamp" : "0x580223b8",
"transactionsTrie" : "50f0f01320e78f4ea013368304ca412fd36cb758cd051a717378cc8dd18b871b",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"rlp" : "0xf90447f901faa0ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0d6c172507a4e3d5977e652d294075e0d35469808ded3843d62daa63f28281236a050f0f01320e78f4ea013368304ca412fd36cb758cd051a717378cc8dd18b871ba0516f24d9989eb3dec28434a8f1667a42342f98adb2524b980b9f116f9e93e487b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023ec68301f01884580223b880a0067968b01dfe7bd172a87f8380db26a013f8bc37147a406ba2ec67d2400a126588c196d1163d69e2bbf90246f85f800a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecda06baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188f85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506c0",
"transactions" : [
{
"data" : "0x",
"gasLimit" : "0x55f0",
"gasPrice" : "0x0a",
"nonce" : "0x00",
"r" : "0x575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecd",
"s" : "0x6baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188",
"to" : "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0x5208",
"gasPrice" : "0x0a",
"nonce" : "0x01",
"r" : "0x4fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5b",
"s" : "0x17bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192e",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1b",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0x5208",
"gasPrice" : "0x0a",
"nonce" : "0x02",
"r" : "0x04377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458ada",
"s" : "0x53a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0x5208",
"gasPrice" : "0x0a",
"nonce" : "0x03",
"r" : "0x4fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615",
"s" : "0x651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0x5208",
"gasPrice" : "0x0a",
"nonce" : "0x04",
"r" : "0x78e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567d",
"s" : "0x13254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198dd",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1b",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0x5208",
"gasPrice" : "0x0a",
"nonce" : "0x05",
"r" : "0xa7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54",
"s" : "0x534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1b",
"value" : "0x0a"
}
],
"uncleHeaders" : [
]
}
],
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x42",
"gasLimit" : "0x023e38",
"gasUsed" : "0x00",
"hash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0102030405060708",
"number" : "0x00",
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
"lastblockhash" : "7f7b5aa2c8b0c530c860c294e1c68ce1da99e19f8adc9db3a39650d12e820cc2",
"postState" : {
"8888f1f195afa192cfee860698584c030f4c9db1" : {
"balance" : "0x45639182450760f0",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x4a723dc6b40b8a99ec9ede",
"code" : "0x",
"nonce" : "0x06",
"storage" : {
}
},
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x02540be400",
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
"nonce" : "0x00",
"storage" : {
}
},
"bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x32",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x4a723dc6b40b8a9a000000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x02540be400",
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
"nonce" : "0x00",
"storage" : {
}
}
}
},
"GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideLast" : {
"blocks" : [
{
"blockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x",
"gasLimit" : "0x057224",
"gasUsed" : "0x021efa",
"hash" : "2eb60f05a7c1de9324272c530a036f9d7d4961bd0624a4305332688ee4f3a1ad",
"mixHash" : "46f46431ee1ccce22ed8a9ba68a376b13fdf11049fde4b0673ff9b7cb69a2113",
"nonce" : "7174ad3c7b1386db",
"number" : "0x01",
"parentHash" : "6b68d5db45371f617741815045c95862f0fbcb659c1eb25dda1d63b15d7280af",
"receiptTrie" : "2244456c1f7bdf7204250dfa2a2a1474014a9f50477ae0106dcf2dda6227a0f1",
"stateRoot" : "96860dd0661d97a7f0d394ebc3505f9cb804be725da9a2b7800ab3f73c3e17fc",
"timestamp" : "0x580223ba",
"transactionsTrie" : "f326b89e33ec4068bb300de24bb45f2a81e59333badd5b858e60e7239e984a00",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"rlp" : "0xf904a8f901faa06b68d5db45371f617741815045c95862f0fbcb659c1eb25dda1d63b15d7280afa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a096860dd0661d97a7f0d394ebc3505f9cb804be725da9a2b7800ab3f73c3e17fca0f326b89e33ec4068bb300de24bb45f2a81e59333badd5b858e60e7239e984a00a02244456c1f7bdf7204250dfa2a2a1474014a9f50477ae0106dcf2dda6227a0f1b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018305722483021efa84580223ba80a046f46431ee1ccce22ed8a9ba68a376b13fdf11049fde4b0673ff9b7cb69a2113887174ad3c7b1386dbf902a7f85f800a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0d5f556ab52e7baa68c0312f2482ec84288d55fec2e3feb617e11859269aea1f7a0546a329bf1ab773dcec4861c7341bcd8de5a0f3c75c37230a101cd0c8f763155f85f010a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca054b220ad38df2c2f927f6db93047e2fd19ed3d4fa3263c64db555529b00caddca0688f6a99a0a02850ebe5015a2bbacd780a236dffc2cf41069c7e9f374e618310f85f020a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0739f7287fe4c8c4d41a9721f7c7dca156a70e07c3bc58ac8680cc03add73cc5da056909c94e76719d959fa30679f1080431395f4b85f1fc011f2176ad9119f7dccf85f030a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca09a6b71ffd5ca40339dc032244b33b9dcee5c6c2f5a6519ccb695a959dde6a579a03003f276fa97709ae630cc53d301441e4527ab9645da02053676990943c0f73ef85f040a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca08070f1c4c61c8a2b8f6f814e08a0460dec7fd337e5fde990ad157239c92a7b8fa051dc860feae88e8851be7c7d9b3665d4185b6b85510bdb9426eb9806d0e3d5f0f85f050a82c73894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca016886934bf97dc78307bc6d4ad150255d15531043ac7e8073c599dc7903dbd4aa0413ba95502d806757c7b273f018904f19d5c0d441e3547002a387f0e55c4f406f85f060a82cb2094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0fac540b907e8ad85e503830b3ebdd35336fc535102bde0790987cd0ee253d876a0668bc7331874caefbb7d457161632482293e7df4c90c84a254850cabc13a83eac0",
"transactions" : [
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x00",
"r" : "0xd5f556ab52e7baa68c0312f2482ec84288d55fec2e3feb617e11859269aea1f7",
"s" : "0x546a329bf1ab773dcec4861c7341bcd8de5a0f3c75c37230a101cd0c8f763155",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x01",
"r" : "0x54b220ad38df2c2f927f6db93047e2fd19ed3d4fa3263c64db555529b00caddc",
"s" : "0x688f6a99a0a02850ebe5015a2bbacd780a236dffc2cf41069c7e9f374e618310",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x02",
"r" : "0x739f7287fe4c8c4d41a9721f7c7dca156a70e07c3bc58ac8680cc03add73cc5d",
"s" : "0x56909c94e76719d959fa30679f1080431395f4b85f1fc011f2176ad9119f7dcc",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1b",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x03",
"r" : "0x9a6b71ffd5ca40339dc032244b33b9dcee5c6c2f5a6519ccb695a959dde6a579",
"s" : "0x3003f276fa97709ae630cc53d301441e4527ab9645da02053676990943c0f73e",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x04",
"r" : "0x8070f1c4c61c8a2b8f6f814e08a0460dec7fd337e5fde990ad157239c92a7b8f",
"s" : "0x51dc860feae88e8851be7c7d9b3665d4185b6b85510bdb9426eb9806d0e3d5f0",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xc738",
"gasPrice" : "0x0a",
"nonce" : "0x05",
"r" : "0x16886934bf97dc78307bc6d4ad150255d15531043ac7e8073c599dc7903dbd4a",
"s" : "0x413ba95502d806757c7b273f018904f19d5c0d441e3547002a387f0e55c4f406",
"to" : "bbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x0a"
},
{
"data" : "0x",
"gasLimit" : "0xcb20",
"gasPrice" : "0x0a",
"nonce" : "0x06",
"r" : "0xfac540b907e8ad85e503830b3ebdd35336fc535102bde0790987cd0ee253d876",
"s" : "0x668bc7331874caefbb7d457161632482293e7df4c90c84a254850cabc13a83ea",
"to" : "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1b",
"value" : "0x0a"
}
],
"uncleHeaders" : [
]
}
],
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x42",
"gasLimit" : "0x057288",
"gasUsed" : "0x00",
"hash" : "6b68d5db45371f617741815045c95862f0fbcb659c1eb25dda1d63b15d7280af",
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0102030405060708",
"number" : "0x00",
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083057288808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
"lastblockhash" : "2eb60f05a7c1de9324272c530a036f9d7d4961bd0624a4305332688ee4f3a1ad",
"postState" : {
"8888f1f195afa192cfee860698584c030f4c9db1" : {
"balance" : "0x45639182450935c4",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x4a723dc6b40b8cedf6ae00",
"code" : "0x",
"nonce" : "0x07",
"storage" : {
}
},
"bbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x3c",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x4a723dc6b40b8a9a000000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x02540be400",
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
"nonce" : "0x00",
"storage" : {
}
}
}
},
"GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideLast2" : {
"blocks" : [
{
"rlp" : "0xf904a8f901faa0ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a053f912b64765458bba76c0978a8e5ecd90417d527ea20f55689108400763c8a039b55901ee38a65fa27c7d60137fd431afcf6a7615746ae9501e7cf0ca68bd11a071ba8e7c3c6ee55bfb14c3119ca5b4ceb032cfad51952e3a116a449240b38aa4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023dd48302422084580223bb80a04b470f8cc54688c5989133701126272e6c272a4a7853a5d05b27adc94460f50b88830f7ed5cbc7d1f9f902a7f85f800a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba01117bd549fe17f8383012bf168dabd9e70851fdf2f332e5bfea89318dddd6c77a001364d3a0e23f462052127c53a5473c428e2211806c927601562f840eb6b899cf85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0c40c1300a7cc64b842c9421a6c6e985b5531020d1a26c82f9c6a5200154e91dfa052c28fc6dc0dad9ea23fcce6510a9dc23b9903b1b19a126ac25f77a195b50f83c0"
}
],
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x42",
"gasLimit" : "0x023e38",
"gasUsed" : "0x00",
"hash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0102030405060708",
"number" : "0x00",
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
"lastblockhash" : "ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1ae",
"postState" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x4a723dc6b40b8a9a000000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x02540be400",
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
"nonce" : "0x00",
"storage" : {
}
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x4a723dc6b40b8a9a000000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x02540be400",
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
"nonce" : "0x00",
"storage" : {
}
}
}
},
"SuicideTransaction" : {
"blocks" : [
{
"blockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x",
"gasLimit" : "0x01e8c1",
"gasUsed" : "0x32ca",
"hash" : "a3eba1779c002a8e02f41bab6dea595cbad0e44d5c3fbbdd0ad908190c34c63d",
"mixHash" : "e13d00455c6d34792fcd2f2036744f822e2f269e8bc6f5a7389307812db0711d",
"nonce" : "97bf5b2844593304",
"number" : "0x01",
"parentHash" : "926fddd6a0f69ff8c29833222a7150b9d50f759bda6d50e4c9ea3af6c4ba921d",
"receiptTrie" : "10910901e8fd125dffe40187af7dae0d71bbf63f0fed0bb84bedc624586060f7",
"stateRoot" : "483344fadf21e2fc01ab19a4041532edc23747d017bb386edcc0859ba225fe0d",
"timestamp" : "0x580223bd",
"transactionsTrie" : "f0162cdb94cda8b79bf634c6093931008a12d1e4922821a992e34511b83ed0d5",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"rlp" : "0xf90261f901f9a0926fddd6a0f69ff8c29833222a7150b9d50f759bda6d50e4c9ea3af6c4ba921da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0483344fadf21e2fc01ab19a4041532edc23747d017bb386edcc0859ba225fe0da0f0162cdb94cda8b79bf634c6093931008a12d1e4922821a992e34511b83ed0d5a010910901e8fd125dffe40187af7dae0d71bbf63f0fed0bb84bedc624586060f7b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018301e8c18232ca84580223bd80a0e13d00455c6d34792fcd2f2036744f822e2f269e8bc6f5a7389307812db0711d8897bf5b2844593304f862f860800a830186a094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0444ed2cb67c1cce2c37add4bef48d3dda9ef05e28eaf023006036a4c5f7c96b0a00c56b07bfc50471d458e67923c91108b90cb7bba23f4d373f0a75632a413bd84c0",
"transactions" : [
{
"data" : "0x",
"gasLimit" : "0x0186a0",
"gasPrice" : "0x0a",
"nonce" : "0x00",
"r" : "0x444ed2cb67c1cce2c37add4bef48d3dda9ef05e28eaf023006036a4c5f7c96b0",
"s" : "0x0c56b07bfc50471d458e67923c91108b90cb7bba23f4d373f0a75632a413bd84",
"to" : "aaaf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1b",
"value" : "0x0a"
}
],
"uncleHeaders" : [
]
}
],
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x42",
"gasLimit" : "0x01e848",
"gasUsed" : "0x00",
"hash" : "926fddd6a0f69ff8c29833222a7150b9d50f759bda6d50e4c9ea3af6c4ba921d",
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0102030405060708",
"number" : "0x00",
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000808301e848808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
"lastblockhash" : "a3eba1779c002a8e02f41bab6dea595cbad0e44d5c3fbbdd0ad908190c34c63d",
"postState" : {
"8888f1f195afa192cfee860698584c030f4c9db1" : {
"balance" : "0x4563918244f5fbe4",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x4a723dc6b40b8cee09e81c",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x4a723dc6b40b8a9a000000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x02540be400",
"code" : "0x73a94f5374fce5edbc8e2a8697c15331677e6ebf0bff",
"nonce" : "0x00",
"storage" : {
}
}
}
}
}
Loaded 100 of 961 files, more files were not shown because too many files have changed in this diff. Show more