From a1b6a9ac29d0aa8d29a2c0535bafdb5fe4d4830b Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 18 Nov 2014 16:58:22 +0100 Subject: Begin of moving objects to types package * Block(s) * Transaction(s) --- block_pool.go | 13 +- chain/block.go | 419 --------------------------------------- chain/block_manager.go | 38 ++-- chain/bloom9.go | 56 ------ chain/bloom9_test.go | 29 --- chain/chain_manager.go | 68 ++++--- chain/dagger.go | 5 +- chain/derive_sha.go | 20 -- chain/events.go | 8 +- chain/filter.go | 9 +- chain/receipt.go | 60 ------ chain/state_transition.go | 11 +- chain/transaction.go | 224 --------------------- chain/transaction_pool.go | 41 ++-- chain/transaction_test.go | 1 - chain/types/block.go | 419 +++++++++++++++++++++++++++++++++++++++ chain/types/bloom9.go | 56 ++++++ chain/types/bloom9_test.go | 30 +++ chain/types/common.go | 10 + chain/types/derive_sha.go | 20 ++ chain/types/receipt.go | 68 +++++++ chain/types/transaction.go | 224 +++++++++++++++++++++ chain/types/transaction_test.go | 1 + chain/vm_env.go | 7 +- cmd/mist/bindings.go | 5 +- cmd/mist/ext_app.go | 3 +- cmd/mist/gui.go | 7 +- cmd/mist/html_container.go | 5 +- cmd/mist/qml_container.go | 5 +- cmd/mist/ui_lib.go | 5 +- cmd/utils/vm_env.go | 7 +- ethereum.go | 3 +- javascript/javascript_runtime.go | 3 +- miner/miner.go | 15 +- peer.go | 11 +- xeth/hexface.go | 9 +- xeth/js_types.go | 9 +- xeth/pipe.go | 11 +- xeth/vm_env.go | 7 +- 39 files changed, 990 insertions(+), 952 deletions(-) delete mode 100644 chain/block.go delete mode 100644 chain/bloom9.go delete mode 100644 chain/bloom9_test.go delete mode 100644 chain/derive_sha.go delete mode 100644 chain/receipt.go delete mode 100644 chain/transaction.go delete mode 100644 chain/transaction_test.go create mode 100644 chain/types/block.go create mode 100644 chain/types/bloom9.go create mode 100644 chain/types/bloom9_test.go create mode 100644 chain/types/common.go create mode 100644 chain/types/derive_sha.go create mode 100644 chain/types/receipt.go create mode 100644 chain/types/transaction.go create mode 100644 chain/types/transaction_test.go diff --git a/block_pool.go b/block_pool.go index f9bd3b28e..dcddca58e 100644 --- a/block_pool.go +++ b/block_pool.go @@ -10,6 +10,7 @@ import ( "time" "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/wire" @@ -20,7 +21,7 @@ var poollogger = logger.NewLogger("BPOOL") type block struct { from *Peer peer *Peer - block *chain.Block + block *types.Block reqAt time.Time requested int } @@ -73,7 +74,7 @@ func (self *BlockPool) HasCommonHash(hash []byte) bool { return self.eth.ChainManager().GetBlock(hash) != nil } -func (self *BlockPool) Blocks() (blocks chain.Blocks) { +func (self *BlockPool) Blocks() (blocks types.Blocks) { for _, item := range self.pool { if item.block != nil { blocks = append(blocks, item.block) @@ -123,15 +124,15 @@ func (self *BlockPool) AddHash(hash []byte, peer *Peer) { } } -func (self *BlockPool) Add(b *chain.Block, peer *Peer) { +func (self *BlockPool) Add(b *types.Block, peer *Peer) { self.addBlock(b, peer, false) } -func (self *BlockPool) AddNew(b *chain.Block, peer *Peer) { +func (self *BlockPool) AddNew(b *types.Block, peer *Peer) { self.addBlock(b, peer, true) } -func (self *BlockPool) addBlock(b *chain.Block, peer *Peer, newBlock bool) { +func (self *BlockPool) addBlock(b *types.Block, peer *Peer, newBlock bool) { self.mut.Lock() defer self.mut.Unlock() @@ -283,7 +284,7 @@ out: break out case <-procTimer.C: blocks := self.Blocks() - chain.BlockBy(chain.Number).Sort(blocks) + types.BlockBy(types.Number).Sort(blocks) // Find common block for i, block := range blocks { diff --git a/chain/block.go b/chain/block.go deleted file mode 100644 index a4ab560dc..000000000 --- a/chain/block.go +++ /dev/null @@ -1,419 +0,0 @@ -package chain - -import ( - "bytes" - "fmt" - "math/big" - "sort" - "time" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethutil" - "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 { - // Hash to the previous block - PrevHash ethutil.Bytes - // Uncles of this block - Uncles Blocks - UncleSha []byte - // The coin base address - Coinbase []byte - // Block Trie state - //state *ethutil.Trie - state *state.State - // Difficulty for the current block - Difficulty *big.Int - // Creation time - Time int64 - // The block number - Number *big.Int - // Minimum Gas Price - MinGasPrice *big.Int - // Gas limit - GasLimit *big.Int - // Gas used - GasUsed *big.Int - // 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 -} - -func NewBlockFromBytes(raw []byte) *Block { - block := &Block{} - block.RlpDecode(raw) - - return block -} - -// New block takes a raw encoded string -func NewBlockFromRlpValue(rlpValue *ethutil.Value) *Block { - block := &Block{} - block.RlpValueDecode(rlpValue) - - return block -} - -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(), - Extra: extra, - UncleSha: nil, - GasUsed: new(big.Int), - MinGasPrice: new(big.Int), - GasLimit: new(big.Int), - } - block.SetUncles([]*Block{}) - - block.state = state.New(trie.New(ethutil.Config.Db, root)) - - 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.State { - return block.state -} - -func (block *Block) Transactions() []*Transaction { - return block.transactions -} - -func (block *Block) CalcGasLimit(parent *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) -} - -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 - } - } - - 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() - } - - return encR -} - -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() - } - - return uncles -} - -func (block *Block) SetUncles(uncles []*Block) { - block.Uncles = uncles - block.UncleSha = crypto.Sha3(ethutil.Encode(block.rlpUncles())) -} - -func (self *Block) SetReceipts(receipts Receipts) { - self.receipts = receipts - self.ReceiptSha = DeriveSha(receipts) - self.LogsBloom = CreateBloom(receipts) -} - -func (self *Block) SetTransactions(txs Transactions) { - self.transactions = txs - self.TxSha = DeriveSha(txs) -} - -func (block *Block) Value() *ethutil.Value { - return ethutil.NewValue([]interface{}{block.header(), block.transactions, block.rlpUncles()}) -} - -func (block *Block) RlpEncode() []byte { - // Encode a slice interface which contains the header and the list of - // transactions. - return block.Value().Encode() -} - -func (block *Block) RlpDecode(data []byte) { - rlpValue := ethutil.NewValueFromBytes(data) - block.RlpValueDecode(rlpValue) -} - -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) 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.MinGasPrice = header.Get(9).BigInt() - self.GasLimit = header.Get(10).BigInt() - self.GasUsed = header.Get(11).BigInt() - self.Time = int64(header.Get(12).BigInt().Uint64()) - self.Extra = header.Get(13).Str() - self.Nonce = header.Get(14).Bytes() -} - -func NewUncleBlockFromValue(header *ethutil.Value) *Block { - block := &Block{} - block.setHeader(header) - - return block -} - -func (block *Block) Trie() *trie.Trie { - return block.state.Trie -} - -func (block *Block) Root() interface{} { - return block.state.Root() -} - -func (block *Block) Diff() *big.Int { - return block.Difficulty -} - -func (self *Block) Receipts() []*Receipt { - return self.receipts -} - -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 minimum gas price - block.MinGasPrice, - // Block upper gas bound - block.GasLimit, - // Block gas used - block.GasUsed, - // Time the block was found? - block.Time, - // Extra data - block.Extra, - } -} - -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 - MinGas: %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.MinGasPrice, - 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())) -} - -// Implement RlpEncodable -func (self *Block) RlpData() interface{} { - return self.Value().Val -} diff --git a/chain/block_manager.go b/chain/block_manager.go index efe9e0862..e652ad10e 100644 --- a/chain/block_manager.go +++ b/chain/block_manager.go @@ -9,6 +9,7 @@ import ( "sync" "time" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" @@ -69,7 +70,7 @@ type BlockManager struct { // The last attempted block is mainly used for debugging purposes // This does not have to be a valid block and will be set during // 'Process' & canonical validation. - lastAttemptedBlock *Block + lastAttemptedBlock *types.Block events event.Subscription } @@ -117,11 +118,11 @@ func (sm *BlockManager) ChainManager() *ChainManager { return sm.bc } -func (self *BlockManager) ProcessTransactions(coinbase *state.StateObject, state *state.State, block, parent *Block, txs Transactions) (Receipts, Transactions, Transactions, Transactions, error) { +func (self *BlockManager) ProcessTransactions(coinbase *state.StateObject, state *state.State, block, parent *types.Block, txs types.Transactions) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) { var ( - receipts Receipts - handled, unhandled Transactions - erroneous Transactions + receipts types.Receipts + handled, unhandled types.Transactions + erroneous types.Transactions totalUsedGas = big.NewInt(0) err error ) @@ -159,8 +160,9 @@ done: txGas.Sub(txGas, st.gas) cumulative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas)) - receipt := &Receipt{ethutil.CopyBytes(state.Root()), cumulative, nil /*bloom*/, state.Logs()} - receipt.Bloom = CreateBloom(Receipts{receipt}) + receipt := types.NewReceipt(state.Root(), cumulative) + receipt.SetLogs(state.Logs()) + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) // Notify all subscribers go self.eth.EventMux().Post(TxPostEvent{tx}) @@ -178,7 +180,7 @@ done: return receipts, handled, unhandled, erroneous, err } -func (sm *BlockManager) Process(block *Block) (td *big.Int, msgs state.Messages, err error) { +func (sm *BlockManager) Process(block *types.Block) (td *big.Int, msgs state.Messages, err error) { // Processing a blocks may never happen simultaneously sm.mutex.Lock() defer sm.mutex.Unlock() @@ -195,7 +197,7 @@ func (sm *BlockManager) Process(block *Block) (td *big.Int, msgs state.Messages, return sm.ProcessWithParent(block, parent) } -func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, messages state.Messages, err error) { +func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.Int, messages state.Messages, err error) { sm.lastAttemptedBlock = block state := parent.State().Copy() @@ -215,13 +217,13 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me return } - txSha := DeriveSha(block.transactions) + 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) return } - receiptSha := DeriveSha(receipts) + receiptSha := types.DeriveSha(receipts) if bytes.Compare(receiptSha, block.ReceiptSha) != 0 { err = fmt.Errorf("validating receipt root. received=%x got=%x", block.ReceiptSha, receiptSha) return @@ -238,8 +240,8 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me return } - block.receipts = receipts // although this isn't necessary it be in the future - rbloom := CreateBloom(receipts) + //block.receipts = receipts // although this isn't necessary it be in the future + rbloom := types.CreateBloom(receipts) if bytes.Compare(rbloom, block.LogsBloom) != 0 { err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom) return @@ -272,7 +274,7 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me } } -func (sm *BlockManager) ApplyDiff(state *state.State, parent, block *Block) (receipts Receipts, err error) { +func (sm *BlockManager) ApplyDiff(state *state.State, parent, block *types.Block) (receipts types.Receipts, err error) { coinbase := state.GetOrNewStateObject(block.Coinbase) coinbase.SetGasPool(block.CalcGasLimit(parent)) @@ -285,7 +287,7 @@ func (sm *BlockManager) ApplyDiff(state *state.State, parent, block *Block) (rec return receipts, nil } -func (sm *BlockManager) CalculateTD(block *Block) (*big.Int, bool) { +func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) { uncleDiff := new(big.Int) for _, uncle := range block.Uncles { uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty) @@ -311,7 +313,7 @@ func (sm *BlockManager) CalculateTD(block *Block) (*big.Int, bool) { // Validates the current block. Returns an error if the block was invalid, // an uncle or anything that isn't on the current block chain. // Validation validates easy over difficult (dagger takes longer time = difficult) -func (sm *BlockManager) ValidateBlock(block, parent *Block) error { +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) @@ -337,7 +339,7 @@ func (sm *BlockManager) ValidateBlock(block, parent *Block) error { return nil } -func (sm *BlockManager) AccumelateRewards(state *state.State, block, parent *Block) error { +func (sm *BlockManager) AccumelateRewards(state *state.State, block, parent *types.Block) error { reward := new(big.Int).Set(BlockReward) knownUncles := ethutil.Set(parent.Uncles) @@ -380,7 +382,7 @@ func (sm *BlockManager) AccumelateRewards(state *state.State, block, parent *Blo return nil } -func (sm *BlockManager) GetMessages(block *Block) (messages []*state.Message, err error) { +func (sm *BlockManager) GetMessages(block *types.Block) (messages []*state.Message, err error) { if !sm.bc.HasBlock(block.PrevHash) { return nil, ParentError(block.PrevHash) } diff --git a/chain/bloom9.go b/chain/bloom9.go deleted file mode 100644 index c610bd101..000000000 --- a/chain/bloom9.go +++ /dev/null @@ -1,56 +0,0 @@ -package chain - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/state" -) - -func CreateBloom(receipts Receipts) []byte { - bin := new(big.Int) - for _, receipt := range receipts { - bin.Or(bin, logsBloom(receipt.logs)) - } - - return ethutil.LeftPadBytes(bin.Bytes(), 64) -} - -func logsBloom(logs state.Logs) *big.Int { - bin := new(big.Int) - for _, log := range logs { - data := [][]byte{log.Address} - for _, topic := range log.Topics { - data = append(data, topic) - } - - for _, b := range data { - bin.Or(bin, ethutil.BigD(bloom9(crypto.Sha3(b)).Bytes())) - } - - //if log.Data != nil { - // data = append(data, log.Data) - //} - } - - return bin -} - -func bloom9(b []byte) *big.Int { - r := new(big.Int) - for _, i := range []int{0, 2, 4} { - t := big.NewInt(1) - b := uint(b[i+1]) + 256*(uint(b[i])&1) - r.Or(r, t.Lsh(t, b)) - } - - return r -} - -func BloomLookup(bin, topic []byte) bool { - bloom := ethutil.BigD(bin) - cmp := bloom9(crypto.Sha3(topic)) - - return bloom.And(bloom, cmp).Cmp(cmp) == 0 -} diff --git a/chain/bloom9_test.go b/chain/bloom9_test.go deleted file mode 100644 index 8b1b962cb..000000000 --- a/chain/bloom9_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package chain - -import ( - "testing" - "github.com/ethereum/go-ethereum/state" -) - -func TestBloom9(t *testing.T) { - testCase := []byte("testtest") - bin := LogsBloom([]state.Log{ - {testCase, [][]byte{[]byte("hellohello")}, nil}, - }).Bytes() - res := BloomLookup(bin, testCase) - - if !res { - t.Errorf("Bloom lookup failed") - } -} - -/* -func TestAddress(t *testing.T) { - block := &Block{} - block.Coinbase = ethutil.Hex2Bytes("22341ae42d6dd7384bc8584e50419ea3ac75b83f") - fmt.Printf("%x\n", crypto.Sha3(block.Coinbase)) - - bin := CreateBloom(block) - fmt.Printf("bin = %x\n", ethutil.LeftPadBytes(bin, 64)) -} -*/ diff --git a/chain/chain_manager.go b/chain/chain_manager.go index 02741bc0b..11df4e17e 100644 --- a/chain/chain_manager.go +++ b/chain/chain_manager.go @@ -6,6 +6,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/state" @@ -13,7 +14,7 @@ import ( var chainlogger = logger.NewLogger("CHAIN") -func AddTestNetFunds(block *Block) { +func AddTestNetFunds(block *types.Block) { for _, addr := range []string{ "51ba59315b3a95761d0863b05ccc7a7f54703d99", "e4157b34ea9615cfbde6b4fda419828124b70c78", @@ -25,13 +26,13 @@ func AddTestNetFunds(block *Block) { "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", } { codedAddr := ethutil.Hex2Bytes(addr) - account := block.state.GetAccount(codedAddr) + account := block.State().GetAccount(codedAddr) account.SetBalance(ethutil.Big("1606938044258990275541962092341162602522202993782792835301376")) //ethutil.BigPow(2, 200) - block.state.UpdateStateObject(account) + block.State().UpdateStateObject(account) } } -func CalcDifficulty(block, parent *Block) *big.Int { +func CalcDifficulty(block, parent *types.Block) *big.Int { diff := new(big.Int) adjust := new(big.Int).Rsh(parent.Difficulty, 10) @@ -45,36 +46,41 @@ func CalcDifficulty(block, parent *Block) *big.Int { } type ChainManager struct { - eth EthManager - genesisBlock *Block + //eth EthManager + processor types.BlockProcessor + genesisBlock *types.Block // Last known total difficulty TD *big.Int LastBlockNumber uint64 - CurrentBlock *Block + CurrentBlock *types.Block LastBlockHash []byte workingChain *BlockChain } -func NewChainManager(ethereum EthManager) *ChainManager { +func NewChainManager() *ChainManager { bc := &ChainManager{} - bc.genesisBlock = NewBlockFromBytes(ethutil.Encode(Genesis)) - bc.eth = ethereum + bc.genesisBlock = types.NewBlockFromBytes(ethutil.Encode(Genesis)) + //bc.eth = ethereum bc.setLastBlock() return bc } +func (self *ChainManager) SetProcessor(proc types.BlockProcessor) { + self.processor = proc +} + func (bc *ChainManager) setLastBlock() { data, _ := ethutil.Config.Db.Get([]byte("LastBlock")) if len(data) != 0 { // Prep genesis AddTestNetFunds(bc.genesisBlock) - block := NewBlockFromBytes(data) + block := types.NewBlockFromBytes(data) bc.CurrentBlock = block bc.LastBlockHash = block.Hash() bc.LastBlockNumber = block.Number.Uint64() @@ -89,7 +95,7 @@ func (bc *ChainManager) setLastBlock() { } // Block creation & chain handling -func (bc *ChainManager) NewBlock(coinbase []byte) *Block { +func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block { var root interface{} hash := ZeroHash256 @@ -98,7 +104,7 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *Block { hash = bc.LastBlockHash } - block := CreateBlock( + block := types.CreateBlock( root, hash, coinbase, @@ -122,7 +128,7 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *Block { func (bc *ChainManager) Reset() { AddTestNetFunds(bc.genesisBlock) - bc.genesisBlock.state.Trie.Sync() + bc.genesisBlock.Trie().Sync() // Prepare the genesis block bc.add(bc.genesisBlock) bc.CurrentBlock = bc.genesisBlock @@ -134,7 +140,7 @@ func (bc *ChainManager) Reset() { } // Add a block to the chain and record addition information -func (bc *ChainManager) add(block *Block) { +func (bc *ChainManager) add(block *types.Block) { bc.writeBlockInfo(block) bc.CurrentBlock = block @@ -148,7 +154,7 @@ func (bc *ChainManager) add(block *Block) { } // Accessors -func (bc *ChainManager) Genesis() *Block { +func (bc *ChainManager) Genesis() *types.Block { return bc.genesisBlock } @@ -179,7 +185,7 @@ func (self *ChainManager) GetChainHashesFromHash(hash []byte, max uint64) (chain return } -func (self *ChainManager) GetBlock(hash []byte) *Block { +func (self *ChainManager) GetBlock(hash []byte) *types.Block { data, _ := ethutil.Config.Db.Get(hash) if len(data) == 0 { if self.workingChain != nil { @@ -194,10 +200,10 @@ func (self *ChainManager) GetBlock(hash []byte) *Block { return nil } - return NewBlockFromBytes(data) + return types.NewBlockFromBytes(data) } -func (self *ChainManager) GetBlockByNumber(num uint64) *Block { +func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { block := self.CurrentBlock for ; block != nil; block = self.GetBlock(block.PrevHash) { if block.Number.Uint64() == num { @@ -217,7 +223,7 @@ func (bc *ChainManager) SetTotalDifficulty(td *big.Int) { bc.TD = td } -func (self *ChainManager) CalcTotalDiff(block *Block) (*big.Int, error) { +func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) { parent := self.GetBlock(block.PrevHash) if parent == nil { return nil, fmt.Errorf("Unable to calculate total diff without known parent %x", block.PrevHash) @@ -237,8 +243,8 @@ func (self *ChainManager) CalcTotalDiff(block *Block) (*big.Int, error) { return td, nil } -func (bc *ChainManager) BlockInfo(block *Block) BlockInfo { - bi := BlockInfo{} +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) @@ -246,9 +252,9 @@ func (bc *ChainManager) BlockInfo(block *Block) BlockInfo { } // Unexported method for writing extra non-essential block info to the db -func (bc *ChainManager) writeBlockInfo(block *Block) { +func (bc *ChainManager) writeBlockInfo(block *types.Block) { bc.LastBlockNumber++ - bi := BlockInfo{Number: bc.LastBlockNumber, Hash: block.Hash(), Parent: block.PrevHash, TD: bc.TD} + 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()) @@ -271,8 +277,8 @@ func (self *ChainManager) InsertChain(chain *BlockChain) { self.add(link.block) self.SetTotalDifficulty(link.td) - self.eth.EventMux().Post(NewBlockEvent{link.block}) - self.eth.EventMux().Post(link.messages) + //self.eth.EventMux().Post(NewBlockEvent{link.block}) + //self.eth.EventMux().Post(link.messages) } b, e := chain.Front(), chain.Back() @@ -299,7 +305,7 @@ func (self *ChainManager) TestChain(chain *BlockChain) (td *big.Int, err error) } var messages state.Messages - td, messages, err = self.eth.BlockManager().ProcessWithParent(block, parent) + td, messages, err = self.processor.ProcessWithParent(block, parent) //self.eth.BlockManager().ProcessWithParent(block, parent) if err != nil { chainlogger.Infoln(err) chainlogger.Debugf("Block #%v failed (%x...)\n", block.Number, block.Hash()[0:4]) @@ -323,7 +329,7 @@ func (self *ChainManager) TestChain(chain *BlockChain) (td *big.Int, err error) } type link struct { - block *Block + block *types.Block messages state.Messages td *big.Int } @@ -332,7 +338,7 @@ type BlockChain struct { *list.List } -func NewChain(blocks Blocks) *BlockChain { +func NewChain(blocks types.Blocks) *BlockChain { chain := &BlockChain{list.New()} for _, block := range blocks { @@ -353,10 +359,10 @@ func (self *BlockChain) RlpEncode() []byte { type ChainIterator struct { cm *ChainManager - block *Block // current block in the iterator + block *types.Block // current block in the iterator } -func (self *ChainIterator) Prev() *Block { +func (self *ChainIterator) Prev() *types.Block { self.block = self.cm.GetBlock(self.block.PrevHash) return self.block } diff --git a/chain/dagger.go b/chain/dagger.go index 2cf70e091..f7e2229e9 100644 --- a/chain/dagger.go +++ b/chain/dagger.go @@ -6,6 +6,7 @@ import ( "math/rand" "time" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" @@ -15,7 +16,7 @@ import ( var powlogger = logger.NewLogger("POW") type PoW interface { - Search(block *Block, stop <-chan struct{}) []byte + Search(block *types.Block, stop <-chan struct{}) []byte Verify(hash []byte, diff *big.Int, nonce []byte) bool GetHashrate() int64 Turbo(bool) @@ -35,7 +36,7 @@ func (pow *EasyPow) Turbo(on bool) { pow.turbo = on } -func (pow *EasyPow) Search(block *Block, stop <-chan struct{}) []byte { +func (pow *EasyPow) Search(block *types.Block, stop <-chan struct{}) []byte { r := rand.New(rand.NewSource(time.Now().UnixNano())) hash := block.HashNoNonce() diff := block.Difficulty diff --git a/chain/derive_sha.go b/chain/derive_sha.go deleted file mode 100644 index 4246aeb02..000000000 --- a/chain/derive_sha.go +++ /dev/null @@ -1,20 +0,0 @@ -package chain - -import ( - "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/trie" -) - -type DerivableList interface { - Len() int - GetRlp(i int) []byte -} - -func DeriveSha(list DerivableList) []byte { - trie := trie.New(ethutil.Config.Db, "") - for i := 0; i < list.Len(); i++ { - trie.Update(string(ethutil.NewValue(i).Encode()), string(list.GetRlp(i))) - } - - return trie.GetRoot() -} diff --git a/chain/events.go b/chain/events.go index 2703e955d..06ab6be79 100644 --- a/chain/events.go +++ b/chain/events.go @@ -1,10 +1,12 @@ package chain +import "github.com/ethereum/go-ethereum/chain/types" + // TxPreEvent is posted when a transaction enters the transaction pool. -type TxPreEvent struct{ Tx *Transaction } +type TxPreEvent struct{ Tx *types.Transaction } // TxPostEvent is posted when a transaction has been processed. -type TxPostEvent struct{ Tx *Transaction } +type TxPostEvent struct{ Tx *types.Transaction } // NewBlockEvent is posted when a block has been imported. -type NewBlockEvent struct{ Block *Block } +type NewBlockEvent struct{ Block *types.Block } diff --git a/chain/filter.go b/chain/filter.go index 3c0b02d4f..fd8adaa8f 100644 --- a/chain/filter.go +++ b/chain/filter.go @@ -5,6 +5,7 @@ import ( "math" "math/big" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" ) @@ -24,7 +25,7 @@ type Filter struct { Altered []AccountChange - BlockCallback func(*Block) + BlockCallback func(*types.Block) MessageCallback func(state.Messages) } @@ -171,11 +172,11 @@ func (self *Filter) FilterMessages(msgs []*state.Message) []*state.Message { return messages } -func (self *Filter) bloomFilter(block *Block) bool { +func (self *Filter) bloomFilter(block *types.Block) bool { var fromIncluded, toIncluded bool if len(self.from) > 0 { for _, from := range self.from { - if BloomLookup(block.LogsBloom, from) { + if types.BloomLookup(block.LogsBloom, from) { fromIncluded = true break } @@ -186,7 +187,7 @@ func (self *Filter) bloomFilter(block *Block) bool { if len(self.to) > 0 { for _, to := range self.to { - if BloomLookup(block.LogsBloom, ethutil.U256(new(big.Int).Add(ethutil.Big1, ethutil.BigD(to))).Bytes()) { + if types.BloomLookup(block.LogsBloom, ethutil.U256(new(big.Int).Add(ethutil.Big1, ethutil.BigD(to))).Bytes()) { toIncluded = true break } diff --git a/chain/receipt.go b/chain/receipt.go deleted file mode 100644 index fa53f1cdb..000000000 --- a/chain/receipt.go +++ /dev/null @@ -1,60 +0,0 @@ -package chain - -import ( - "bytes" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/state" -) - -type Receipt struct { - PostState []byte - CumulativeGasUsed *big.Int - Bloom []byte - logs state.Logs -} - -func NewRecieptFromValue(val *ethutil.Value) *Receipt { - r := &Receipt{} - r.RlpValueDecode(val) - - return r -} - -func (self *Receipt) RlpValueDecode(decoder *ethutil.Value) { - self.PostState = decoder.Get(0).Bytes() - self.CumulativeGasUsed = decoder.Get(1).BigInt() - self.Bloom = decoder.Get(2).Bytes() - - it := decoder.Get(3).NewIterator() - for it.Next() { - self.logs = append(self.logs, state.NewLogFromValue(it.Value())) - } -} - -func (self *Receipt) RlpData() interface{} { - return []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs.RlpData()} -} - -func (self *Receipt) RlpEncode() []byte { - return ethutil.Encode(self.RlpData()) -} - -func (self *Receipt) Cmp(other *Receipt) bool { - if bytes.Compare(self.PostState, other.PostState) != 0 { - return false - } - - return true -} - -func (self *Receipt) String() string { - return fmt.Sprintf("receipt{med=%x cgas=%v bloom=%x logs=%v}", self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs) -} - -type Receipts []*Receipt - -func (self Receipts) Len() int { return len(self) } -func (self Receipts) GetRlp(i int) []byte { return ethutil.Rlp(self[i]) } diff --git a/chain/state_transition.go b/chain/state_transition.go index afe044299..789698675 100644 --- a/chain/state_transition.go +++ b/chain/state_transition.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" ) @@ -26,17 +27,17 @@ import ( */ type StateTransition struct { coinbase, receiver []byte - tx *Transaction + tx *types.Transaction gas, gasPrice *big.Int value *big.Int data []byte state *state.State - block *Block + block *types.Block cb, rec, sen *state.StateObject } -func NewStateTransition(coinbase *state.StateObject, tx *Transaction, state *state.State, block *Block) *StateTransition { +func NewStateTransition(coinbase *state.StateObject, tx *types.Transaction, state *state.State, block *types.Block) *StateTransition { return &StateTransition{coinbase.Address(), tx.Recipient, tx, new(big.Int), new(big.Int).Set(tx.GasPrice), tx.Value, tx.Data, state, block, coinbase, nil, nil} } @@ -203,7 +204,7 @@ func (self *StateTransition) TransitionState() (err error) { }) // Process the init code and create 'valid' contract - if IsContractAddr(self.receiver) { + if types.IsContractAddr(self.receiver) { // Evaluate the initialization script // and use the return value as the // script section for the state object. @@ -280,7 +281,7 @@ func (self *StateTransition) Eval(msg *state.Message, script []byte, context *st } // Converts an transaction in to a state object -func MakeContract(tx *Transaction, state *state.State) *state.StateObject { +func MakeContract(tx *types.Transaction, state *state.State) *state.StateObject { addr := tx.CreationAddress(state) contract := state.GetOrNewStateObject(addr) diff --git a/chain/transaction.go b/chain/transaction.go deleted file mode 100644 index d81a0ea1b..000000000 --- a/chain/transaction.go +++ /dev/null @@ -1,224 +0,0 @@ -package chain - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/state" - "github.com/obscuren/secp256k1-go" -) - -var ContractAddr = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - -func IsContractAddr(addr []byte) bool { - return len(addr) == 0 - //return bytes.Compare(addr, ContractAddr) == 0 -} - -type Transaction struct { - Nonce uint64 - Recipient []byte - Value *big.Int - Gas *big.Int - GasPrice *big.Int - Data []byte - v byte - r, s []byte - - // Indicates whether this tx is a contract creation transaction - contractCreation bool -} - -func NewContractCreationTx(value, gas, gasPrice *big.Int, script []byte) *Transaction { - return &Transaction{Recipient: nil, Value: value, Gas: gas, GasPrice: gasPrice, Data: script, contractCreation: true} -} - -func NewTransactionMessage(to []byte, value, gas, gasPrice *big.Int, data []byte) *Transaction { - return &Transaction{Recipient: to, Value: value, GasPrice: gasPrice, Gas: gas, Data: data, contractCreation: IsContractAddr(to)} -} - -func NewTransactionFromBytes(data []byte) *Transaction { - tx := &Transaction{} - tx.RlpDecode(data) - - return tx -} - -func NewTransactionFromValue(val *ethutil.Value) *Transaction { - tx := &Transaction{} - tx.RlpValueDecode(val) - - return tx -} - -func (self *Transaction) GasValue() *big.Int { - return new(big.Int).Mul(self.Gas, self.GasPrice) -} - -func (self *Transaction) TotalValue() *big.Int { - v := self.GasValue() - return v.Add(v, self.Value) -} - -func (tx *Transaction) Hash() []byte { - data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data} - - return crypto.Sha3(ethutil.NewValue(data).Encode()) -} - -func (tx *Transaction) CreatesContract() bool { - return tx.contractCreation -} - -/* Deprecated */ -func (tx *Transaction) IsContract() bool { - return tx.CreatesContract() -} - -func (tx *Transaction) CreationAddress(state *state.State) []byte { - // Generate a new address - addr := crypto.Sha3(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:] - //for i := uint64(0); state.GetStateObject(addr) != nil; i++ { - // addr = crypto.Sha3(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce + i}).Encode())[12:] - //} - - return addr -} - -func (tx *Transaction) Signature(key []byte) []byte { - hash := tx.Hash() - - sig, _ := secp256k1.Sign(hash, key) - - return sig -} - -func (tx *Transaction) PublicKey() []byte { - hash := tx.Hash() - - // TODO - r := ethutil.LeftPadBytes(tx.r, 32) - s := ethutil.LeftPadBytes(tx.s, 32) - - sig := append(r, s...) - sig = append(sig, tx.v-27) - - pubkey := crypto.Ecrecover(append(hash, sig...)) - //pubkey, _ := secp256k1.RecoverPubkey(hash, sig) - - return pubkey -} - -func (tx *Transaction) Sender() []byte { - pubkey := tx.PublicKey() - - // Validate the returned key. - // Return nil if public key isn't in full format - if len(pubkey) != 0 && pubkey[0] != 4 { - return nil - } - - return crypto.Sha3(pubkey[1:])[12:] -} - -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 - - return nil -} - -func (tx *Transaction) RlpData() interface{} { - data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data} - - // TODO Remove prefixing zero's - - 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()) -} - -func (tx *Transaction) RlpEncode() []byte { - return tx.RlpValue().Encode() -} - -func (tx *Transaction) RlpDecode(data []byte) { - tx.RlpValueDecode(ethutil.NewValueFromBytes(data)) -} - -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() - - if IsContractAddr(tx.Recipient) { - tx.contractCreation = true - } -} - -func (tx *Transaction) String() string { - return fmt.Sprintf(` - TX(%x) - Contract: %v - From: %x - To: %x - Nonce: %v - GasPrice: %v - Gas: %v - Value: %v - Data: 0x%x - V: 0x%x - R: 0x%x - S: 0x%x - `, - tx.Hash(), - len(tx.Recipient) == 0, - tx.Sender(), - tx.Recipient, - tx.Nonce, - tx.GasPrice, - tx.Gas, - tx.Value, - tx.Data, - tx.v, - tx.r, - tx.s) -} - -// Transaction slice type for basic sorting -type Transactions []*Transaction - -func (self Transactions) RlpData() interface{} { - // Marshal the transactions of this block - enc := make([]interface{}, len(self)) - for i, tx := range self { - // Cast it to a string (safe) - enc[i] = tx.RlpData() - } - - return enc -} -func (s Transactions) Len() int { return len(s) } -func (s Transactions) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -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 -} diff --git a/chain/transaction_pool.go b/chain/transaction_pool.go index ff75089d6..119712ba8 100644 --- a/chain/transaction_pool.go +++ b/chain/transaction_pool.go @@ -7,6 +7,7 @@ import ( "math/big" "sync" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/wire" @@ -16,7 +17,7 @@ var txplogger = logger.NewLogger("TXP") const txPoolQueueSize = 50 -type TxPoolHook chan *Transaction +type TxPoolHook chan *types.Transaction type TxMsgTy byte const ( @@ -26,21 +27,21 @@ const ( var MinGasPrice = big.NewInt(10000000000000) type TxMsg struct { - Tx *Transaction + Tx *types.Transaction Type TxMsgTy } -func EachTx(pool *list.List, it func(*Transaction, *list.Element) bool) { +func EachTx(pool *list.List, it func(*types.Transaction, *list.Element) bool) { for e := pool.Front(); e != nil; e = e.Next() { - if it(e.Value.(*Transaction), e) { + if it(e.Value.(*types.Transaction), e) { break } } } -func FindTx(pool *list.List, finder func(*Transaction, *list.Element) bool) *Transaction { +func FindTx(pool *list.List, finder func(*types.Transaction, *list.Element) bool) *types.Transaction { for e := pool.Front(); e != nil; e = e.Next() { - if tx, ok := e.Value.(*Transaction); ok { + if tx, ok := e.Value.(*types.Transaction); ok { if finder(tx, e) { return tx } @@ -51,7 +52,7 @@ func FindTx(pool *list.List, finder func(*Transaction, *list.Element) bool) *Tra } type TxProcessor interface { - ProcessTransaction(tx *Transaction) + ProcessTransaction(tx *types.Transaction) } // The tx pool a thread safe transaction pool handler. In order to @@ -65,7 +66,7 @@ type TxPool struct { mutex sync.Mutex // Queueing channel for reading and writing incoming // transactions to - queueChan chan *Transaction + queueChan chan *types.Transaction // Quiting channel quit chan bool // The actual pool @@ -79,14 +80,14 @@ type TxPool struct { func NewTxPool(ethereum EthManager) *TxPool { return &TxPool{ pool: list.New(), - queueChan: make(chan *Transaction, txPoolQueueSize), + queueChan: make(chan *types.Transaction, txPoolQueueSize), quit: make(chan bool), Ethereum: ethereum, } } // Blocking function. Don't use directly. Use QueueTransaction instead -func (pool *TxPool) addTransaction(tx *Transaction) { +func (pool *TxPool) addTransaction(tx *types.Transaction) { pool.mutex.Lock() defer pool.mutex.Unlock() @@ -96,7 +97,7 @@ func (pool *TxPool) addTransaction(tx *Transaction) { pool.Ethereum.Broadcast(wire.MsgTxTy, []interface{}{tx.RlpData()}) } -func (pool *TxPool) ValidateTransaction(tx *Transaction) error { +func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { // Get the last block so we can retrieve the sender and receiver from // the merkle trie block := pool.Ethereum.ChainManager().CurrentBlock @@ -142,7 +143,7 @@ out: select { case tx := <-pool.queueChan: hash := tx.Hash() - foundTx := FindTx(pool.pool, func(tx *Transaction, e *list.Element) bool { + foundTx := FindTx(pool.pool, func(tx *types.Transaction, e *list.Element) bool { return bytes.Compare(tx.Hash(), hash) == 0 }) @@ -172,18 +173,18 @@ out: } } -func (pool *TxPool) QueueTransaction(tx *Transaction) { +func (pool *TxPool) QueueTransaction(tx *types.Transaction) { pool.queueChan <- tx } -func (pool *TxPool) CurrentTransactions() []*Transaction { +func (pool *TxPool) CurrentTransactions() []*types.Transaction { pool.mutex.Lock() defer pool.mutex.Unlock() - txList := make([]*Transaction, pool.pool.Len()) + txList := make([]*types.Transaction, pool.pool.Len()) i := 0 for e := pool.pool.Front(); e != nil; e = e.Next() { - tx := e.Value.(*Transaction) + tx := e.Value.(*types.Transaction) txList[i] = tx @@ -198,7 +199,7 @@ func (pool *TxPool) RemoveInvalid(state *state.State) { defer pool.mutex.Unlock() for e := pool.pool.Front(); e != nil; e = e.Next() { - tx := e.Value.(*Transaction) + tx := e.Value.(*types.Transaction) sender := state.GetAccount(tx.Sender()) err := pool.ValidateTransaction(tx) if err != nil || sender.Nonce >= tx.Nonce { @@ -207,12 +208,12 @@ func (pool *TxPool) RemoveInvalid(state *state.State) { } } -func (self *TxPool) RemoveSet(txs Transactions) { +func (self *TxPool) RemoveSet(txs types.Transactions) { self.mutex.Lock() defer self.mutex.Unlock() for _, tx := range txs { - EachTx(self.pool, func(t *Transaction, element *list.Element) bool { + EachTx(self.pool, func(t *types.Transaction, element *list.Element) bool { if t == tx { self.pool.Remove(element) return true // To stop the loop @@ -222,7 +223,7 @@ func (self *TxPool) RemoveSet(txs Transactions) { } } -func (pool *TxPool) Flush() []*Transaction { +func (pool *TxPool) Flush() []*types.Transaction { txList := pool.CurrentTransactions() // Recreate a new list all together diff --git a/chain/transaction_test.go b/chain/transaction_test.go deleted file mode 100644 index fef1d2010..000000000 --- a/chain/transaction_test.go +++ /dev/null @@ -1 +0,0 @@ -package chain diff --git a/chain/types/block.go b/chain/types/block.go new file mode 100644 index 000000000..b311433e3 --- /dev/null +++ b/chain/types/block.go @@ -0,0 +1,419 @@ +package types + +import ( + "bytes" + "fmt" + "math/big" + "sort" + "time" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethutil" + "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 { + // Hash to the previous block + PrevHash ethutil.Bytes + // Uncles of this block + Uncles Blocks + UncleSha []byte + // The coin base address + Coinbase []byte + // Block Trie state + //state *ethutil.Trie + state *state.State + // Difficulty for the current block + Difficulty *big.Int + // Creation time + Time int64 + // The block number + Number *big.Int + // Minimum Gas Price + MinGasPrice *big.Int + // Gas limit + GasLimit *big.Int + // Gas used + GasUsed *big.Int + // 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 +} + +func NewBlockFromBytes(raw []byte) *Block { + block := &Block{} + block.RlpDecode(raw) + + return block +} + +// New block takes a raw encoded string +func NewBlockFromRlpValue(rlpValue *ethutil.Value) *Block { + block := &Block{} + block.RlpValueDecode(rlpValue) + + return block +} + +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(), + Extra: extra, + UncleSha: nil, + GasUsed: new(big.Int), + MinGasPrice: new(big.Int), + GasLimit: new(big.Int), + } + block.SetUncles([]*Block{}) + + block.state = state.New(trie.New(ethutil.Config.Db, root)) + + 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.State { + return block.state +} + +func (block *Block) Transactions() Transactions { + return block.transactions +} + +func (block *Block) CalcGasLimit(parent *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) +} + +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 + } + } + + 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() + } + + return encR +} + +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() + } + + return uncles +} + +func (block *Block) SetUncles(uncles []*Block) { + block.Uncles = uncles + block.UncleSha = crypto.Sha3(ethutil.Encode(block.rlpUncles())) +} + +func (self *Block) SetReceipts(receipts Receipts) { + self.receipts = receipts + self.ReceiptSha = DeriveSha(receipts) + self.LogsBloom = CreateBloom(receipts) +} + +func (self *Block) SetTransactions(txs Transactions) { + self.transactions = txs + self.TxSha = DeriveSha(txs) +} + +func (block *Block) Value() *ethutil.Value { + return ethutil.NewValue([]interface{}{block.header(), block.transactions, block.rlpUncles()}) +} + +func (block *Block) RlpEncode() []byte { + // Encode a slice interface which contains the header and the list of + // transactions. + return block.Value().Encode() +} + +func (block *Block) RlpDecode(data []byte) { + rlpValue := ethutil.NewValueFromBytes(data) + block.RlpValueDecode(rlpValue) +} + +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) 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.MinGasPrice = header.Get(9).BigInt() + self.GasLimit = header.Get(10).BigInt() + self.GasUsed = header.Get(11).BigInt() + self.Time = int64(header.Get(12).BigInt().Uint64()) + self.Extra = header.Get(13).Str() + self.Nonce = header.Get(14).Bytes() +} + +func NewUncleBlockFromValue(header *ethutil.Value) *Block { + block := &Block{} + block.setHeader(header) + + return block +} + +func (block *Block) Trie() *trie.Trie { + return block.state.Trie +} + +func (block *Block) Root() interface{} { + return block.state.Root() +} + +func (block *Block) Diff() *big.Int { + return block.Difficulty +} + +func (self *Block) Receipts() []*Receipt { + return self.receipts +} + +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 minimum gas price + block.MinGasPrice, + // Block upper gas bound + block.GasLimit, + // Block gas used + block.GasUsed, + // Time the block was found? + block.Time, + // Extra data + block.Extra, + } +} + +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 + MinGas: %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.MinGasPrice, + 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())) +} + +// Implement RlpEncodable +func (self *Block) RlpData() interface{} { + return self.Value().Val +} diff --git a/chain/types/bloom9.go b/chain/types/bloom9.go new file mode 100644 index 000000000..626711cca --- /dev/null +++ b/chain/types/bloom9.go @@ -0,0 +1,56 @@ +package types + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/state" +) + +func CreateBloom(receipts Receipts) []byte { + bin := new(big.Int) + for _, receipt := range receipts { + bin.Or(bin, logsBloom(receipt.logs)) + } + + return ethutil.LeftPadBytes(bin.Bytes(), 64) +} + +func logsBloom(logs state.Logs) *big.Int { + bin := new(big.Int) + for _, log := range logs { + data := [][]byte{log.Address} + for _, topic := range log.Topics { + data = append(data, topic) + } + + for _, b := range data { + bin.Or(bin, ethutil.BigD(bloom9(crypto.Sha3(b)).Bytes())) + } + + //if log.Data != nil { + // data = append(data, log.Data) + //} + } + + return bin +} + +func bloom9(b []byte) *big.Int { + r := new(big.Int) + for _, i := range []int{0, 2, 4} { + t := big.NewInt(1) + b := uint(b[i+1]) + 256*(uint(b[i])&1) + r.Or(r, t.Lsh(t, b)) + } + + return r +} + +func BloomLookup(bin, topic []byte) bool { + bloom := ethutil.BigD(bin) + cmp := bloom9(crypto.Sha3(topic)) + + return bloom.And(bloom, cmp).Cmp(cmp) == 0 +} diff --git a/chain/types/bloom9_test.go b/chain/types/bloom9_test.go new file mode 100644 index 000000000..8ee63becb --- /dev/null +++ b/chain/types/bloom9_test.go @@ -0,0 +1,30 @@ +package types + +import ( + "testing" + + "github.com/ethereum/go-ethereum/state" +) + +func TestBloom9(t *testing.T) { + testCase := []byte("testtest") + bin := LogsBloom([]state.Log{ + {testCase, [][]byte{[]byte("hellohello")}, nil}, + }).Bytes() + res := BloomLookup(bin, testCase) + + if !res { + t.Errorf("Bloom lookup failed") + } +} + +/* +func TestAddress(t *testing.T) { + block := &Block{} + block.Coinbase = ethutil.Hex2Bytes("22341ae42d6dd7384bc8584e50419ea3ac75b83f") + fmt.Printf("%x\n", crypto.Sha3(block.Coinbase)) + + bin := CreateBloom(block) + fmt.Printf("bin = %x\n", ethutil.LeftPadBytes(bin, 64)) +} +*/ diff --git a/chain/types/common.go b/chain/types/common.go new file mode 100644 index 000000000..ae0e7c3fa --- /dev/null +++ b/chain/types/common.go @@ -0,0 +1,10 @@ +package types + +import ( + "math/big" + "github.com/ethereum/go-ethereum/state" +) + +type BlockProcessor interface { + ProcessWithParent(*Block, *Block) (*big.Int, state.Messages, error) +} diff --git a/chain/types/derive_sha.go b/chain/types/derive_sha.go new file mode 100644 index 000000000..1897ff198 --- /dev/null +++ b/chain/types/derive_sha.go @@ -0,0 +1,20 @@ +package types + +import ( + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/trie" +) + +type DerivableList interface { + Len() int + GetRlp(i int) []byte +} + +func DeriveSha(list DerivableList) []byte { + trie := trie.New(ethutil.Config.Db, "") + for i := 0; i < list.Len(); i++ { + trie.Update(string(ethutil.NewValue(i).Encode()), string(list.GetRlp(i))) + } + + return trie.GetRoot() +} diff --git a/chain/types/receipt.go b/chain/types/receipt.go new file mode 100644 index 000000000..25fa8fb07 --- /dev/null +++ b/chain/types/receipt.go @@ -0,0 +1,68 @@ +package types + +import ( + "bytes" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/state" +) + +type Receipt struct { + PostState []byte + CumulativeGasUsed *big.Int + Bloom []byte + logs state.Logs +} + +func NewReceipt(root []byte, cumalativeGasUsed *big.Int) *Receipt { + return &Receipt{PostState: ethutil.CopyBytes(root), CumulativeGasUsed: cumalativeGasUsed} +} + +func NewRecieptFromValue(val *ethutil.Value) *Receipt { + r := &Receipt{} + r.RlpValueDecode(val) + + return r +} + +func (self *Receipt) SetLogs(logs state.Logs) { + self.logs = logs +} + +func (self *Receipt) RlpValueDecode(decoder *ethutil.Value) { + self.PostState = decoder.Get(0).Bytes() + self.CumulativeGasUsed = decoder.Get(1).BigInt() + self.Bloom = decoder.Get(2).Bytes() + + it := decoder.Get(3).NewIterator() + for it.Next() { + self.logs = append(self.logs, state.NewLogFromValue(it.Value())) + } +} + +func (self *Receipt) RlpData() interface{} { + return []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs.RlpData()} +} + +func (self *Receipt) RlpEncode() []byte { + return ethutil.Encode(self.RlpData()) +} + +func (self *Receipt) Cmp(other *Receipt) bool { + if bytes.Compare(self.PostState, other.PostState) != 0 { + return false + } + + return true +} + +func (self *Receipt) String() string { + return fmt.Sprintf("receipt{med=%x cgas=%v bloom=%x logs=%v}", self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs) +} + +type Receipts []*Receipt + +func (self Receipts) Len() int { return len(self) } +func (self Receipts) GetRlp(i int) []byte { return ethutil.Rlp(self[i]) } diff --git a/chain/types/transaction.go b/chain/types/transaction.go new file mode 100644 index 000000000..626a7e5ce --- /dev/null +++ b/chain/types/transaction.go @@ -0,0 +1,224 @@ +package types + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/state" + "github.com/obscuren/secp256k1-go" +) + +var ContractAddr = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +func IsContractAddr(addr []byte) bool { + return len(addr) == 0 + //return bytes.Compare(addr, ContractAddr) == 0 +} + +type Transaction struct { + Nonce uint64 + Recipient []byte + Value *big.Int + Gas *big.Int + GasPrice *big.Int + Data []byte + v byte + r, s []byte + + // Indicates whether this tx is a contract creation transaction + contractCreation bool +} + +func NewContractCreationTx(value, gas, gasPrice *big.Int, script []byte) *Transaction { + return &Transaction{Recipient: nil, Value: value, Gas: gas, GasPrice: gasPrice, Data: script, contractCreation: true} +} + +func NewTransactionMessage(to []byte, value, gas, gasPrice *big.Int, data []byte) *Transaction { + return &Transaction{Recipient: to, Value: value, GasPrice: gasPrice, Gas: gas, Data: data, contractCreation: IsContractAddr(to)} +} + +func NewTransactionFromBytes(data []byte) *Transaction { + tx := &Transaction{} + tx.RlpDecode(data) + + return tx +} + +func NewTransactionFromValue(val *ethutil.Value) *Transaction { + tx := &Transaction{} + tx.RlpValueDecode(val) + + return tx +} + +func (self *Transaction) GasValue() *big.Int { + return new(big.Int).Mul(self.Gas, self.GasPrice) +} + +func (self *Transaction) TotalValue() *big.Int { + v := self.GasValue() + return v.Add(v, self.Value) +} + +func (tx *Transaction) Hash() []byte { + data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data} + + return crypto.Sha3(ethutil.NewValue(data).Encode()) +} + +func (tx *Transaction) CreatesContract() bool { + return tx.contractCreation +} + +/* Deprecated */ +func (tx *Transaction) IsContract() bool { + return tx.CreatesContract() +} + +func (tx *Transaction) CreationAddress(state *state.State) []byte { + // Generate a new address + addr := crypto.Sha3(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:] + //for i := uint64(0); state.GetStateObject(addr) != nil; i++ { + // addr = crypto.Sha3(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce + i}).Encode())[12:] + //} + + return addr +} + +func (tx *Transaction) Signature(key []byte) []byte { + hash := tx.Hash() + + sig, _ := secp256k1.Sign(hash, key) + + return sig +} + +func (tx *Transaction) PublicKey() []byte { + hash := tx.Hash() + + // TODO + r := ethutil.LeftPadBytes(tx.r, 32) + s := ethutil.LeftPadBytes(tx.s, 32) + + sig := append(r, s...) + sig = append(sig, tx.v-27) + + pubkey := crypto.Ecrecover(append(hash, sig...)) + //pubkey, _ := secp256k1.RecoverPubkey(hash, sig) + + return pubkey +} + +func (tx *Transaction) Sender() []byte { + pubkey := tx.PublicKey() + + // Validate the returned key. + // Return nil if public key isn't in full format + if len(pubkey) != 0 && pubkey[0] != 4 { + return nil + } + + return crypto.Sha3(pubkey[1:])[12:] +} + +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 + + return nil +} + +func (tx *Transaction) RlpData() interface{} { + data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data} + + // TODO Remove prefixing zero's + + 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()) +} + +func (tx *Transaction) RlpEncode() []byte { + return tx.RlpValue().Encode() +} + +func (tx *Transaction) RlpDecode(data []byte) { + tx.RlpValueDecode(ethutil.NewValueFromBytes(data)) +} + +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() + + if IsContractAddr(tx.Recipient) { + tx.contractCreation = true + } +} + +func (tx *Transaction) String() string { + return fmt.Sprintf(` + TX(%x) + Contract: %v + From: %x + To: %x + Nonce: %v + GasPrice: %v + Gas: %v + Value: %v + Data: 0x%x + V: 0x%x + R: 0x%x + S: 0x%x + `, + tx.Hash(), + len(tx.Recipient) == 0, + tx.Sender(), + tx.Recipient, + tx.Nonce, + tx.GasPrice, + tx.Gas, + tx.Value, + tx.Data, + tx.v, + tx.r, + tx.s) +} + +// Transaction slice type for basic sorting +type Transactions []*Transaction + +func (self Transactions) RlpData() interface{} { + // Marshal the transactions of this block + enc := make([]interface{}, len(self)) + for i, tx := range self { + // Cast it to a string (safe) + enc[i] = tx.RlpData() + } + + return enc +} +func (s Transactions) Len() int { return len(s) } +func (s Transactions) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +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 +} diff --git a/chain/types/transaction_test.go b/chain/types/transaction_test.go new file mode 100644 index 000000000..ab1254f4c --- /dev/null +++ b/chain/types/transaction_test.go @@ -0,0 +1 @@ +package types diff --git a/chain/vm_env.go b/chain/vm_env.go index 4f3dc3ca4..c1911ff51 100644 --- a/chain/vm_env.go +++ b/chain/vm_env.go @@ -3,17 +3,18 @@ package chain import ( "math/big" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" ) type VMEnv struct { state *state.State - block *Block - tx *Transaction + block *types.Block + tx *types.Transaction } -func NewEnv(state *state.State, tx *Transaction, block *Block) *VMEnv { +func NewEnv(state *state.State, tx *types.Transaction, block *types.Block) *VMEnv { return &VMEnv{ state: state, block: block, diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go index 480c38b2e..eb78c3acc 100644 --- a/cmd/mist/bindings.go +++ b/cmd/mist/bindings.go @@ -21,8 +21,7 @@ import ( "encoding/json" "os" "strconv" - - "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" @@ -106,7 +105,7 @@ func (self *Gui) DumpState(hash, path string) { if len(hash) == 0 { stateDump = self.eth.BlockManager().CurrentState().Dump() } else { - var block *chain.Block + var block *types.Block if hash[0] == '#' { i, _ := strconv.Atoi(hash[1:]) block = self.eth.ChainManager().GetBlockByNumber(uint64(i)) diff --git a/cmd/mist/ext_app.go b/cmd/mist/ext_app.go index d004f98c5..22fa4bfaf 100644 --- a/cmd/mist/ext_app.go +++ b/cmd/mist/ext_app.go @@ -21,6 +21,7 @@ import ( "encoding/json" "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/javascript" "github.com/ethereum/go-ethereum/state" @@ -36,7 +37,7 @@ type AppContainer interface { Window() *qml.Window Engine() *qml.Engine - NewBlock(*chain.Block) + NewBlock(*types.Block) NewWatcher(chan bool) Messages(state.Messages, string) Post(string, int) diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go index 62943fa9e..61b66cce3 100644 --- a/cmd/mist/gui.go +++ b/cmd/mist/gui.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" @@ -290,7 +291,7 @@ func (self *Gui) loadMergedMiningOptions() { } } -func (gui *Gui) insertTransaction(window string, tx *chain.Transaction) { +func (gui *Gui) insertTransaction(window string, tx *types.Transaction) { pipe := xeth.New(gui.eth) nameReg := pipe.World().Config().Get("NameReg") addr := gui.address() @@ -340,7 +341,7 @@ func (gui *Gui) insertTransaction(window string, tx *chain.Transaction) { func (gui *Gui) readPreviousTransactions() { it := gui.txDb.NewIterator() for it.Next() { - tx := chain.NewTransactionFromBytes(it.Value()) + tx := types.NewTransactionFromBytes(it.Value()) gui.insertTransaction("post", tx) @@ -348,7 +349,7 @@ func (gui *Gui) readPreviousTransactions() { it.Release() } -func (gui *Gui) processBlock(block *chain.Block, initial bool) { +func (gui *Gui) processBlock(block *types.Block, initial bool) { name := strings.Trim(gui.pipe.World().Config().Get("NameReg").Storage(block.Coinbase).Str(), "\x00") b := xeth.NewJSBlock(block) b.Name = name diff --git a/cmd/mist/html_container.go b/cmd/mist/html_container.go index 35e351b02..4c6609a95 100644 --- a/cmd/mist/html_container.go +++ b/cmd/mist/html_container.go @@ -26,8 +26,7 @@ import ( "os" "path" "path/filepath" - - "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/javascript" "github.com/ethereum/go-ethereum/state" @@ -138,7 +137,7 @@ func (app *HtmlApplication) Window() *qml.Window { return app.win } -func (app *HtmlApplication) NewBlock(block *chain.Block) { +func (app *HtmlApplication) NewBlock(block *types.Block) { b := &xeth.JSBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Bytes2Hex(block.Hash())} app.webView.Call("onNewBlockCb", b) } diff --git a/cmd/mist/qml_container.go b/cmd/mist/qml_container.go index 60013ec2b..b5986c16e 100644 --- a/cmd/mist/qml_container.go +++ b/cmd/mist/qml_container.go @@ -20,8 +20,7 @@ package main import ( "fmt" "runtime" - - "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/xeth" @@ -65,7 +64,7 @@ func (app *QmlApplication) NewWatcher(quitChan chan bool) { } // Events -func (app *QmlApplication) NewBlock(block *chain.Block) { +func (app *QmlApplication) NewBlock(block *types.Block) { pblock := &xeth.JSBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Bytes2Hex(block.Hash())} app.win.Call("onNewBlockCb", pblock) } diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go index 4e480144f..01352f192 100644 --- a/cmd/mist/ui_lib.go +++ b/cmd/mist/ui_lib.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/javascript" @@ -126,7 +127,7 @@ func (self *UiLib) PastPeers() *ethutil.List { } func (self *UiLib) ImportTx(rlpTx string) { - tx := chain.NewTransactionFromBytes(ethutil.Hex2Bytes(rlpTx)) + tx := types.NewTransactionFromBytes(ethutil.Hex2Bytes(rlpTx)) self.eth.TxPool().QueueTransaction(tx) } @@ -228,7 +229,7 @@ func (self *UiLib) NewFilter(object map[string]interface{}) (id int) { func (self *UiLib) NewFilterString(typ string) (id int) { filter := chain.NewFilter(self.eth) - filter.BlockCallback = func(block *chain.Block) { + filter.BlockCallback = func(block *types.Block) { if self.win != nil && self.win.Root() != nil { self.win.Root().Call("invokeFilterCallback", "{}", id) } else { diff --git a/cmd/utils/vm_env.go b/cmd/utils/vm_env.go index e201627e2..b2788efa1 100644 --- a/cmd/utils/vm_env.go +++ b/cmd/utils/vm_env.go @@ -2,21 +2,20 @@ package utils import ( "math/big" - - "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" ) type VMEnv struct { state *state.State - block *chain.Block + block *types.Block transactor []byte value *big.Int } -func NewEnv(state *state.State, block *chain.Block, transactor []byte, value *big.Int) *VMEnv { +func NewEnv(state *state.State, block *types.Block, transactor []byte, value *big.Int) *VMEnv { return &VMEnv{ state: state, block: block, diff --git a/ethereum.go b/ethereum.go index ce8a92b58..879a14bd5 100644 --- a/ethereum.go +++ b/ethereum.go @@ -129,8 +129,9 @@ func New(db ethutil.Database, clientIdentity wire.ClientIdentity, keyManager *cr ethereum.blockPool = NewBlockPool(ethereum) ethereum.txPool = chain.NewTxPool(ethereum) - ethereum.blockChain = chain.NewChainManager(ethereum) + ethereum.blockChain = chain.NewChainManager() ethereum.blockManager = chain.NewBlockManager(ethereum) + ethereum.blockChain.SetProcessor(ethereum.blockManager) // Start the tx pool ethereum.txPool.Start() diff --git a/javascript/javascript_runtime.go b/javascript/javascript_runtime.go index 86a376fbf..e8b785f50 100644 --- a/javascript/javascript_runtime.go +++ b/javascript/javascript_runtime.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" @@ -130,7 +131,7 @@ func (self *JSRE) dump(call otto.FunctionCall) otto.Value { var state *state.State if len(call.ArgumentList) > 0 { - var block *chain.Block + var block *types.Block if call.Argument(0).IsNumber() { num, _ := call.Argument(0).ToInteger() block = self.ethereum.ChainManager().GetBlockByNumber(uint64(num)) diff --git a/miner/miner.go b/miner/miner.go index a678a6895..b25e25357 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/wire" @@ -44,7 +45,7 @@ type LocalTx struct { Value string `json:"value"` } -func (self *LocalTx) Sign(key []byte) *chain.Transaction { +func (self *LocalTx) Sign(key []byte) *types.Transaction { return nil } @@ -54,7 +55,7 @@ type Miner struct { eth *eth.Ethereum events event.Subscription - uncles chain.Blocks + uncles types.Blocks localTxs map[int]*LocalTx localTxId int @@ -212,7 +213,7 @@ func (self *Miner) mine() { nonce := self.pow.Search(block, self.powQuitCh) if nonce != nil { block.Nonce = nonce - lchain := chain.NewChain(chain.Blocks{block}) + lchain := chain.NewChain(types.Blocks{block}) _, err := chainMan.TestChain(lchain) if err != nil { minerlogger.Infoln(err) @@ -229,15 +230,15 @@ func (self *Miner) mine() { } } -func (self *Miner) finiliseTxs() chain.Transactions { +func (self *Miner) finiliseTxs() types.Transactions { // Sort the transactions by nonce in case of odd network propagation - var txs chain.Transactions + var txs types.Transactions state := self.eth.BlockManager().TransState() // XXX This has to change. Coinbase is, for new, same as key. key := self.eth.KeyManager() for _, ltx := range self.localTxs { - tx := chain.NewTransactionMessage(ltx.To, ethutil.Big(ltx.Value), ethutil.Big(ltx.Gas), ethutil.Big(ltx.GasPrice), ltx.Data) + tx := types.NewTransactionMessage(ltx.To, ethutil.Big(ltx.Value), ethutil.Big(ltx.Gas), ethutil.Big(ltx.GasPrice), ltx.Data) tx.Nonce = state.GetNonce(self.Coinbase) state.SetNonce(self.Coinbase, tx.Nonce+1) @@ -247,7 +248,7 @@ func (self *Miner) finiliseTxs() chain.Transactions { } txs = append(txs, self.eth.TxPool().CurrentTransactions()...) - sort.Sort(chain.TxByNonce{txs}) + sort.Sort(types.TxByNonce{txs}) return txs } diff --git a/peer.go b/peer.go index b54978854..fa73da21a 100644 --- a/peer.go +++ b/peer.go @@ -11,8 +11,7 @@ import ( "strings" "sync/atomic" "time" - - "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/wire" @@ -155,7 +154,7 @@ type Peer struct { pingTime time.Duration pingStartTime time.Time - lastRequestedBlock *chain.Block + lastRequestedBlock *types.Block protocolCaps *ethutil.Value } @@ -429,7 +428,7 @@ func (p *Peer) HandleInbound() { // in the TxPool where it will undergo validation and // processing when a new block is found for i := 0; i < msg.Data.Len(); i++ { - tx := chain.NewTransactionFromValue(msg.Data.Get(i)) + tx := types.NewTransactionFromValue(msg.Data.Get(i)) p.ethereum.TxPool().QueueTransaction(tx) } case wire.MsgGetPeersTy: @@ -535,7 +534,7 @@ func (p *Peer) HandleInbound() { it := msg.Data.NewIterator() for it.Next() { - block := chain.NewBlockFromRlpValue(it.Value()) + block := types.NewBlockFromRlpValue(it.Value()) blockPool.Add(block, p) p.lastBlockReceived = time.Now() @@ -543,7 +542,7 @@ func (p *Peer) HandleInbound() { case wire.MsgNewBlockTy: var ( blockPool = p.ethereum.blockPool - block = chain.NewBlockFromRlpValue(msg.Data.Get(0)) + block = types.NewBlockFromRlpValue(msg.Data.Get(0)) td = msg.Data.Get(1).BigInt() ) diff --git a/xeth/hexface.go b/xeth/hexface.go index 5ef3eaf1a..5bf9845d4 100644 --- a/xeth/hexface.go +++ b/xeth/hexface.go @@ -6,6 +6,7 @@ import ( "sync/atomic" "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" @@ -209,7 +210,7 @@ func (self *JSXEth) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr gas = ethutil.Big(gasStr) gasPrice = ethutil.Big(gasPriceStr) data []byte - tx *chain.Transaction + tx *types.Transaction ) if ethutil.IsHex(codeStr) { @@ -219,9 +220,9 @@ func (self *JSXEth) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr } if contractCreation { - tx = chain.NewContractCreationTx(value, gas, gasPrice, data) + tx = types.NewContractCreationTx(value, gas, gasPrice, data) } else { - tx = chain.NewTransactionMessage(hash, value, gas, gasPrice, data) + tx = types.NewTransactionMessage(hash, value, gas, gasPrice, data) } acc := self.obj.BlockManager().TransState().GetOrNewStateObject(keyPair.Address()) @@ -240,7 +241,7 @@ func (self *JSXEth) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr } func (self *JSXEth) PushTx(txStr string) (*JSReceipt, error) { - tx := chain.NewTransactionFromBytes(ethutil.Hex2Bytes(txStr)) + tx := types.NewTransactionFromBytes(ethutil.Hex2Bytes(txStr)) self.obj.TxPool().QueueTransaction(tx) return NewJSReciept(tx.CreatesContract(), tx.CreationAddress(self.World().State()), tx.Hash(), tx.Sender()), nil } diff --git a/xeth/js_types.go b/xeth/js_types.go index ff240e21c..cba674416 100644 --- a/xeth/js_types.go +++ b/xeth/js_types.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" @@ -14,7 +15,7 @@ import ( // Block interface exposed to QML type JSBlock struct { //Transactions string `json:"transactions"` - ref *chain.Block + ref *types.Block Size string `json:"size"` Number int `json:"number"` Hash string `json:"hash"` @@ -31,7 +32,7 @@ type JSBlock struct { } // Creates a new QML Block from a chain block -func NewJSBlock(block *chain.Block) *JSBlock { +func NewJSBlock(block *types.Block) *JSBlock { if block == nil { return &JSBlock{} } @@ -79,7 +80,7 @@ func (self *JSBlock) GetTransaction(hash string) *JSTransaction { } type JSTransaction struct { - ref *chain.Transaction + ref *types.Transaction Value string `json:"value"` Gas string `json:"gas"` @@ -94,7 +95,7 @@ type JSTransaction struct { Confirmations int `json:"confirmations"` } -func NewJSTx(tx *chain.Transaction, state *state.State) *JSTransaction { +func NewJSTx(tx *types.Transaction, state *state.State) *JSTransaction { hash := ethutil.Bytes2Hex(tx.Hash()) receiver := ethutil.Bytes2Hex(tx.Recipient) if receiver == "0000000000000000000000000000000000000000" { diff --git a/xeth/pipe.go b/xeth/pipe.go index abed8ef9a..8130ab72e 100644 --- a/xeth/pipe.go +++ b/xeth/pipe.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" @@ -72,7 +73,7 @@ func (self *XEth) ExecuteObject(object *Object, data []byte, value, gas, price * return ret, err } -func (self *XEth) Block(hash []byte) *chain.Block { +func (self *XEth) Block(hash []byte) *types.Block { return self.blockChain.GetBlock(hash) } @@ -115,7 +116,7 @@ func (self *XEth) Transact(key *crypto.KeyPair, rec []byte, value, gas, price *e contractCreation = true } - var tx *chain.Transaction + var tx *types.Transaction // Compile and assemble the given data if contractCreation { script, err := ethutil.Compile(string(data), false) @@ -123,7 +124,7 @@ func (self *XEth) Transact(key *crypto.KeyPair, rec []byte, value, gas, price *e return nil, err } - tx = chain.NewContractCreationTx(value.BigInt(), gas.BigInt(), price.BigInt(), script) + tx = types.NewContractCreationTx(value.BigInt(), gas.BigInt(), price.BigInt(), script) } else { data := ethutil.StringToByteFunc(string(data), func(s string) (ret []byte) { slice := strings.Split(s, "\n") @@ -134,7 +135,7 @@ func (self *XEth) Transact(key *crypto.KeyPair, rec []byte, value, gas, price *e return }) - tx = chain.NewTransactionMessage(hash, value.BigInt(), gas.BigInt(), price.BigInt(), data) + tx = types.NewTransactionMessage(hash, value.BigInt(), gas.BigInt(), price.BigInt(), data) } acc := self.blockManager.TransState().GetOrNewStateObject(key.Address()) @@ -155,7 +156,7 @@ func (self *XEth) Transact(key *crypto.KeyPair, rec []byte, value, gas, price *e return tx.Hash(), nil } -func (self *XEth) PushTx(tx *chain.Transaction) ([]byte, error) { +func (self *XEth) PushTx(tx *types.Transaction) ([]byte, error) { self.obj.TxPool().QueueTransaction(tx) if tx.Recipient == nil { addr := tx.CreationAddress(self.World().State()) diff --git a/xeth/vm_env.go b/xeth/vm_env.go index 68b13e5a8..10575ad79 100644 --- a/xeth/vm_env.go +++ b/xeth/vm_env.go @@ -2,20 +2,19 @@ package xeth import ( "math/big" - - "github.com/ethereum/go-ethereum/chain" + "github.com/ethereum/go-ethereum/chain/types" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/vm" ) type VMEnv struct { state *state.State - block *chain.Block + block *types.Block value *big.Int sender []byte } -func NewEnv(state *state.State, block *chain.Block, value *big.Int, sender []byte) *VMEnv { +func NewEnv(state *state.State, block *types.Block, value *big.Int, sender []byte) *VMEnv { return &VMEnv{ state: state, block: block, -- cgit v1.2.3