From 4cd79d8ddd7608d60344b13fe4bda7315429d1d9 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 23 Dec 2014 13:48:44 +0100 Subject: Refactored block & Transaction * Includes new rlp decoder --- core/block_manager.go | 86 ++++---- core/chain_manager.go | 134 +++++++------ core/filter.go | 13 +- core/genesis.go | 65 +++--- core/types/block.go | 490 ++++++++++++++++------------------------------ core/types/block_test.go | 23 +++ core/types/transaction.go | 121 ++++++------ core/vm_env.go | 12 +- 8 files changed, 416 insertions(+), 528 deletions(-) create mode 100644 core/types/block_test.go (limited to 'core') diff --git a/core/block_manager.go b/core/block_manager.go index b60cecc29..c61cf6504 100644 --- a/core/block_manager.go +++ b/core/block_manager.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/pow/ezp" "github.com/ethereum/go-ethereum/state" + "gopkg.in/fatih/set.v0" ) var statelogger = logger.NewLogger("BLOCK") @@ -82,8 +83,8 @@ func NewBlockManager(txpool *TxPool, chainManager *ChainManager, eventMux *event } func (sm *BlockManager) TransitionState(statedb *state.StateDB, parent, block *types.Block) (receipts types.Receipts, err error) { - coinbase := statedb.GetOrNewStateObject(block.Coinbase) - coinbase.SetGasPool(block.CalcGasLimit(parent)) + coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase) + coinbase.SetGasPool(CalcGasLimit(parent, block)) // Process the transactions on to current block receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), false) @@ -156,7 +157,7 @@ done: } block.Reward = cumulativeSum - block.GasUsed = totalUsedGas + block.Header().GasUsed = totalUsedGas return receipts, handled, unhandled, erroneous, err } @@ -166,14 +167,15 @@ func (sm *BlockManager) Process(block *types.Block) (td *big.Int, msgs state.Mes sm.mutex.Lock() defer sm.mutex.Unlock() - if sm.bc.HasBlock(block.Hash()) { - return nil, nil, &KnownBlockError{block.Number, block.Hash()} + header := block.Header() + if sm.bc.HasBlock(header.Hash()) { + return nil, nil, &KnownBlockError{header.Number, header.Hash()} } - if !sm.bc.HasBlock(block.PrevHash) { - return nil, nil, ParentError(block.PrevHash) + if !sm.bc.HasBlock(header.ParentHash) { + return nil, nil, ParentError(header.ParentHash) } - parent := sm.bc.GetBlock(block.PrevHash) + parent := sm.bc.GetBlock(header.ParentHash) return sm.ProcessWithParent(block, parent) } @@ -181,7 +183,7 @@ func (sm *BlockManager) Process(block *types.Block) (td *big.Int, msgs state.Mes func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.Int, messages state.Messages, err error) { sm.lastAttemptedBlock = block - state := parent.State().Copy() + state := state.New(parent.Trie().Copy()) // Defer the Undo on the Trie. If the block processing happened // we don't want to undo but since undo only happens on dirty @@ -199,23 +201,23 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I return } + header := block.Header() + rbloom := types.CreateBloom(receipts) - if bytes.Compare(rbloom, block.LogsBloom) != 0 { + if bytes.Compare(rbloom, header.Bloom) != 0 { err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom) return } txSha := types.DeriveSha(block.Transactions()) - if bytes.Compare(txSha, block.TxSha) != 0 { - err = fmt.Errorf("validating transaction root. received=%x got=%x", block.TxSha, txSha) + if bytes.Compare(txSha, header.TxHash) != 0 { + err = fmt.Errorf("validating transaction root. received=%x got=%x", header.TxHash, txSha) return } receiptSha := types.DeriveSha(receipts) - if bytes.Compare(receiptSha, block.ReceiptSha) != 0 { - //chainlogger.Debugf("validating receipt root. received=%x got=%x", block.ReceiptSha, receiptSha) - fmt.Printf("%x\n", ethutil.Encode(receipts)) - err = fmt.Errorf("validating receipt root. received=%x got=%x", block.ReceiptSha, receiptSha) + if bytes.Compare(receiptSha, header.ReceiptHash) != 0 { + err = fmt.Errorf("validating receipt root. received=%x got=%x", header.ReceiptHash, receiptSha) return } @@ -225,8 +227,8 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I state.Update(ethutil.Big0) - if !block.State().Cmp(state) { - err = fmt.Errorf("invalid merkle root. received=%x got=%x", block.Root(), state.Root()) + if !bytes.Equal(header.Root, state.Root()) { + err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root()) return } @@ -238,7 +240,7 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I messages := state.Manifest().Messages state.Manifest().Reset() - chainlogger.Infof("Processed block #%d (%x...)\n", block.Number, block.Hash()[0:4]) + chainlogger.Infof("Processed block #%d (%x...)\n", header.Number, block.Hash()[0:4]) sm.txpool.RemoveSet(block.Transactions()) @@ -250,14 +252,14 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) { uncleDiff := new(big.Int) - for _, uncle := range block.Uncles { + for _, uncle := range block.Uncles() { uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty) } // TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty td := new(big.Int) td = td.Add(sm.bc.Td(), uncleDiff) - td = td.Add(td, block.Difficulty) + td = td.Add(td, block.Header().Difficulty) // The new TD will only be accepted if the new difficulty is // is greater than the previous. @@ -273,13 +275,13 @@ func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) { // Validation validates easy over difficult (dagger takes longer time = difficult) func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error { expd := CalcDifficulty(block, parent) - if expd.Cmp(block.Difficulty) < 0 { - return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) + if expd.Cmp(block.Header().Difficulty) < 0 { + return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd) } - diff := block.Time - parent.Time + diff := block.Header().Time - parent.Header().Time if diff < 0 { - return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Time, sm.bc.CurrentBlock().Time) + return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Header().Time, sm.bc.CurrentBlock().Header().Time) } /* XXX @@ -291,7 +293,7 @@ func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error { // Verify the nonce of the block. Return an error if it's not valid if !sm.Pow.Verify(block /*block.HashNoNonce(), block.Difficulty, block.Nonce*/) { - return ValidationError("Block's nonce is invalid (= %v)", ethutil.Bytes2Hex(block.Nonce)) + return ValidationError("Block's nonce is invalid (= %v)", ethutil.Bytes2Hex(block.Header().Nonce)) } return nil @@ -300,24 +302,28 @@ func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error { func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent *types.Block) error { reward := new(big.Int).Set(BlockReward) - knownUncles := ethutil.Set(parent.Uncles) - nonces := ethutil.NewSet(block.Nonce) - for _, uncle := range block.Uncles { + knownUncles := set.New() + for _, uncle := range parent.Uncles() { + knownUncles.Add(uncle.Hash()) + } + + nonces := ethutil.NewSet(block.Header().Nonce) + for _, uncle := range block.Uncles() { if nonces.Include(uncle.Nonce) { // Error not unique return UncleError("Uncle not unique") } - uncleParent := sm.bc.GetBlock(uncle.PrevHash) + uncleParent := sm.bc.GetBlock(uncle.ParentHash) if uncleParent == nil { - return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.PrevHash[0:4])) + return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) } - if uncleParent.Number.Cmp(new(big.Int).Sub(parent.Number, big.NewInt(6))) < 0 { + if uncleParent.Header().Number.Cmp(new(big.Int).Sub(parent.Header().Number, big.NewInt(6))) < 0 { return UncleError("Uncle too old") } - if knownUncles.Include(uncle.Hash()) { + if knownUncles.Has(uncle.Hash()) { return UncleError("Uncle in chain") } @@ -333,15 +339,15 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent } // Get the account associated with the coinbase - account := statedb.GetAccount(block.Coinbase) + account := statedb.GetAccount(block.Header().Coinbase) // Reward amount of ether to the coinbase address account.AddAmount(reward) statedb.Manifest().AddMessage(&state.Message{ - To: block.Coinbase, + To: block.Header().Coinbase, Input: nil, Origin: nil, - Block: block.Hash(), Timestamp: block.Time, Coinbase: block.Coinbase, Number: block.Number, + Block: block.Hash(), Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number, Value: new(big.Int).Add(reward, block.Reward), }) @@ -349,15 +355,15 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent } func (sm *BlockManager) GetMessages(block *types.Block) (messages []*state.Message, err error) { - if !sm.bc.HasBlock(block.PrevHash) { - return nil, ParentError(block.PrevHash) + if !sm.bc.HasBlock(block.Header().ParentHash) { + return nil, ParentError(block.Header().ParentHash) } sm.lastAttemptedBlock = block var ( - parent = sm.bc.GetBlock(block.PrevHash) - state = parent.State().Copy() + parent = sm.bc.GetBlock(block.Header().ParentHash) + state = state.New(parent.Trie().Copy()) ) defer state.Reset() diff --git a/core/chain_manager.go b/core/chain_manager.go index e6268c01e..e35c4aa3a 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -1,6 +1,7 @@ package core import ( + "bytes" "fmt" "math/big" "sync" @@ -9,11 +10,13 @@ import ( "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/state" ) var chainlogger = logger.NewLogger("CHAIN") +/* func AddTestNetFunds(block *types.Block) { for _, addr := range []string{ "51ba59315b3a95761d0863b05ccc7a7f54703d99", @@ -31,20 +34,41 @@ func AddTestNetFunds(block *types.Block) { block.State().UpdateStateObject(account) } } +*/ func CalcDifficulty(block, parent *types.Block) *big.Int { diff := new(big.Int) - adjust := new(big.Int).Rsh(parent.Difficulty, 10) - if block.Time >= parent.Time+5 { - diff.Sub(parent.Difficulty, adjust) + bh, ph := block.Header(), parent.Header() + adjust := new(big.Int).Rsh(ph.Difficulty, 10) + if bh.Time >= ph.Time+5 { + diff.Sub(ph.Difficulty, adjust) } else { - diff.Add(parent.Difficulty, adjust) + diff.Add(ph.Difficulty, adjust) } return diff } +func CalcGasLimit(parent, block *types.Block) *big.Int { + if block.Number().Cmp(big.NewInt(0)) == 0 { + return ethutil.BigPow(10, 6) + } + + // ((1024-1) * parent.gasLimit + (gasUsed * 6 / 5)) / 1024 + + previous := new(big.Int).Mul(big.NewInt(1024-1), parent.GasLimit()) + current := new(big.Rat).Mul(new(big.Rat).SetInt(parent.GasUsed()), big.NewRat(6, 5)) + curInt := new(big.Int).Div(current.Num(), current.Denom()) + + result := new(big.Int).Add(previous, curInt) + result.Div(result, big.NewInt(1024)) + + min := big.NewInt(125000) + + return ethutil.BigMax(min, result) +} + type ChainManager struct { //eth EthManager processor types.BlockProcessor @@ -90,7 +114,7 @@ func (self *ChainManager) CurrentBlock() *types.Block { func NewChainManager(mux *event.TypeMux) *ChainManager { bc := &ChainManager{} - bc.genesisBlock = types.NewBlockFromBytes(ethutil.Encode(Genesis)) + bc.genesisBlock = GenesisBlock() bc.eventMux = mux bc.setLastBlock() @@ -112,7 +136,7 @@ func (self *ChainManager) SetProcessor(proc types.BlockProcessor) { } func (self *ChainManager) State() *state.StateDB { - return self.CurrentBlock().State() + return state.New(self.CurrentBlock().Trie()) } func (self *ChainManager) TransState() *state.StateDB { @@ -122,13 +146,11 @@ func (self *ChainManager) TransState() *state.StateDB { func (bc *ChainManager) setLastBlock() { data, _ := ethutil.Config.Db.Get([]byte("LastBlock")) if len(data) != 0 { - // Prep genesis - AddTestNetFunds(bc.genesisBlock) - - block := types.NewBlockFromBytes(data) - bc.currentBlock = block + var block types.Block + rlp.Decode(bytes.NewReader(data), &block) + bc.currentBlock = &block bc.lastBlockHash = block.Hash() - bc.lastBlockNumber = block.Number.Uint64() + bc.lastBlockNumber = block.Header().Number.Uint64() // Set the last know difficulty (might be 0x0 as initial value, Genesis) bc.td = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) @@ -144,27 +166,28 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block { bc.mu.RLock() defer bc.mu.RUnlock() - var root interface{} - hash := ZeroHash256 + var root []byte + parentHash := ZeroHash256 if bc.CurrentBlock != nil { - root = bc.currentBlock.Root() - hash = bc.lastBlockHash + root = bc.currentBlock.Header().Root + parentHash = bc.lastBlockHash } - block := types.CreateBlock( - root, - hash, + block := types.NewBlock( + parentHash, coinbase, + root, ethutil.BigPow(2, 32), nil, "") parent := bc.currentBlock if parent != nil { - block.Difficulty = CalcDifficulty(block, parent) - block.Number = new(big.Int).Add(bc.currentBlock.Number, ethutil.Big1) - block.GasLimit = block.CalcGasLimit(bc.currentBlock) + header := block.Header() + header.Difficulty = CalcDifficulty(block, parent) + header.Number = new(big.Int).Add(parent.Header().Number, ethutil.Big1) + header.GasLimit = CalcGasLimit(parent, block) } @@ -175,9 +198,6 @@ func (bc *ChainManager) Reset() { bc.mu.Lock() defer bc.mu.Unlock() - AddTestNetFunds(bc.genesisBlock) - - bc.genesisBlock.Trie().Sync() // Prepare the genesis block bc.write(bc.genesisBlock) bc.insert(bc.genesisBlock) @@ -193,18 +213,20 @@ func (self *ChainManager) Export() []byte { self.mu.RLock() defer self.mu.RUnlock() - chainlogger.Infof("exporting %v blocks...\n", self.currentBlock.Number) + chainlogger.Infof("exporting %v blocks...\n", self.currentBlock.Header().Number) - blocks := make([]*types.Block, int(self.currentBlock.Number.Int64())+1) - for block := self.currentBlock; block != nil; block = self.GetBlock(block.PrevHash) { - blocks[block.Number.Int64()] = block + blocks := make([]*types.Block, int(self.currentBlock.NumberU64())+1) + for block := self.currentBlock; block != nil; block = self.GetBlock(block.Header().ParentHash) { + blocks[block.NumberU64()] = block } + //fmt.Println(blocks) + return nil return ethutil.Encode(blocks) } func (bc *ChainManager) insert(block *types.Block) { - encodedBlock := block.RlpEncode() + encodedBlock := ethutil.Encode(block) ethutil.Config.Db.Put([]byte("LastBlock"), encodedBlock) bc.currentBlock = block bc.lastBlockHash = block.Hash() @@ -213,7 +235,7 @@ func (bc *ChainManager) insert(block *types.Block) { func (bc *ChainManager) write(block *types.Block) { bc.writeBlockInfo(block) - encodedBlock := block.RlpEncode() + encodedBlock := ethutil.Encode(block) ethutil.Config.Db.Put(block.Hash(), encodedBlock) } @@ -238,11 +260,11 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain for i := uint64(0); i < max; i++ { chain = append(chain, block.Hash()) - if block.Number.Cmp(ethutil.Big0) <= 0 { + if block.Header().Number.Cmp(ethutil.Big0) <= 0 { break } - block = self.GetBlock(block.PrevHash) + block = self.GetBlock(block.Header().ParentHash) } return @@ -253,8 +275,13 @@ func (self *ChainManager) GetBlock(hash []byte) *types.Block { if len(data) == 0 { return nil } + var block types.Block + if err := rlp.Decode(bytes.NewReader(data), &block); err != nil { + fmt.Println(err) + return nil + } - return types.NewBlockFromBytes(data) + return &block } func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { @@ -262,13 +289,13 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { defer self.mu.RUnlock() block := self.currentBlock - for ; block != nil; block = self.GetBlock(block.PrevHash) { - if block.Number.Uint64() == num { + for ; block != nil; block = self.GetBlock(block.Header().ParentHash) { + if block.Header().Number.Uint64() == num { break } } - if block != nil && block.Number.Uint64() == 0 && num != 0 { + if block != nil && block.Header().Number.Uint64() == 0 && num != 0 { return nil } @@ -281,40 +308,28 @@ func (bc *ChainManager) setTotalDifficulty(td *big.Int) { } func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) { - parent := self.GetBlock(block.PrevHash) + parent := self.GetBlock(block.Header().ParentHash) if parent == nil { - return nil, fmt.Errorf("Unable to calculate total diff without known parent %x", block.PrevHash) + return nil, fmt.Errorf("Unable to calculate total diff without known parent %x", block.Header().ParentHash) } - parentTd := parent.BlockInfo().TD + parentTd := parent.Td uncleDiff := new(big.Int) - for _, uncle := range block.Uncles { + for _, uncle := range block.Uncles() { uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty) } td := new(big.Int) td = td.Add(parentTd, uncleDiff) - td = td.Add(td, block.Difficulty) + td = td.Add(td, block.Header().Difficulty) return td, nil } -func (bc *ChainManager) BlockInfo(block *types.Block) types.BlockInfo { - bi := types.BlockInfo{} - data, _ := ethutil.Config.Db.Get(append(block.Hash(), []byte("Info")...)) - bi.RlpDecode(data) - - return bi -} - // Unexported method for writing extra non-essential block info to the db func (bc *ChainManager) writeBlockInfo(block *types.Block) { bc.lastBlockNumber++ - bi := types.BlockInfo{Number: bc.lastBlockNumber, Hash: block.Hash(), Parent: block.PrevHash, TD: bc.td} - - // For now we use the block hash with the words "info" appended as key - ethutil.Config.Db.Put(append(block.Hash(), []byte("Info")...), bi.RlpEncode()) } func (bc *ChainManager) Stop() { @@ -331,7 +346,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { continue } - chainlogger.Infof("block #%v process failed (%x)\n", block.Number, block.Hash()[:4]) + h := block.Header() + chainlogger.Infof("block #%v process failed (%x)\n", h.Number, h.Hash()[:4]) chainlogger.Infoln(block) chainlogger.Infoln(err) return err @@ -339,16 +355,16 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { self.mu.Lock() { - self.write(block) + cblock := self.currentBlock if td.Cmp(self.td) > 0 { - if block.Number.Cmp(new(big.Int).Add(self.currentBlock.Number, ethutil.Big1)) < 0 { - chainlogger.Infof("Split detected. New head #%v (%x), was #%v (%x)\n", block.Number, block.Hash()[:4], self.currentBlock.Number, self.currentBlock.Hash()[:4]) + if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 { + chainlogger.Infof("Split detected. New head #%v (%x), was #%v (%x)\n", block.Header().Number, block.Hash()[:4], cblock.Header().Number, cblock.Hash()[:4]) } self.setTotalDifficulty(td) self.insert(block) - self.transState = self.currentBlock.State().Copy() + self.transState = state.New(cblock.Trie().Copy()) } } diff --git a/core/filter.go b/core/filter.go index fb992782d..7c34748df 100644 --- a/core/filter.go +++ b/core/filter.go @@ -76,13 +76,14 @@ func (self *Filter) SetSkip(skip int) { // Run filters messages with the current parameters set func (self *Filter) Find() []*state.Message { + earliestBlock := self.eth.ChainManager().CurrentBlock() var earliestBlockNo uint64 = uint64(self.earliest) if self.earliest == -1 { - earliestBlockNo = self.eth.ChainManager().CurrentBlock().Number.Uint64() + earliestBlockNo = earliestBlock.NumberU64() } var latestBlockNo uint64 = uint64(self.latest) if self.latest == -1 { - latestBlockNo = self.eth.ChainManager().CurrentBlock().Number.Uint64() + latestBlockNo = earliestBlock.NumberU64() } var ( @@ -93,7 +94,7 @@ func (self *Filter) Find() []*state.Message { for i := 0; !quit && block != nil; i++ { // Quit on latest switch { - case block.Number.Uint64() == earliestBlockNo, block.Number.Uint64() == 0: + case block.NumberU64() == earliestBlockNo, block.NumberU64() == 0: quit = true case self.max <= len(messages): break @@ -113,7 +114,7 @@ func (self *Filter) Find() []*state.Message { messages = append(messages, self.FilterMessages(msgs)...) } - block = self.eth.ChainManager().GetBlock(block.PrevHash) + block = self.eth.ChainManager().GetBlock(block.ParentHash()) } skip := int(math.Min(float64(len(messages)), float64(self.skip))) @@ -176,7 +177,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool { var fromIncluded, toIncluded bool if len(self.from) > 0 { for _, from := range self.from { - if types.BloomLookup(block.LogsBloom, from) || bytes.Equal(block.Coinbase, from) { + if types.BloomLookup(block.Bloom(), from) || bytes.Equal(block.Coinbase(), from) { fromIncluded = true break } @@ -187,7 +188,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool { if len(self.to) > 0 { for _, to := range self.to { - if types.BloomLookup(block.LogsBloom, ethutil.U256(new(big.Int).Add(ethutil.Big1, ethutil.BigD(to))).Bytes()) || bytes.Equal(block.Coinbase, to) { + if types.BloomLookup(block.Bloom(), ethutil.U256(new(big.Int).Add(ethutil.Big1, ethutil.BigD(to))).Bytes()) || bytes.Equal(block.Coinbase(), to) { toIncluded = true break } diff --git a/core/genesis.go b/core/genesis.go index 707154759..51afa314e 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -3,8 +3,10 @@ package core import ( "math/big" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/state" ) /* @@ -17,36 +19,35 @@ var ZeroHash512 = make([]byte, 64) var EmptyShaList = crypto.Sha3(ethutil.Encode([]interface{}{})) var EmptyListRoot = crypto.Sha3(ethutil.Encode("")) -var GenesisHeader = []interface{}{ - // Previous hash (none) - ZeroHash256, - // Empty uncles - EmptyShaList, - // Coinbase - ZeroHash160, - // Root state - EmptyShaList, - // tx root - EmptyListRoot, - // receipt root - EmptyListRoot, - // bloom - ZeroHash512, - // Difficulty - //ethutil.BigPow(2, 22), - big.NewInt(131072), - // Number - ethutil.Big0, - // Block upper gas bound - big.NewInt(1000000), - // Block gas used - ethutil.Big0, - // Time - ethutil.Big0, - // Extra - nil, - // Nonce - crypto.Sha3(big.NewInt(42).Bytes()), -} +func GenesisBlock() *types.Block { + genesis := types.NewBlock(ZeroHash256, ZeroHash160, EmptyListRoot, big.NewInt(131072), crypto.Sha3(big.NewInt(42).Bytes()), "") + genesis.Header().Number = ethutil.Big0 + genesis.Header().GasLimit = big.NewInt(1000000) + genesis.Header().GasUsed = ethutil.Big0 + genesis.Header().Time = 0 + + genesis.SetUncles([]*types.Header{}) + genesis.SetTransactions(types.Transactions{}) + genesis.SetReceipts(types.Receipts{}) -var Genesis = []interface{}{GenesisHeader, []interface{}{}, []interface{}{}} + statedb := state.New(genesis.Trie()) + for _, addr := range []string{ + "51ba59315b3a95761d0863b05ccc7a7f54703d99", + "e4157b34ea9615cfbde6b4fda419828124b70c78", + "b9c015918bdaba24b4ff057a92a3873d6eb201be", + "6c386a4b26f73c802f34673f7248bb118f97424a", + "cd2a3d9f938e13cd947ec05abc7fe734df8dd826", + "2ef47100e0787b915105fd5e3f4ff6752079d5cb", + "e6716f9544a56c530d868e4bfbacb172315bdead", + "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", + } { + codedAddr := ethutil.Hex2Bytes(addr) + account := statedb.GetAccount(codedAddr) + account.SetBalance(ethutil.Big("1606938044258990275541962092341162602522202993782792835301376")) //ethutil.BigPow(2, 200) + statedb.UpdateStateObject(account) + } + statedb.Sync() + genesis.Header().Root = statedb.Root() + + return genesis +} diff --git a/core/types/block.go b/core/types/block.go index 2d889f35f..b0fcbdd9b 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -9,408 +9,252 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/trie" ) -type BlockInfo struct { - Number uint64 - Hash []byte - Parent []byte - TD *big.Int -} - -func (bi *BlockInfo) RlpDecode(data []byte) { - decoder := ethutil.NewValueFromBytes(data) - - bi.Number = decoder.Get(0).Uint() - bi.Hash = decoder.Get(1).Bytes() - bi.Parent = decoder.Get(2).Bytes() - bi.TD = decoder.Get(3).BigInt() -} - -func (bi *BlockInfo) RlpEncode() []byte { - return ethutil.Encode([]interface{}{bi.Number, bi.Hash, bi.Parent, bi.TD}) -} - -type Blocks []*Block - -func (self Blocks) AsSet() ethutil.UniqueSet { - set := make(ethutil.UniqueSet) - for _, block := range self { - set.Insert(block.Hash()) - } - - return set -} - -type BlockBy func(b1, b2 *Block) bool - -func (self BlockBy) Sort(blocks Blocks) { - bs := blockSorter{ - blocks: blocks, - by: self, - } - sort.Sort(bs) -} - -type blockSorter struct { - blocks Blocks - by func(b1, b2 *Block) bool -} - -func (self blockSorter) Len() int { return len(self.blocks) } -func (self blockSorter) Swap(i, j int) { - self.blocks[i], self.blocks[j] = self.blocks[j], self.blocks[i] -} -func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) } - -func Number(b1, b2 *Block) bool { return b1.Number.Cmp(b2.Number) < 0 } - -type Block struct { +type Header struct { // Hash to the previous block - PrevHash ethutil.Bytes + ParentHash ethutil.Bytes // Uncles of this block - Uncles Blocks - UncleSha []byte + UncleHash []byte // The coin base address Coinbase []byte // Block Trie state - //state *ethutil.Trie - state *state.StateDB + Root []byte + // Tx sha + TxHash []byte + // Receipt sha + ReceiptHash []byte + // Bloom + Bloom []byte // Difficulty for the current block Difficulty *big.Int - // Creation time - Time int64 // The block number Number *big.Int // Gas limit GasLimit *big.Int // Gas used GasUsed *big.Int + // Creation time + Time uint64 // Extra data Extra string // Block Nonce for verification Nonce ethutil.Bytes - // List of transactions and/or contracts - transactions Transactions - receipts Receipts - TxSha, ReceiptSha []byte - LogsBloom []byte - - Reward *big.Int } -func NewBlockFromBytes(raw []byte) *Block { - block := &Block{} - block.RlpDecode(raw) +func (self *Header) rlpData(withNonce bool) []interface{} { + fields := []interface{}{self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra} + if withNonce { + fields = append(fields, self.Nonce) + } - return block + return fields +} + +func (self *Header) RlpData() interface{} { + return self.rlpData(true) } -// New block takes a raw encoded string -func NewBlockFromRlpValue(rlpValue *ethutil.Value) *Block { - block := &Block{} - block.RlpValueDecode(rlpValue) +func (self *Header) Hash() []byte { + return crypto.Sha3(ethutil.Encode(self.rlpData(true))) +} - return block +func (self *Header) HashNoNonce() []byte { + return crypto.Sha3(ethutil.Encode(self.rlpData(false))) } -func CreateBlock(root interface{}, - prevHash []byte, - base []byte, - Difficulty *big.Int, - Nonce []byte, - extra string) *Block { - - block := &Block{ - PrevHash: prevHash, - Coinbase: base, - Difficulty: Difficulty, - Nonce: Nonce, - Time: time.Now().Unix(), +type Block struct { + header *Header + uncles []*Header + transactions Transactions + Td *big.Int + + receipts Receipts + Reward *big.Int +} + +func NewBlock(parentHash []byte, coinbase []byte, root []byte, difficulty *big.Int, nonce []byte, extra string) *Block { + header := &Header{ + Root: root, + ParentHash: parentHash, + Coinbase: coinbase, + Difficulty: difficulty, + Nonce: nonce, + Time: uint64(time.Now().Unix()), Extra: extra, - UncleSha: nil, GasUsed: new(big.Int), GasLimit: new(big.Int), } - block.SetUncles([]*Block{}) - block.state = state.New(trie.New(ethutil.Config.Db, root)) + block := &Block{header: header, Reward: new(big.Int)} return block } -// Returns a hash of the block -func (block *Block) Hash() ethutil.Bytes { - return crypto.Sha3(ethutil.NewValue(block.header()).Encode()) - //return crypto.Sha3(block.Value().Encode()) -} - -func (block *Block) HashNoNonce() []byte { - return crypto.Sha3(ethutil.Encode(block.miningHeader())) -} - -func (block *Block) State() *state.StateDB { - return block.state -} - -func (block *Block) Transactions() Transactions { - return block.transactions +func NewBlockWithHeader(header *Header) *Block { + return &Block{header: header} } -func (block *Block) CalcGasLimit(parent *Block) *big.Int { - if block.Number.Cmp(big.NewInt(0)) == 0 { - return ethutil.BigPow(10, 6) +func (self *Block) DecodeRLP(s *rlp.Stream) error { + if _, err := s.List(); err != nil { + return err } - // ((1024-1) * parent.gasLimit + (gasUsed * 6 / 5)) / 1024 - - previous := new(big.Int).Mul(big.NewInt(1024-1), parent.GasLimit) - current := new(big.Rat).Mul(new(big.Rat).SetInt(parent.GasUsed), big.NewRat(6, 5)) - curInt := new(big.Int).Div(current.Num(), current.Denom()) - - result := new(big.Int).Add(previous, curInt) - result.Div(result, big.NewInt(1024)) - - min := big.NewInt(125000) - - return ethutil.BigMax(min, result) -} - -func (block *Block) BlockInfo() BlockInfo { - bi := BlockInfo{} - data, _ := ethutil.Config.Db.Get(append(block.Hash(), []byte("Info")...)) - bi.RlpDecode(data) - - return bi -} - -func (self *Block) GetTransaction(hash []byte) *Transaction { - for _, tx := range self.transactions { - if bytes.Compare(tx.Hash(), hash) == 0 { - return tx - } + var header Header + if err := s.Decode(&header); err != nil { + return err } - return nil -} - -// Sync the block's state and contract respectively -func (block *Block) Sync() { - block.state.Sync() -} - -func (block *Block) Undo() { - // Sync the block state itself - block.state.Reset() -} - -/////// Block Encoding -func (block *Block) rlpReceipts() interface{} { - // Marshal the transactions of this block - encR := make([]interface{}, len(block.receipts)) - for i, r := range block.receipts { - // Cast it to a string (safe) - encR[i] = r.RlpData() + var transactions []*Transaction + if err := s.Decode(&transactions); err != nil { + return err } - return encR -} + var uncleHeaders []*Header + if err := s.Decode(&uncleHeaders); err != nil { + return err + } -func (block *Block) rlpUncles() interface{} { - // Marshal the transactions of this block - uncles := make([]interface{}, len(block.Uncles)) - for i, uncle := range block.Uncles { - // Cast it to a string (safe) - uncles[i] = uncle.header() + var tdBytes []byte + if err := s.Decode(&tdBytes); err != nil { + // If this block comes from the network that's fine. If loaded from disk it should be there + // Blocks don't store their Td when propagated over the network + } else { + self.Td = ethutil.BigD(tdBytes) } - return uncles -} + if err := s.ListEnd(); err != nil { + return err + } -func (block *Block) SetUncles(uncles []*Block) { - block.Uncles = uncles - block.UncleSha = crypto.Sha3(ethutil.Encode(block.rlpUncles())) -} + self.header = &header + self.uncles = uncleHeaders + self.transactions = transactions -func (self *Block) SetReceipts(receipts Receipts) { - self.receipts = receipts - self.ReceiptSha = DeriveSha(receipts) - self.LogsBloom = CreateBloom(receipts) + return nil } -func (self *Block) SetTransactions(txs Transactions) { - self.transactions = txs - self.TxSha = DeriveSha(txs) +func (self *Block) Header() *Header { + return self.header } -func (block *Block) Value() *ethutil.Value { - return ethutil.NewValue([]interface{}{block.header(), block.transactions, block.rlpUncles()}) +func (self *Block) Uncles() []*Header { + return self.uncles } -func (block *Block) RlpEncode() []byte { - // Encode a slice interface which contains the header and the list of - // transactions. - return block.Value().Encode() +func (self *Block) SetUncles(uncleHeaders []*Header) { + self.uncles = uncleHeaders + self.header.UncleHash = crypto.Sha3(ethutil.Encode(uncleHeaders)) } -func (block *Block) RlpDecode(data []byte) { - rlpValue := ethutil.NewValueFromBytes(data) - block.RlpValueDecode(rlpValue) +func (self *Block) Transactions() Transactions { + return self.transactions } -func (block *Block) RlpValueDecode(decoder *ethutil.Value) { - block.setHeader(decoder.Get(0)) - - // Tx list might be empty if this is an uncle. Uncles only have their - // header set. - if decoder.Get(1).IsNil() == false { // Yes explicitness - //receipts := decoder.Get(1) - //block.receipts = make([]*Receipt, receipts.Len()) - txs := decoder.Get(1) - block.transactions = make(Transactions, txs.Len()) - for i := 0; i < txs.Len(); i++ { - block.transactions[i] = NewTransactionFromValue(txs.Get(i)) - //receipt := NewRecieptFromValue(receipts.Get(i)) - //block.transactions[i] = receipt.Tx - //block.receipts[i] = receipt - } - - } - - if decoder.Get(2).IsNil() == false { // Yes explicitness - uncles := decoder.Get(2) - block.Uncles = make([]*Block, uncles.Len()) - for i := 0; i < uncles.Len(); i++ { - block.Uncles[i] = NewUncleBlockFromValue(uncles.Get(i)) +func (self *Block) Transaction(hash []byte) *Transaction { + for _, transaction := range self.transactions { + if bytes.Equal(hash, transaction.Hash()) { + return transaction } } - + return nil } -func (self *Block) setHeader(header *ethutil.Value) { - self.PrevHash = header.Get(0).Bytes() - self.UncleSha = header.Get(1).Bytes() - self.Coinbase = header.Get(2).Bytes() - self.state = state.New(trie.New(ethutil.Config.Db, header.Get(3).Val)) - self.TxSha = header.Get(4).Bytes() - self.ReceiptSha = header.Get(5).Bytes() - self.LogsBloom = header.Get(6).Bytes() - self.Difficulty = header.Get(7).BigInt() - self.Number = header.Get(8).BigInt() - self.GasLimit = header.Get(9).BigInt() - self.GasUsed = header.Get(10).BigInt() - self.Time = int64(header.Get(11).BigInt().Uint64()) - self.Extra = header.Get(12).Str() - self.Nonce = header.Get(13).Bytes() +func (self *Block) SetTransactions(transactions Transactions) { + self.transactions = transactions + self.header.TxHash = DeriveSha(transactions) } -func NewUncleBlockFromValue(header *ethutil.Value) *Block { - block := &Block{} - block.setHeader(header) - - return block +func (self *Block) Receipts() Receipts { + return self.receipts } -func (block *Block) Trie() *trie.Trie { - return block.state.Trie +func (self *Block) SetReceipts(receipts Receipts) { + self.receipts = receipts + self.header.ReceiptHash = DeriveSha(receipts) + self.header.Bloom = CreateBloom(receipts) } -func (block *Block) Root() interface{} { - return block.state.Root() +func (self *Block) RlpData() interface{} { + return []interface{}{self.header, self.transactions, self.uncles} +} + +func (self *Block) RlpDataForStorage() interface{} { + return []interface{}{self.header, self.transactions, self.uncles, self.Td /* TODO receipts */} +} + +// Header accessors (add as you need them) +func (self *Block) Number() *big.Int { return self.header.Number } +func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() } +func (self *Block) ParentHash() []byte { return self.header.ParentHash } +func (self *Block) Bloom() []byte { return self.header.Bloom } +func (self *Block) Coinbase() []byte { return self.header.Coinbase } +func (self *Block) Time() int64 { return int64(self.header.Time) } +func (self *Block) GasLimit() *big.Int { return self.header.GasLimit } +func (self *Block) GasUsed() *big.Int { return self.header.GasUsed } +func (self *Block) Hash() []byte { return self.header.Hash() } +func (self *Block) Trie() *trie.Trie { return trie.New(ethutil.Config.Db, self.header.Root) } +func (self *Block) State() *state.StateDB { return state.New(self.Trie()) } +func (self *Block) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) } + +// Implement block.Pow +func (self *Block) Difficulty() *big.Int { return self.header.Difficulty } +func (self *Block) N() []byte { return self.header.Nonce } +func (self *Block) HashNoNonce() []byte { + return crypto.Sha3(ethutil.Encode(self.header.rlpData(false))) +} + +func (self *Block) String() string { + return fmt.Sprintf(`BLOCK(%x): Size: %v { +%v +%v +%v +} +`, self.header.Hash(), self.Size(), self.header, self.uncles, self.transactions) +} + +func (self *Header) String() string { + return fmt.Sprintf(`ParentHash: %x +UncleHash: %x +Coinbase: %x +Root: %x +TxSha %x +ReceiptSha: %x +Bloom: %x +Difficulty: %v +Number: %v +GasLimit: %v +GasUsed: %v +Time: %v +Extra: %v +Nonce: %x +`, self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra, self.Nonce) } -func (block *Block) Diff() *big.Int { - return block.Difficulty -} +type Blocks []*Block -func (self *Block) Receipts() []*Receipt { - return self.receipts -} +type BlockBy func(b1, b2 *Block) bool -func (block *Block) miningHeader() []interface{} { - return []interface{}{ - // Sha of the previous block - block.PrevHash, - // Sha of uncles - block.UncleSha, - // Coinbase address - block.Coinbase, - // root state - block.Root(), - // tx root - block.TxSha, - // Sha of tx - block.ReceiptSha, - // Bloom - block.LogsBloom, - // Current block Difficulty - block.Difficulty, - // The block number - block.Number, - // Block upper gas bound - block.GasLimit, - // Block gas used - block.GasUsed, - // Time the block was found? - block.Time, - // Extra data - block.Extra, +func (self BlockBy) Sort(blocks Blocks) { + bs := blockSorter{ + blocks: blocks, + by: self, } + sort.Sort(bs) } -func (block *Block) header() []interface{} { - return append(block.miningHeader(), block.Nonce) -} - -func (block *Block) String() string { - return fmt.Sprintf(` - BLOCK(%x): Size: %v - PrevHash: %x - UncleSha: %x - Coinbase: %x - Root: %x - TxSha %x - ReceiptSha: %x - Bloom: %x - Difficulty: %v - Number: %v - MaxLimit: %v - GasUsed: %v - Time: %v - Extra: %v - Nonce: %x - NumTx: %v -`, - block.Hash(), - block.Size(), - block.PrevHash, - block.UncleSha, - block.Coinbase, - block.Root(), - block.TxSha, - block.ReceiptSha, - block.LogsBloom, - block.Difficulty, - block.Number, - block.GasLimit, - block.GasUsed, - block.Time, - block.Extra, - block.Nonce, - len(block.transactions), - ) -} - -func (self *Block) Size() ethutil.StorageSize { - return ethutil.StorageSize(len(self.RlpEncode())) +type blockSorter struct { + blocks Blocks + by func(b1, b2 *Block) bool } -// Implement RlpEncodable -func (self *Block) RlpData() interface{} { - return []interface{}{self.header(), self.transactions, self.rlpUncles()} +func (self blockSorter) Len() int { return len(self.blocks) } +func (self blockSorter) Swap(i, j int) { + self.blocks[i], self.blocks[j] = self.blocks[j], self.blocks[i] } +func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) } -// Implement pow.Block -func (self *Block) N() []byte { return self.Nonce } +func Number(b1, b2 *Block) bool { return b1.Header().Number.Cmp(b2.Header().Number) < 0 } diff --git a/core/types/block_test.go b/core/types/block_test.go new file mode 100644 index 000000000..c85708975 --- /dev/null +++ b/core/types/block_test.go @@ -0,0 +1,23 @@ +package types + +import ( + "bytes" + "testing" + + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/rlp" +) + +func init() { + ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "") + ethutil.Config.Db, _ = ethdb.NewMemDatabase() +} + +func TestNewBlock(t *testing.T) { + block := GenesisBlock() + data := ethutil.Encode(block) + + var genesis Block + err := rlp.Decode(bytes.NewReader(data), &genesis) +} diff --git a/core/types/transaction.go b/core/types/transaction.go index 3a87f7844..c2f7df7a7 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -1,11 +1,13 @@ package types import ( + "bytes" "fmt" "math/big" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/rlp" "github.com/obscuren/secp256k1-go" ) @@ -14,22 +16,22 @@ func IsContractAddr(addr []byte) bool { } type Transaction struct { - nonce uint64 - recipient []byte - value *big.Int - gas *big.Int - gasPrice *big.Int - data []byte - v byte - r, s []byte + AccountNonce uint64 + Recipient []byte + Amount *big.Int + GasAmount *big.Int + Price *big.Int + Payload []byte + V uint64 + R, S []byte } -func NewContractCreationTx(value, gas, gasPrice *big.Int, script []byte) *Transaction { - return &Transaction{recipient: nil, value: value, gas: gas, gasPrice: gasPrice, data: script} +func NewContractCreationTx(Amount, gasAmount, price *big.Int, data []byte) *Transaction { + return NewTransactionMessage(nil, Amount, gasAmount, price, data) } -func NewTransactionMessage(to []byte, value, gas, gasPrice *big.Int, data []byte) *Transaction { - return &Transaction{recipient: to, value: value, gasPrice: gasPrice, gas: gas, data: data} +func NewTransactionMessage(to []byte, Amount, gasAmount, price *big.Int, data []byte) *Transaction { + return &Transaction{Recipient: to, Amount: Amount, Price: price, GasAmount: gasAmount, Payload: data} } func NewTransactionFromBytes(data []byte) *Transaction { @@ -39,7 +41,7 @@ func NewTransactionFromBytes(data []byte) *Transaction { return tx } -func NewTransactionFromValue(val *ethutil.Value) *Transaction { +func NewTransactionFromAmount(val *ethutil.Value) *Transaction { tx := &Transaction{} tx.RlpValueDecode(val) @@ -47,33 +49,33 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction { } func (tx *Transaction) Hash() []byte { - data := []interface{}{tx.nonce, tx.gasPrice, tx.gas, tx.recipient, tx.value, tx.data} + data := []interface{}{tx.AccountNonce, tx.Price, tx.GasAmount, tx.Recipient, tx.Amount, tx.Payload} - return crypto.Sha3(ethutil.NewValue(data).Encode()) + return crypto.Sha3(ethutil.Encode(data)) } func (self *Transaction) Data() []byte { - return self.data + return self.Payload } func (self *Transaction) Gas() *big.Int { - return self.gas + return self.GasAmount } func (self *Transaction) GasPrice() *big.Int { - return self.gasPrice + return self.Price } func (self *Transaction) Value() *big.Int { - return self.value + return self.Amount } func (self *Transaction) Nonce() uint64 { - return self.nonce + return self.AccountNonce } -func (self *Transaction) SetNonce(nonce uint64) { - self.nonce = nonce +func (self *Transaction) SetNonce(AccountNonce uint64) { + self.AccountNonce = AccountNonce } func (self *Transaction) From() []byte { @@ -81,13 +83,13 @@ func (self *Transaction) From() []byte { } func (self *Transaction) To() []byte { - return self.recipient + return self.Recipient } func (tx *Transaction) Curve() (v byte, r []byte, s []byte) { - v = tx.v - r = ethutil.LeftPadBytes(tx.r, 32) - s = ethutil.LeftPadBytes(tx.s, 32) + v = byte(tx.V) + r = ethutil.LeftPadBytes(tx.R, 32) + s = ethutil.LeftPadBytes(tx.S, 32) return } @@ -130,42 +132,37 @@ func (tx *Transaction) Sign(privk []byte) error { sig := tx.Signature(privk) - tx.r = sig[:32] - tx.s = sig[32:64] - tx.v = sig[64] + 27 + tx.R = sig[:32] + tx.S = sig[32:64] + tx.V = uint64(sig[64] + 27) return nil } func (tx *Transaction) RlpData() interface{} { - data := []interface{}{tx.nonce, tx.gasPrice, tx.gas, tx.recipient, tx.value, tx.data} + data := []interface{}{tx.AccountNonce, tx.Price, tx.GasAmount, tx.Recipient, tx.Amount, tx.Payload} - return append(data, tx.v, new(big.Int).SetBytes(tx.r).Bytes(), new(big.Int).SetBytes(tx.s).Bytes()) -} - -func (tx *Transaction) RlpValue() *ethutil.Value { - return ethutil.NewValue(tx.RlpData()) + return append(data, tx.V, new(big.Int).SetBytes(tx.R).Bytes(), new(big.Int).SetBytes(tx.S).Bytes()) } func (tx *Transaction) RlpEncode() []byte { - return tx.RlpValue().Encode() + return ethutil.Encode(tx) } func (tx *Transaction) RlpDecode(data []byte) { - tx.RlpValueDecode(ethutil.NewValueFromBytes(data)) + rlp.Decode(bytes.NewReader(data), tx) } func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) { - tx.nonce = decoder.Get(0).Uint() - tx.gasPrice = decoder.Get(1).BigInt() - tx.gas = decoder.Get(2).BigInt() - tx.recipient = decoder.Get(3).Bytes() - tx.value = decoder.Get(4).BigInt() - tx.data = decoder.Get(5).Bytes() - tx.v = byte(decoder.Get(6).Uint()) - - tx.r = decoder.Get(7).Bytes() - tx.s = decoder.Get(8).Bytes() + tx.AccountNonce = decoder.Get(0).Uint() + tx.Price = decoder.Get(1).BigInt() + tx.GasAmount = decoder.Get(2).BigInt() + tx.Recipient = decoder.Get(3).Bytes() + tx.Amount = decoder.Get(4).BigInt() + tx.Payload = decoder.Get(5).Bytes() + tx.V = decoder.Get(6).Uint() + tx.R = decoder.Get(7).Bytes() + tx.S = decoder.Get(8).Bytes() } func (tx *Transaction) String() string { @@ -174,10 +171,10 @@ func (tx *Transaction) String() string { Contract: %v From: %x To: %x - Nonce: %v - GasPrice: %v - Gas: %v - Value: %v + AccountNonce: %v + GasAmountPrice: %v + GasAmount: %v + Amount: %v Data: 0x%x V: 0x%x R: 0x%x @@ -185,17 +182,17 @@ func (tx *Transaction) String() string { Hex: %x `, tx.Hash(), - len(tx.recipient) == 0, + len(tx.Recipient) == 0, tx.From(), - tx.recipient, - tx.nonce, - tx.gasPrice, - tx.gas, - tx.value, - tx.data, - tx.v, - tx.r, - tx.s, + tx.Recipient, + tx.AccountNonce, + tx.Price, + tx.GasAmount, + tx.Amount, + tx.Payload, + tx.V, + tx.R, + tx.S, ethutil.Encode(tx), ) } @@ -220,5 +217,5 @@ func (s Transactions) GetRlp(i int) []byte { return ethutil.Rlp(s[i]) } type TxByNonce struct{ Transactions } func (s TxByNonce) Less(i, j int) bool { - return s.Transactions[i].nonce < s.Transactions[j].nonce + return s.Transactions[i].AccountNonce < s.Transactions[j].AccountNonce } diff --git a/core/vm_env.go b/core/vm_env.go index ad63ecf9c..209115eab 100644 --- a/core/vm_env.go +++ b/core/vm_env.go @@ -24,15 +24,15 @@ func NewEnv(state *state.StateDB, msg Message, block *types.Block) *VMEnv { } func (self *VMEnv) Origin() []byte { return self.msg.From() } -func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number } -func (self *VMEnv) PrevHash() []byte { return self.block.PrevHash } -func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase } -func (self *VMEnv) Time() int64 { return self.block.Time } -func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty } +func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() } +func (self *VMEnv) PrevHash() []byte { return self.block.ParentHash() } +func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() } +func (self *VMEnv) Time() int64 { return self.block.Time() } +func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() } func (self *VMEnv) BlockHash() []byte { return self.block.Hash() } +func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() } func (self *VMEnv) Value() *big.Int { return self.msg.Value() } func (self *VMEnv) State() *state.StateDB { return self.state } -func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit } func (self *VMEnv) Depth() int { return self.depth } func (self *VMEnv) SetDepth(i int) { self.depth = i } func (self *VMEnv) AddLog(log state.Log) { -- cgit