From f3e78c8f3cd2196ef70a41f298b6df556543d581 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 28 Jan 2015 10:23:18 +0100 Subject: reworking messages => log --- core/block_processor.go | 21 +++++++++ core/filter.go | 118 ++++++++++++++---------------------------------- 2 files changed, 56 insertions(+), 83 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index 37acc4f72..2dcaa37c2 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -330,3 +330,24 @@ func (sm *BlockProcessor) GetMessages(block *types.Block) (messages []*state.Mes return state.Manifest().Messages, nil } + +func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) { + if !sm.bc.HasBlock(block.Header().ParentHash) { + return nil, ParentError(block.Header().ParentHash) + } + + sm.lastAttemptedBlock = block + + var ( + parent = sm.bc.GetBlock(block.Header().ParentHash) + //state = state.New(parent.Trie().Copy()) + state = state.New(parent.Root(), sm.db) + ) + + defer state.Reset() + + sm.TransitionState(state, parent, block) + sm.AccumelateRewards(state, block, parent) + + return state.Logs(), nil +} diff --git a/core/filter.go b/core/filter.go index 29be8841c..efdd819ed 100644 --- a/core/filter.go +++ b/core/filter.go @@ -3,10 +3,8 @@ package core import ( "bytes" "math" - "math/big" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" ) @@ -20,13 +18,12 @@ type Filter struct { earliest int64 latest int64 skip int - from, to [][]byte + address []byte max int + topics [][]byte - Altered []AccountChange - - BlockCallback func(*types.Block) - MessageCallback func(state.Messages) + BlockCallback func(*types.Block) + LogsCallback func(state.Logs) } // Create a new filter which uses a bloom filter on blocks to figure out whether a particular block @@ -35,10 +32,6 @@ func NewFilter(eth EthManager) *Filter { return &Filter{eth: eth} } -func (self *Filter) AddAltered(address, stateAddress []byte) { - self.Altered = append(self.Altered, AccountChange{address, stateAddress}) -} - // Set the earliest and latest block for filtering. // -1 = latest block (i.e., the current block) // hash = particular hash from-to @@ -50,20 +43,12 @@ func (self *Filter) SetLatestBlock(latest int64) { self.latest = latest } -func (self *Filter) SetFrom(addr [][]byte) { - self.from = addr -} - -func (self *Filter) AddFrom(addr []byte) { - self.from = append(self.from, addr) -} - -func (self *Filter) SetTo(addr [][]byte) { - self.to = addr +func (self *Filter) SetAddress(addr []byte) { + self.address = addr } -func (self *Filter) AddTo(addr []byte) { - self.to = append(self.to, addr) +func (self *Filter) SetTopics(topics [][]byte) { + self.topics = topics } func (self *Filter) SetMax(max int) { @@ -74,8 +59,8 @@ func (self *Filter) SetSkip(skip int) { self.skip = skip } -// Run filters messages with the current parameters set -func (self *Filter) Find() []*state.Message { +// Run filters logs with the current parameters set +func (self *Filter) Find() state.Logs { earliestBlock := self.eth.ChainManager().CurrentBlock() var earliestBlockNo uint64 = uint64(self.earliest) if self.earliest == -1 { @@ -87,39 +72,39 @@ func (self *Filter) Find() []*state.Message { } var ( - messages []*state.Message - block = self.eth.ChainManager().GetBlockByNumber(latestBlockNo) - quit bool + logs state.Logs + block = self.eth.ChainManager().GetBlockByNumber(latestBlockNo) + quit bool ) for i := 0; !quit && block != nil; i++ { // Quit on latest switch { case block.NumberU64() == earliestBlockNo, block.NumberU64() == 0: quit = true - case self.max <= len(messages): + case self.max <= len(logs): break } // Use bloom filtering to see if this block is interesting given the // current parameters if self.bloomFilter(block) { - // Get the messages of the block - msgs, err := self.eth.BlockProcessor().GetMessages(block) + // Get the logs of the block + logs, err := self.eth.BlockProcessor().GetLogs(block) if err != nil { - chainlogger.Warnln("err: filter get messages ", err) + chainlogger.Warnln("err: filter get logs ", err) break } - messages = append(messages, self.FilterMessages(msgs)...) + logs = append(logs, self.FilterLogs(logs)...) } block = self.eth.ChainManager().GetBlock(block.ParentHash()) } - skip := int(math.Min(float64(len(messages)), float64(self.skip))) + skip := int(math.Min(float64(len(logs)), float64(self.skip))) - return messages[skip:] + return logs[skip:] } func includes(addresses [][]byte, a []byte) (found bool) { @@ -132,70 +117,37 @@ func includes(addresses [][]byte, a []byte) (found bool) { return } -func (self *Filter) FilterMessages(msgs []*state.Message) []*state.Message { - var messages []*state.Message +func (self *Filter) FilterLogs(logs state.Logs) state.Logs { + var ret state.Logs - // Filter the messages for interesting stuff - for _, message := range msgs { - if len(self.to) > 0 && !includes(self.to, message.To) { + // Filter the logs for interesting stuff + for _, log := range logs { + if len(self.address) > 0 && !bytes.Equal(self.address, log.Address()) { continue } - if len(self.from) > 0 && !includes(self.from, message.From) { - continue - } - - var match bool - if len(self.Altered) == 0 { - match = true - } - - for _, accountChange := range self.Altered { - if len(accountChange.Address) > 0 && bytes.Compare(message.To, accountChange.Address) != 0 { + for _, topic := range self.topics { + if !includes(log.Topics(), topic) { continue } - - if len(accountChange.StateAddress) > 0 && !includes(message.ChangedAddresses, accountChange.StateAddress) { - continue - } - - match = true - break - } - - if !match { - continue } - messages = append(messages, message) + ret = append(ret, log) } - return messages + return ret } 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.Bloom(), from) || bytes.Equal(block.Coinbase(), from) { - fromIncluded = true - break - } - } - } else { - fromIncluded = true + if len(self.address) > 0 && !types.BloomLookup(block.Bloom(), self.address) { + return false } - if len(self.to) > 0 { - for _, to := range self.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 - } + for _, topic := range self.topics { + if !types.BloomLookup(block.Bloom(), topic) { + return false } - } else { - toIncluded = true } - return fromIncluded && toIncluded + return true } -- cgit From 7f638f0b2d8d989be25e660178d79df3278e4c84 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 28 Jan 2015 18:14:28 +0100 Subject: moving to a better xeth --- core/genesis.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/genesis.go b/core/genesis.go index d9edaace2..6d4eeba72 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -34,7 +34,7 @@ func GenesisBlock(db ethutil.Database) *types.Block { statedb := state.New(genesis.Root(), db) //statedb := state.New(genesis.Trie()) for _, addr := range []string{ - "51ba59315b3a95761d0863b05ccc7a7f54703d99", + "dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6", "e4157b34ea9615cfbde6b4fda419828124b70c78", "b9c015918bdaba24b4ff057a92a3873d6eb201be", "6c386a4b26f73c802f34673f7248bb118f97424a", -- cgit From 3440a8a0bfd7fbb3fd04c034356700522dec9dd4 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 28 Jan 2015 21:12:26 +0100 Subject: changed lost key --- core/chain_manager.go | 8 +++++++- core/genesis.go | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index c68b7cfc2..9646bfc53 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -251,7 +251,13 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain // XXX Could be optimised by using a different database which only holds hashes (i.e., linked list) for i := uint64(0); i < max; i++ { - block = self.GetBlock(block.Header().ParentHash) + parentHash := block.Header().ParentHash + block = self.GetBlock(parentHash) + if block == nil { + chainlogger.Infof("GetBlockHashesFromHash Parent UNKNOWN %x\n", parentHash) + break + } + chain = append(chain, block.Hash()) if block.Header().Number.Cmp(ethutil.Big0) <= 0 { break diff --git a/core/genesis.go b/core/genesis.go index d9edaace2..6d4eeba72 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -34,7 +34,7 @@ func GenesisBlock(db ethutil.Database) *types.Block { statedb := state.New(genesis.Root(), db) //statedb := state.New(genesis.Trie()) for _, addr := range []string{ - "51ba59315b3a95761d0863b05ccc7a7f54703d99", + "dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6", "e4157b34ea9615cfbde6b4fda419828124b70c78", "b9c015918bdaba24b4ff057a92a3873d6eb201be", "6c386a4b26f73c802f34673f7248bb118f97424a", -- cgit From 6488a392a347d0d47212fdc78386e3e0e5841d7d Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 29 Jan 2015 16:52:00 +0100 Subject: Reimplemented message filters for rpc calls --- core/filter.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'core') diff --git a/core/filter.go b/core/filter.go index efdd819ed..d154e7b7a 100644 --- a/core/filter.go +++ b/core/filter.go @@ -12,6 +12,17 @@ type AccountChange struct { Address, StateAddress []byte } +type FilterOptions struct { + Earliest int64 + Latest int64 + + Address []byte + Topics [][]byte + + Skip int + Max int +} + // Filtering interface type Filter struct { eth EthManager @@ -32,6 +43,16 @@ func NewFilter(eth EthManager) *Filter { return &Filter{eth: eth} } +func (self *Filter) SetOptions(options FilterOptions) { + self.earliest = options.Earliest + self.latest = options.Latest + self.skip = options.Skip + self.max = options.Max + self.address = options.Address + self.topics = options.Topics + +} + // Set the earliest and latest block for filtering. // -1 = latest block (i.e., the current block) // hash = particular hash from-to -- cgit From cb382fa76ba30d213e4707d05bf3a00bc87dec9a Mon Sep 17 00:00:00 2001 From: obscuren Date: Sat, 31 Jan 2015 17:22:17 +0100 Subject: Validate transactions sender before adding to pool. Closes #272 --- core/transaction_pool.go | 20 +++++++++++++------- core/transaction_pool_test.go | 10 ++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) (limited to 'core') diff --git a/core/transaction_pool.go b/core/transaction_pool.go index d3aec9050..7a901fcae 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -1,6 +1,7 @@ package core import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/core/types" @@ -9,7 +10,11 @@ import ( "github.com/ethereum/go-ethereum/logger" ) -var txplogger = logger.NewLogger("TXP") +var ( + txplogger = logger.NewLogger("TXP") + + ErrInvalidSender = errors.New("Invalid sender") +) const txPoolQueueSize = 50 @@ -60,22 +65,23 @@ func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { return fmt.Errorf("Invalid recipient. len = %d", len(tx.To())) } + // Validate curve param v, _, _ := tx.Curve() if v > 28 || v < 27 { return fmt.Errorf("tx.v != (28 || 27) => %v", v) } + // Validate sender address + senderAddr := tx.From() + if senderAddr == nil || len(senderAddr) != 20 { + return ErrInvalidSender + } + /* XXX this kind of validation needs to happen elsewhere in the gui when sending txs. Other clients should do their own validation. Value transfer could throw error but doesn't necessarily invalidate the tx. Gas can still be payed for and miner can still be rewarded for their inclusion and processing. - // Get the sender - senderAddr := tx.From() - if senderAddr == nil { - return fmt.Errorf("invalid sender") - } sender := pool.stateQuery.GetAccount(senderAddr) - totAmount := new(big.Int).Set(tx.Value()) // Make sure there's enough in the sender's account. Having insufficient // funds won't invalidate this transaction but simple ignores it. diff --git a/core/transaction_pool_test.go b/core/transaction_pool_test.go index 7f192fc4d..b2d981f01 100644 --- a/core/transaction_pool_test.go +++ b/core/transaction_pool_test.go @@ -85,3 +85,13 @@ func TestRemoveInvalid(t *testing.T) { t.Error("expected pool size to be 1, is", pool.Size()) } } + +func TestInvalidSender(t *testing.T) { + pool, _ := setup() + tx := new(types.Transaction) + tx.V = 28 + err := pool.ValidateTransaction(tx) + if err != ErrInvalidSender { + t.Error("expected %v, got %v", ErrInvalidSender, err) + } +} -- cgit From 8ccde784f9035c0a7a8f234994538c817c5b9de7 Mon Sep 17 00:00:00 2001 From: obscuren Date: Sun, 1 Feb 2015 15:30:29 +0100 Subject: Added (disabled) Jit validation --- core/execution.go | 3 +-- core/state_transition.go | 25 +++++++++++++++++++++++++ core/vm_env.go | 4 ++++ 3 files changed, 30 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/execution.go b/core/execution.go index cad4e84aa..5e0cbd37e 100644 --- a/core/execution.go +++ b/core/execution.go @@ -33,8 +33,7 @@ func (self *Execution) Call(codeAddr []byte, caller vm.ContextRef) ([]byte, erro func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret []byte, err error) { env := self.env - evm := vm.New(env) - + evm := vm.NewVm(env) if env.Depth() == vm.MaxCallDepth { caller.ReturnGas(self.Gas, self.price) diff --git a/core/state_transition.go b/core/state_transition.go index 8b0ca2ac4..00d9d486a 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -10,6 +10,8 @@ import ( "github.com/ethereum/go-ethereum/vm" ) +const tryJit = false + /* * The State transitioning model * @@ -184,6 +186,7 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) { return } + stateCopy := self.env.State().Copy() vmenv := self.env var ref vm.ContextRef if MessageCreatesContract(msg) { @@ -196,8 +199,30 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) { ref.SetCode(ret) } } + + if vmenv, ok := vmenv.(*VMEnv); ok && tryJit { + statelogger.Infof("CREATE: re-running using JIT (PH=%x)\n", stateCopy.Root()[:4]) + // re-run using the JIT (validation for the JIT) + goodState := vmenv.State().Copy() + vmenv.state = stateCopy + vmenv.SetVmType(vm.JitVmTy) + vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) + statelogger.Infof("DONE PH=%x STD_H=%x JIT_H=%x\n", stateCopy.Root()[:4], goodState.Root()[:4], vmenv.State().Root()[:4]) + self.state.Set(goodState) + } } else { ret, err = vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) + + if vmenv, ok := vmenv.(*VMEnv); ok && tryJit { + statelogger.Infof("CALL: re-running using JIT (PH=%x)\n", stateCopy.Root()[:4]) + // re-run using the JIT (validation for the JIT) + goodState := vmenv.State().Copy() + vmenv.state = stateCopy + vmenv.SetVmType(vm.JitVmTy) + vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) + statelogger.Infof("DONE PH=%x STD_H=%x JIT_H=%x\n", stateCopy.Root()[:4], goodState.Root()[:4], vmenv.State().Root()[:4]) + self.state.Set(goodState) + } } if err != nil { diff --git a/core/vm_env.go b/core/vm_env.go index 624a63333..c7491bcdc 100644 --- a/core/vm_env.go +++ b/core/vm_env.go @@ -14,6 +14,7 @@ type VMEnv struct { msg Message depth int chain *ChainManager + typ vm.Type } func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types.Block) *VMEnv { @@ -22,6 +23,7 @@ func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types state: state, block: block, msg: msg, + typ: vm.StdVmTy, } } @@ -35,6 +37,8 @@ func (self *VMEnv) Value() *big.Int { return self.msg.Value() } func (self *VMEnv) State() *state.StateDB { return self.state } func (self *VMEnv) Depth() int { return self.depth } func (self *VMEnv) SetDepth(i int) { self.depth = i } +func (self *VMEnv) VmType() vm.Type { return self.typ } +func (self *VMEnv) SetVmType(t vm.Type) { self.typ = t } func (self *VMEnv) GetHash(n uint64) []byte { if block := self.chain.GetBlockByNumber(n); block != nil { return block.Hash() -- cgit From 30fa30bd4a5f12e86480bec0a7dd2fe290c9abc4 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 2 Feb 2015 20:02:00 -0800 Subject: Docs & old code removed --- core/block_processor.go | 2 +- core/genesis.go | 1 - core/state_transition.go | 46 +++++++++++++++++++++++++--------------------- 3 files changed, 26 insertions(+), 23 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index 2dcaa37c2..4d5cd94c9 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -219,7 +219,7 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big // Calculate the td for this block td = CalculateTD(block, parent) - // Sync the current block's state to the database and cancelling out the deferred Undo + // Sync the current block's state to the database state.Sync() // Set the block hashes for the current messages state.Manifest().SetHash(block.Hash()) diff --git a/core/genesis.go b/core/genesis.go index 6d4eeba72..c870ce61e 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -32,7 +32,6 @@ func GenesisBlock(db ethutil.Database) *types.Block { genesis.SetReceipts(types.Receipts{}) statedb := state.New(genesis.Root(), db) - //statedb := state.New(genesis.Trie()) for _, addr := range []string{ "dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6", "e4157b34ea9615cfbde6b4fda419828124b70c78", diff --git a/core/state_transition.go b/core/state_transition.go index 00d9d486a..33dd45f02 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -186,7 +186,7 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) { return } - stateCopy := self.env.State().Copy() + //stateCopy := self.env.State().Copy() vmenv := self.env var ref vm.ContextRef if MessageCreatesContract(msg) { @@ -200,29 +200,33 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) { } } - if vmenv, ok := vmenv.(*VMEnv); ok && tryJit { - statelogger.Infof("CREATE: re-running using JIT (PH=%x)\n", stateCopy.Root()[:4]) - // re-run using the JIT (validation for the JIT) - goodState := vmenv.State().Copy() - vmenv.state = stateCopy - vmenv.SetVmType(vm.JitVmTy) - vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) - statelogger.Infof("DONE PH=%x STD_H=%x JIT_H=%x\n", stateCopy.Root()[:4], goodState.Root()[:4], vmenv.State().Root()[:4]) - self.state.Set(goodState) - } + /* + if vmenv, ok := vmenv.(*VMEnv); ok && tryJit { + statelogger.Infof("CREATE: re-running using JIT (PH=%x)\n", stateCopy.Root()[:4]) + // re-run using the JIT (validation for the JIT) + goodState := vmenv.State().Copy() + vmenv.state = stateCopy + vmenv.SetVmType(vm.JitVmTy) + vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) + statelogger.Infof("DONE PH=%x STD_H=%x JIT_H=%x\n", stateCopy.Root()[:4], goodState.Root()[:4], vmenv.State().Root()[:4]) + self.state.Set(goodState) + } + */ } else { ret, err = vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) - if vmenv, ok := vmenv.(*VMEnv); ok && tryJit { - statelogger.Infof("CALL: re-running using JIT (PH=%x)\n", stateCopy.Root()[:4]) - // re-run using the JIT (validation for the JIT) - goodState := vmenv.State().Copy() - vmenv.state = stateCopy - vmenv.SetVmType(vm.JitVmTy) - vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) - statelogger.Infof("DONE PH=%x STD_H=%x JIT_H=%x\n", stateCopy.Root()[:4], goodState.Root()[:4], vmenv.State().Root()[:4]) - self.state.Set(goodState) - } + /* + if vmenv, ok := vmenv.(*VMEnv); ok && tryJit { + statelogger.Infof("CALL: re-running using JIT (PH=%x)\n", stateCopy.Root()[:4]) + // re-run using the JIT (validation for the JIT) + goodState := vmenv.State().Copy() + vmenv.state = stateCopy + vmenv.SetVmType(vm.JitVmTy) + vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) + statelogger.Infof("DONE PH=%x STD_H=%x JIT_H=%x\n", stateCopy.Root()[:4], goodState.Root()[:4], vmenv.State().Root()[:4]) + self.state.Set(goodState) + } + */ } if err != nil { -- cgit From 697c2b5dc16653228c5264d01c08163cebda3aeb Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Tue, 3 Feb 2015 23:09:39 +0100 Subject: Correct block parent timestamp check and typos --- core/block_processor.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index 4d5cd94c9..60d73e390 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -206,7 +206,7 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big return } - if err = sm.AccumelateRewards(state, block, parent); err != nil { + if err = sm.AccumulateRewards(state, block, parent); err != nil { return } @@ -248,8 +248,8 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { } diff := block.Header().Time - parent.Header().Time - if diff < 0 { - return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Header().Time, sm.bc.CurrentBlock().Header().Time) + if diff <= 0 { + return ValidationError("Block timestamp not after prev block %v (%v - %v)", diff, block.Header().Time, sm.bc.CurrentBlock().Header().Time) } if block.Time() > time.Now().Unix() { @@ -264,7 +264,7 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { return nil } -func (sm *BlockProcessor) AccumelateRewards(statedb *state.StateDB, block, parent *types.Block) error { +func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, parent *types.Block) error { reward := new(big.Int).Set(BlockReward) ancestors := set.New() @@ -326,7 +326,7 @@ func (sm *BlockProcessor) GetMessages(block *types.Block) (messages []*state.Mes defer state.Reset() sm.TransitionState(state, parent, block) - sm.AccumelateRewards(state, block, parent) + sm.AccumulateRewards(state, block, parent) return state.Manifest().Messages, nil } @@ -347,7 +347,7 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro defer state.Reset() sm.TransitionState(state, parent, block) - sm.AccumelateRewards(state, block, parent) + sm.AccumulateRewards(state, block, parent) return state.Logs(), nil } -- cgit From b1870631a4829e075eae77064973ef94aa2166b3 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 4 Feb 2015 05:52:59 -0800 Subject: WIP miner --- core/block_processor.go | 74 ++++++++++++++++++++++++------------------------- core/types/block.go | 26 +++++++++-------- 2 files changed, 52 insertions(+), 48 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index 4d5cd94c9..20a651e84 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -84,6 +84,35 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block return receipts, nil } +func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, state *state.StateDB, block *types.Block, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) { + // If we are mining this block and validating we want to set the logs back to 0 + state.EmptyLogs() + + txGas := new(big.Int).Set(tx.Gas()) + + cb := state.GetStateObject(coinbase.Address()) + st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb) + _, err := st.TransitionState() + + txGas.Sub(txGas, st.gas) + + // Update the state with pending changes + state.Update(txGas) + + cumulative := new(big.Int).Set(usedGas.Add(usedGas, txGas)) + receipt := types.NewReceipt(state.Root(), cumulative) + receipt.SetLogs(state.Logs()) + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + chainlogger.Debugln(receipt) + + // Notify all subscribers + if !transientProcess { + go self.eventMux.Post(TxPostEvent{tx}) + } + + return receipt, txGas, err +} + func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) { var ( receipts types.Receipts @@ -96,15 +125,10 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state done: for i, tx := range txs { - // If we are mining this block and validating we want to set the logs back to 0 - state.EmptyLogs() - - txGas := new(big.Int).Set(tx.Gas()) - - cb := state.GetStateObject(coinbase.Address()) - st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb) - _, err = st.TransitionState() + receipt, txGas, err := self.ApplyTransaction(coinbase, state, block, tx, totalUsedGas, transientProcess) if err != nil { + return nil, nil, nil, nil, err + switch { case IsNonceErr(err): err = nil // ignore error @@ -119,30 +143,10 @@ done: err = nil } } - - txGas.Sub(txGas, st.gas) - cumulativeSum.Add(cumulativeSum, new(big.Int).Mul(txGas, tx.GasPrice())) - - // Update the state with pending changes - state.Update(txGas) - - cumulative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas)) - receipt := types.NewReceipt(state.Root(), cumulative) - receipt.SetLogs(state.Logs()) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - chainlogger.Debugln(receipt) - - // Notify all subscribers - if !transientProcess { - go self.eventMux.Post(TxPostEvent{tx}) - } - receipts = append(receipts, receipt) handled = append(handled, tx) - if ethutil.Config.Diff && ethutil.Config.DiffType == "all" { - state.CreateOutputForDiff() - } + cumulativeSum.Add(cumulativeSum, new(big.Int).Mul(txGas, tx.GasPrice())) } block.Reward = cumulativeSum @@ -285,6 +289,10 @@ func (sm *BlockProcessor) AccumelateRewards(statedb *state.StateDB, block, paren return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) } + if !sm.Pow.Verify(types.NewBlockWithHeader(uncle)) { + return ValidationError("Uncle's nonce is invalid (= %v)", ethutil.Bytes2Hex(uncle.Nonce)) + } + r := new(big.Int) r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16)) @@ -299,14 +307,6 @@ func (sm *BlockProcessor) AccumelateRewards(statedb *state.StateDB, block, paren // Reward amount of ether to the coinbase address account.AddAmount(reward) - statedb.Manifest().AddMessage(&state.Message{ - To: block.Header().Coinbase, - Input: nil, - Origin: nil, - Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number, - Value: new(big.Int).Add(reward, block.Reward), - }) - return nil } diff --git a/core/types/block.go b/core/types/block.go index be57e86a6..a334c512e 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -6,7 +6,6 @@ import ( "math/big" "sort" "time" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/rlp" @@ -146,6 +145,10 @@ func (self *Block) SetTransactions(transactions Transactions) { self.transactions = transactions self.header.TxHash = DeriveSha(transactions) } +func (self *Block) AddTransaction(transaction *Transaction) { + self.transactions = append(self.transactions, transaction) + self.SetTransactions(self.transactions) +} func (self *Block) Receipts() Receipts { return self.receipts @@ -156,6 +159,10 @@ func (self *Block) SetReceipts(receipts Receipts) { self.header.ReceiptHash = DeriveSha(receipts) self.header.Bloom = CreateBloom(receipts) } +func (self *Block) AddReceipt(receipt *Receipt) { + self.receipts = append(self.receipts, receipt) + self.SetReceipts(self.receipts) +} func (self *Block) RlpData() interface{} { return []interface{}{self.header, self.transactions, self.uncles} @@ -166,16 +173,13 @@ func (self *Block) RlpDataForStorage() interface{} { } // 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) 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) Trie() *ptrie.Trie { return ptrie.New(self.header.Root, ethutil.Config.Db) } -//func (self *Block) State() *state.StateDB { return state.New(self.Trie()) } +func (self *Block) Number() *big.Int { return self.header.Number } +func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() } +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) Root() []byte { return self.header.Root } func (self *Block) SetRoot(root []byte) { self.header.Root = root } func (self *Block) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) } -- cgit From 65158d39b0632226c168b9a3415365ca8f072cbf Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 4 Feb 2015 15:05:47 -0800 Subject: Filtering --- core/block_processor.go | 13 +++++++------ core/chain_manager.go | 3 +-- core/filter.go | 7 +++++++ core/types/common.go | 8 ++------ 4 files changed, 17 insertions(+), 14 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index 20a651e84..d59d7feca 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -110,6 +110,8 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, state go self.eventMux.Post(TxPostEvent{tx}) } + go self.eventMux.Post(state.Logs()) + return receipt, txGas, err } @@ -155,25 +157,25 @@ done: return receipts, handled, unhandled, erroneous, err } -func (sm *BlockProcessor) Process(block *types.Block) (td *big.Int, msgs state.Messages, err error) { +func (sm *BlockProcessor) Process(block *types.Block) (td *big.Int, err error) { // Processing a blocks may never happen simultaneously sm.mutex.Lock() defer sm.mutex.Unlock() header := block.Header() if sm.bc.HasBlock(header.Hash()) { - return nil, nil, &KnownBlockError{header.Number, header.Hash()} + return nil, &KnownBlockError{header.Number, header.Hash()} } if !sm.bc.HasBlock(header.ParentHash) { - return nil, nil, ParentError(header.ParentHash) + return nil, ParentError(header.ParentHash) } parent := sm.bc.GetBlock(header.ParentHash) return sm.ProcessWithParent(block, parent) } -func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big.Int, messages state.Messages, err error) { +func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big.Int, err error) { sm.lastAttemptedBlock = block state := state.New(parent.Root(), sm.db) @@ -227,7 +229,6 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big state.Sync() // Set the block hashes for the current messages state.Manifest().SetHash(block.Hash()) - messages = state.Manifest().Messages // Reset the manifest XXX We need this? state.Manifest().Reset() // Remove transactions from the pool @@ -235,7 +236,7 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big chainlogger.Infof("processed block #%d (%x...)\n", header.Number, block.Hash()[0:4]) - return td, messages, nil + return td, nil } // Validates the current block. Returns an error if the block was invalid, diff --git a/core/chain_manager.go b/core/chain_manager.go index 9646bfc53..0847980ca 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -359,7 +359,7 @@ func (bc *ChainManager) Stop() { func (self *ChainManager) InsertChain(chain types.Blocks) error { for _, block := range chain { - td, messages, err := self.processor.Process(block) + td, err := self.processor.Process(block) if err != nil { if IsKnownBlockErr(err) { continue @@ -391,7 +391,6 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { self.mu.Unlock() self.eventMux.Post(NewBlockEvent{block}) - self.eventMux.Post(messages) } return nil diff --git a/core/filter.go b/core/filter.go index d154e7b7a..a458165f5 100644 --- a/core/filter.go +++ b/core/filter.go @@ -2,6 +2,7 @@ package core import ( "bytes" + "fmt" "math" "github.com/ethereum/go-ethereum/core/types" @@ -130,6 +131,7 @@ func (self *Filter) Find() state.Logs { func includes(addresses [][]byte, a []byte) (found bool) { for _, addr := range addresses { + fmt.Println("INCLUDES", addr, a) if bytes.Compare(addr, a) == 0 { return true } @@ -139,20 +141,25 @@ func includes(addresses [][]byte, a []byte) (found bool) { } func (self *Filter) FilterLogs(logs state.Logs) state.Logs { + fmt.Println("FILTER LOGS", self.topics) var ret state.Logs // Filter the logs for interesting stuff for _, log := range logs { + fmt.Println(log) + if len(self.address) > 0 && !bytes.Equal(self.address, log.Address()) { continue } for _, topic := range self.topics { + fmt.Println("TOPIC:", topic) if !includes(log.Topics(), topic) { continue } } + fmt.Println("APPENDED") ret = append(ret, log) } diff --git a/core/types/common.go b/core/types/common.go index ba88b77e1..795374959 100644 --- a/core/types/common.go +++ b/core/types/common.go @@ -1,11 +1,7 @@ package types -import ( - "math/big" - - "github.com/ethereum/go-ethereum/state" -) +import "math/big" type BlockProcessor interface { - Process(*Block) (*big.Int, state.Messages, error) + Process(*Block) (*big.Int, error) } -- cgit From 1d519854e2bfe8d5f2e8674f4f04ccf9aeaabe84 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 4 Feb 2015 17:28:54 -0800 Subject: Propagate known transactions to new peers on connect --- core/filter.go | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'core') diff --git a/core/filter.go b/core/filter.go index a458165f5..c22996d7e 100644 --- a/core/filter.go +++ b/core/filter.go @@ -2,7 +2,6 @@ package core import ( "bytes" - "fmt" "math" "github.com/ethereum/go-ethereum/core/types" @@ -129,37 +128,33 @@ func (self *Filter) Find() state.Logs { return logs[skip:] } -func includes(addresses [][]byte, a []byte) (found bool) { +func includes(addresses [][]byte, a []byte) bool { for _, addr := range addresses { - fmt.Println("INCLUDES", addr, a) - if bytes.Compare(addr, a) == 0 { - return true + if !bytes.Equal(addr, a) { + return false } } - return + return true } func (self *Filter) FilterLogs(logs state.Logs) state.Logs { - fmt.Println("FILTER LOGS", self.topics) var ret state.Logs // Filter the logs for interesting stuff +Logs: for _, log := range logs { - fmt.Println(log) - if len(self.address) > 0 && !bytes.Equal(self.address, log.Address()) { continue } - for _, topic := range self.topics { - fmt.Println("TOPIC:", topic) - if !includes(log.Topics(), topic) { - continue + max := int(math.Min(float64(len(self.topics)), float64(len(log.Topics())))) + for i := 0; i < max; i++ { + if !bytes.Equal(log.Topics()[i], self.topics[i]) { + continue Logs } } - fmt.Println("APPENDED") ret = append(ret, log) } -- cgit From c64852dbccd0c8eb57cab994aefd0243c65b351b Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 5 Feb 2015 11:55:03 -0800 Subject: pending / chain event --- core/block_processor.go | 8 ++++++++ core/filter.go | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index d59d7feca..349de85e0 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -19,6 +19,10 @@ import ( "gopkg.in/fatih/set.v0" ) +type PendingBlockEvent struct { + Block *types.Block +} + var statelogger = logger.NewLogger("BLOCK") type EthManager interface { @@ -154,6 +158,10 @@ done: block.Reward = cumulativeSum block.Header().GasUsed = totalUsedGas + if transientProcess { + go self.eventMux.Post(PendingBlockEvent{block}) + } + return receipts, handled, unhandled, erroneous, err } diff --git a/core/filter.go b/core/filter.go index c22996d7e..24d1f5a4a 100644 --- a/core/filter.go +++ b/core/filter.go @@ -33,8 +33,9 @@ type Filter struct { max int topics [][]byte - BlockCallback func(*types.Block) - LogsCallback func(state.Logs) + BlockCallback func(*types.Block) + PendingCallback func(*types.Block) + LogsCallback func(state.Logs) } // Create a new filter which uses a bloom filter on blocks to figure out whether a particular block -- cgit From f8c1eb157d6025c16c808fad01d5b32dccd8e2f1 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 5 Feb 2015 14:42:12 -0800 Subject: Undone fix. Will re-enable once chain resets --- core/block_processor.go | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index e3f764616..6db3c25f5 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -129,20 +129,14 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state cumulativeSum = new(big.Int) ) -done: - for i, tx := range txs { + for _, tx := range txs { receipt, txGas, err := self.ApplyTransaction(coinbase, state, block, tx, totalUsedGas, transientProcess) if err != nil { - return nil, nil, nil, nil, err - switch { case IsNonceErr(err): - err = nil // ignore error - continue + return nil, nil, nil, nil, err case IsGasLimitErr(err): - unhandled = txs[i:] - - break done + return nil, nil, nil, nil, err default: statelogger.Infoln(err) erroneous = append(erroneous, tx) @@ -260,9 +254,8 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd) } - diff := block.Header().Time - parent.Header().Time - if diff <= 0 { - return ValidationError("Block timestamp not after prev block %v (%v - %v)", diff, block.Header().Time, sm.bc.CurrentBlock().Header().Time) + if block.Time() < parent.Time() { + return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time) } if block.Time() > time.Now().Unix() { -- cgit From 56f777b2fc77275bc636562b66a08b19afe2ec56 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 5 Feb 2015 03:16:16 +0100 Subject: cmd/ethereum, cmd/mist, core, eth, javascript, xeth: fixes for new p2p API --- core/block_processor.go | 1 - core/helper_test.go | 8 -------- 2 files changed, 9 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index 6db3c25f5..e6d4a1cda 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -34,7 +34,6 @@ type EthManager interface { IsListening() bool Peers() []*p2p.Peer KeyManager() *crypto.KeyManager - ClientIdentity() p2p.ClientIdentity Db() ethutil.Database EventMux() *event.TypeMux } diff --git a/core/helper_test.go b/core/helper_test.go index 7b41b86f1..473576e3f 100644 --- a/core/helper_test.go +++ b/core/helper_test.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/p2p" ) // Implement our EthTest Manager @@ -54,13 +53,6 @@ func (tm *TestManager) TxPool() *TxPool { func (tm *TestManager) EventMux() *event.TypeMux { return tm.eventMux } -func (tm *TestManager) Broadcast(msgType p2p.Msg, data []interface{}) { - fmt.Println("Broadcast not implemented") -} - -func (tm *TestManager) ClientIdentity() p2p.ClientIdentity { - return nil -} func (tm *TestManager) KeyManager() *crypto.KeyManager { return nil } -- cgit From c8147fb7b9e4bf349c47a1e4620e1b79cbeb7f7a Mon Sep 17 00:00:00 2001 From: obscuren Date: Sat, 7 Feb 2015 17:04:04 +0100 Subject: Compare regardless of length --- core/filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/filter.go b/core/filter.go index 24d1f5a4a..b93fcc8a5 100644 --- a/core/filter.go +++ b/core/filter.go @@ -145,7 +145,7 @@ func (self *Filter) FilterLogs(logs state.Logs) state.Logs { // Filter the logs for interesting stuff Logs: for _, log := range logs { - if len(self.address) > 0 && !bytes.Equal(self.address, log.Address()) { + if !bytes.Equal(self.address, log.Address()) { continue } -- cgit From 58ba290a9f22d954fcc9a8544b992989121db3df Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 9 Feb 2015 00:08:28 +0100 Subject: moved manager --- core/block_processor.go | 16 ---------------- core/manager.go | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 core/manager.go (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index 6db3c25f5..0eb3f8920 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -8,11 +8,9 @@ import ( "time" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" - "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/pow/ezp" "github.com/ethereum/go-ethereum/state" @@ -25,20 +23,6 @@ type PendingBlockEvent struct { var statelogger = logger.NewLogger("BLOCK") -type EthManager interface { - BlockProcessor() *BlockProcessor - ChainManager() *ChainManager - TxPool() *TxPool - PeerCount() int - IsMining() bool - IsListening() bool - Peers() []*p2p.Peer - KeyManager() *crypto.KeyManager - ClientIdentity() p2p.ClientIdentity - Db() ethutil.Database - EventMux() *event.TypeMux -} - type BlockProcessor struct { db ethutil.Database // Mutex for locking the block processor. Blocks can only be handled one at a time diff --git a/core/manager.go b/core/manager.go new file mode 100644 index 000000000..4671573b1 --- /dev/null +++ b/core/manager.go @@ -0,0 +1,22 @@ +package core + +import ( + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/p2p" +) + +type EthManager interface { + BlockProcessor() *BlockProcessor + ChainManager() *ChainManager + TxPool() *TxPool + PeerCount() int + IsMining() bool + IsListening() bool + Peers() []*p2p.Peer + KeyManager() *crypto.KeyManager + ClientIdentity() p2p.ClientIdentity + Db() ethutil.Database + EventMux() *event.TypeMux +} -- cgit From da2fae0e437f9467a943acfe0571a8a24e8e76fd Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 9 Feb 2015 16:20:34 +0100 Subject: Basic structure miner --- core/block_processor.go | 10 +++++----- core/chain_manager.go | 11 ++++++++++- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index d6755e7f7..8c4e53813 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -7,7 +7,6 @@ import ( "sync" "time" - "github.com/ethereum/c-ethash/go-ethash" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" @@ -15,7 +14,7 @@ import ( "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/pow" - _ "github.com/ethereum/go-ethereum/pow/ezp" + "github.com/ethereum/go-ethereum/pow/ezp" "github.com/ethereum/go-ethereum/state" "gopkg.in/fatih/set.v0" ) @@ -65,9 +64,10 @@ type BlockProcessor struct { func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor { sm := &BlockProcessor{ - db: db, - mem: make(map[string]*big.Int), - Pow: ðash.Ethash{}, + db: db, + mem: make(map[string]*big.Int), + //Pow: ðash.Ethash{}, + Pow: ezp.New(), bc: chainManager, eventMux: eventMux, txpool: txpool, diff --git a/core/chain_manager.go b/core/chain_manager.go index 0847980ca..308e958fe 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -16,6 +16,11 @@ import ( var chainlogger = logger.NewLogger("CHAIN") +type ChainEvent struct { + Block *types.Block + Td *big.Int +} + type StateQuery interface { GetAccount(addr []byte) *state.StateObject } @@ -175,6 +180,9 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block { ethutil.BigPow(2, 32), nil, "") + block.SetUncles(nil) + block.SetTransactions(nil) + block.SetReceipts(nil) parent := bc.currentBlock if parent != nil { @@ -385,8 +393,9 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { self.setTotalDifficulty(td) self.insert(block) self.transState = state.New(cblock.Root(), self.db) //state.New(cblock.Trie().Copy()) - } + self.eventMux.Post(ChainEvent{block, td}) + } } self.mu.Unlock() -- cgit From 3f6baa45a7fb1ae5fd7966d2763a2a776a65eb96 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 11 Feb 2015 23:46:45 +0100 Subject: Documented methods & removed old manifest --- core/block_processor.go | 43 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index 0eb3f8920..c360273da 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -143,6 +143,9 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state return receipts, handled, unhandled, erroneous, err } +// Process block will attempt to process the given block's transactions and applies them +// on top of the block's parent state (given it exists) and will return wether it was +// successful or not. func (sm *BlockProcessor) Process(block *types.Block) (td *big.Int, err error) { // Processing a blocks may never happen simultaneously sm.mutex.Lock() @@ -158,14 +161,14 @@ func (sm *BlockProcessor) Process(block *types.Block) (td *big.Int, err error) { } parent := sm.bc.GetBlock(header.ParentHash) - return sm.ProcessWithParent(block, parent) + return sm.processWithParent(block, parent) } -func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big.Int, err error) { +func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big.Int, err error) { sm.lastAttemptedBlock = block + // Create a new state based on the parent's root (e.g., create copy) state := state.New(parent.Root(), sm.db) - //state := state.New(parent.Trie().Copy()) // Block validation if err = sm.ValidateBlock(block, parent); err != nil { @@ -179,18 +182,23 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big header := block.Header() + // Validate the received block's bloom with the one derived from the generated receipts. + // For valid blocks this should always validate to true. rbloom := types.CreateBloom(receipts) if bytes.Compare(rbloom, header.Bloom) != 0 { err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom) return } + // The transactions Trie's root (R = (Tr [[H1, T1], [H2, T2], ... [Hn, Tn]])) + // can be used by light clients to make sure they've received the correct Txs txSha := types.DeriveSha(block.Transactions()) if bytes.Compare(txSha, header.TxHash) != 0 { err = fmt.Errorf("validating transaction root. received=%x got=%x", header.TxHash, txSha) return } + // Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]])) receiptSha := types.DeriveSha(receipts) if bytes.Compare(receiptSha, header.ReceiptHash) != 0 { fmt.Println("receipts", receipts) @@ -198,12 +206,14 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big return } + // Accumulate static rewards; block reward, uncle's and uncle inclusion. if err = sm.AccumulateRewards(state, block, parent); err != nil { return } + // Commit state objects/accounts to a temporary trie (does not save) + // used to calculate the state root. state.Update(ethutil.Big0) - if !bytes.Equal(header.Root, state.Root()) { err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root()) return @@ -213,10 +223,6 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big td = CalculateTD(block, parent) // Sync the current block's state to the database state.Sync() - // Set the block hashes for the current messages - state.Manifest().SetHash(block.Hash()) - // Reset the manifest XXX We need this? - state.Manifest().Reset() // Remove transactions from the pool sm.txpool.RemoveSet(block.Transactions()) @@ -296,27 +302,6 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren return nil } -func (sm *BlockProcessor) GetMessages(block *types.Block) (messages []*state.Message, err error) { - if !sm.bc.HasBlock(block.Header().ParentHash) { - return nil, ParentError(block.Header().ParentHash) - } - - sm.lastAttemptedBlock = block - - var ( - parent = sm.bc.GetBlock(block.Header().ParentHash) - //state = state.New(parent.Trie().Copy()) - state = state.New(parent.Root(), sm.db) - ) - - defer state.Reset() - - sm.TransitionState(state, parent, block) - sm.AccumulateRewards(state, block, parent) - - return state.Manifest().Messages, nil -} - func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) { if !sm.bc.HasBlock(block.Header().ParentHash) { return nil, ParentError(block.Header().ParentHash) -- cgit From bde3ff16ad98cb4ab0befc899f7f0584d21ff9a4 Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 13 Feb 2015 16:02:37 +0100 Subject: merge --- core/block_processor.go | 13 ------------- core/manager.go | 1 - 2 files changed, 14 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index 8f5ee52b7..c360273da 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -23,19 +23,6 @@ type PendingBlockEvent struct { var statelogger = logger.NewLogger("BLOCK") -type EthManager interface { - BlockProcessor() *BlockProcessor - ChainManager() *ChainManager - TxPool() *TxPool - PeerCount() int - IsMining() bool - IsListening() bool - Peers() []*p2p.Peer - KeyManager() *crypto.KeyManager - Db() ethutil.Database - EventMux() *event.TypeMux -} - type BlockProcessor struct { db ethutil.Database // Mutex for locking the block processor. Blocks can only be handled one at a time diff --git a/core/manager.go b/core/manager.go index 4671573b1..f960fc5f0 100644 --- a/core/manager.go +++ b/core/manager.go @@ -16,7 +16,6 @@ type EthManager interface { IsListening() bool Peers() []*p2p.Peer KeyManager() *crypto.KeyManager - ClientIdentity() p2p.ClientIdentity Db() ethutil.Database EventMux() *event.TypeMux } -- cgit From ce239333d529898edd8333637fd75c565e80a9ff Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 13 Feb 2015 18:15:23 +0100 Subject: Update balance label when mining --- core/types/block.go | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core') diff --git a/core/types/block.go b/core/types/block.go index a334c512e..562a21239 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -6,6 +6,7 @@ import ( "math/big" "sort" "time" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/rlp" @@ -175,6 +176,7 @@ func (self *Block) RlpDataForStorage() interface{} { // 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) Nonce() []byte { return self.header.Nonce } 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) } -- cgit From 32c7ebc51dcb31f21efe1b9c75f2b86cd216f510 Mon Sep 17 00:00:00 2001 From: obscuren Date: Sat, 14 Feb 2015 16:52:14 +0100 Subject: Fixed mining & limited hash power --- core/types/block.go | 3 ++- core/types/receipt.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/types/block.go b/core/types/block.go index 562a21239..fa28f5cc7 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -209,6 +209,7 @@ func (self *Block) ParentHash() []byte { func (self *Block) String() string { return fmt.Sprintf(`BLOCK(%x): Size: %v TD: %v { +NoNonce: %x Header: [ %v @@ -218,7 +219,7 @@ Transactions: Uncles: %v } -`, self.header.Hash(), self.Size(), self.Td, self.header, self.transactions, self.uncles) +`, self.header.Hash(), self.Size(), self.Td, self.header.HashNoNonce(), self.header, self.transactions, self.uncles) } func (self *Header) String() string { diff --git a/core/types/receipt.go b/core/types/receipt.go index bac64e41d..49e68e233 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -17,7 +17,7 @@ type Receipt struct { } func NewReceipt(root []byte, cumalativeGasUsed *big.Int) *Receipt { - return &Receipt{PostState: ethutil.CopyBytes(root), CumulativeGasUsed: cumalativeGasUsed} + return &Receipt{PostState: ethutil.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumalativeGasUsed)} } func NewRecieptFromValue(val *ethutil.Value) *Receipt { -- cgit From b143dad596f4230d74dadd3c5060020bd50ef7f3 Mon Sep 17 00:00:00 2001 From: obscuren Date: Sun, 15 Feb 2015 02:09:57 +0100 Subject: Reference pointer to block instead of pointer to function --- core/chain_manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index 308e958fe..54f1ced8c 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -168,7 +168,7 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block { var root []byte parentHash := ZeroHash256 - if bc.CurrentBlock != nil { + if bc.currentBlock != nil { root = bc.currentBlock.Header().Root parentHash = bc.lastBlockHash } -- cgit From 2c3a014f03390628d329167109f90a30e3c4e4c3 Mon Sep 17 00:00:00 2001 From: obscuren Date: Sun, 15 Feb 2015 16:16:27 +0100 Subject: Resolved some bugs in the miner * TODO nonce error sometimes persists * Fixed mining on wrong blocks * Fixed state error & receipt fail --- core/chain_manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index 54f1ced8c..922d2a8d8 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -392,7 +392,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { self.setTotalDifficulty(td) self.insert(block) - self.transState = state.New(cblock.Root(), self.db) //state.New(cblock.Trie().Copy()) + self.transState = state.New(cblock.Root(), self.db) self.eventMux.Post(ChainEvent{block, td}) } -- cgit From d2a4bc4d7389f4b442a19fc03d0d664c19f931e2 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 16 Feb 2015 12:03:27 +0100 Subject: Removed reference to lastBlockNumber & LastBlockNumber --- core/chain_manager.go | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index 922d2a8d8..c28e901c6 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -78,11 +78,10 @@ type ChainManager struct { eventMux *event.TypeMux genesisBlock *types.Block // Last known total difficulty - mu sync.RWMutex - td *big.Int - lastBlockNumber uint64 - currentBlock *types.Block - lastBlockHash []byte + mu sync.RWMutex + td *big.Int + currentBlock *types.Block + lastBlockHash []byte transState *state.StateDB } @@ -94,13 +93,6 @@ func (self *ChainManager) Td() *big.Int { return self.td } -func (self *ChainManager) LastBlockNumber() uint64 { - self.mu.RLock() - defer self.mu.RUnlock() - - return self.lastBlockNumber -} - func (self *ChainManager) LastBlockHash() []byte { self.mu.RLock() defer self.mu.RUnlock() @@ -149,7 +141,6 @@ func (bc *ChainManager) setLastBlock() { rlp.Decode(bytes.NewReader(data), &block) bc.currentBlock = &block bc.lastBlockHash = block.Hash() - bc.lastBlockNumber = block.Header().Number.Uint64() // Set the last know difficulty (might be 0x0 as initial value, Genesis) bc.td = ethutil.BigD(bc.db.LastKnownTD()) @@ -157,7 +148,7 @@ func (bc *ChainManager) setLastBlock() { bc.Reset() } - chainlogger.Infof("Last block (#%d) %x TD=%v\n", bc.lastBlockNumber, bc.currentBlock.Hash(), bc.td) + chainlogger.Infof("Last block (#%v) %x TD=%v\n", bc.currentBlock.Number(), bc.currentBlock.Hash(), bc.td) } // Block creation & chain handling @@ -234,8 +225,6 @@ func (bc *ChainManager) insert(block *types.Block) { } func (bc *ChainManager) write(block *types.Block) { - bc.writeBlockInfo(block) - encodedBlock := ethutil.Encode(block.RlpDataForStorage()) bc.db.Put(block.Hash(), encodedBlock) } @@ -354,11 +343,6 @@ func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) { return td, nil } -// Unexported method for writing extra non-essential block info to the db -func (bc *ChainManager) writeBlockInfo(block *types.Block) { - bc.lastBlockNumber++ -} - func (bc *ChainManager) Stop() { if bc.CurrentBlock != nil { chainlogger.Infoln("Stopped") -- cgit From 8135752a32837748e6d4a986912131736b1a0aa0 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 17 Feb 2015 12:24:51 +0100 Subject: "centralised" mining to backend. Closes #323 --- core/filter.go | 4 ++-- core/manager.go | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'core') diff --git a/core/filter.go b/core/filter.go index b93fcc8a5..234fa3316 100644 --- a/core/filter.go +++ b/core/filter.go @@ -25,7 +25,7 @@ type FilterOptions struct { // Filtering interface type Filter struct { - eth EthManager + eth Backend earliest int64 latest int64 skip int @@ -40,7 +40,7 @@ type Filter struct { // Create a new filter which uses a bloom filter on blocks to figure out whether a particular block // is interesting or not. -func NewFilter(eth EthManager) *Filter { +func NewFilter(eth Backend) *Filter { return &Filter{eth: eth} } diff --git a/core/manager.go b/core/manager.go index f960fc5f0..bb039d063 100644 --- a/core/manager.go +++ b/core/manager.go @@ -7,12 +7,11 @@ import ( "github.com/ethereum/go-ethereum/p2p" ) -type EthManager interface { +type Backend interface { BlockProcessor() *BlockProcessor ChainManager() *ChainManager TxPool() *TxPool PeerCount() int - IsMining() bool IsListening() bool Peers() []*p2p.Peer KeyManager() *crypto.KeyManager -- cgit From 567428fb3489d639cd7fdcd50e4362be52745ec4 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 17 Feb 2015 16:12:55 +0100 Subject: Filter and mutex locks added --- core/chain_manager.go | 13 ++++++++++++- core/filter.go | 23 +++++++++++++++++------ 2 files changed, 29 insertions(+), 7 deletions(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index c28e901c6..025615676 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -79,6 +79,7 @@ type ChainManager struct { genesisBlock *types.Block // Last known total difficulty mu sync.RWMutex + tsmu sync.RWMutex td *big.Int currentBlock *types.Block lastBlockHash []byte @@ -131,9 +132,19 @@ func (self *ChainManager) State() *state.StateDB { } func (self *ChainManager) TransState() *state.StateDB { + self.tsmu.RLock() + defer self.tsmu.RUnlock() + //tmp := self.transState + return self.transState } +func (self *ChainManager) setTransState(statedb *state.StateDB) { + self.tsmu.Lock() + defer self.tsmu.Unlock() + self.transState = statedb +} + func (bc *ChainManager) setLastBlock() { data, _ := bc.db.Get([]byte("LastBlock")) if len(data) != 0 { @@ -376,7 +387,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { self.setTotalDifficulty(td) self.insert(block) - self.transState = state.New(cblock.Root(), self.db) + self.setTransState(state.New(cblock.Root(), self.db)) self.eventMux.Post(ChainEvent{block, td}) } diff --git a/core/filter.go b/core/filter.go index 234fa3316..88f12a67c 100644 --- a/core/filter.go +++ b/core/filter.go @@ -16,7 +16,7 @@ type FilterOptions struct { Earliest int64 Latest int64 - Address []byte + Address [][]byte Topics [][]byte Skip int @@ -29,7 +29,7 @@ type Filter struct { earliest int64 latest int64 skip int - address []byte + address [][]byte max int topics [][]byte @@ -65,7 +65,7 @@ func (self *Filter) SetLatestBlock(latest int64) { self.latest = latest } -func (self *Filter) SetAddress(addr []byte) { +func (self *Filter) SetAddress(addr [][]byte) { self.address = addr } @@ -145,7 +145,8 @@ func (self *Filter) FilterLogs(logs state.Logs) state.Logs { // Filter the logs for interesting stuff Logs: for _, log := range logs { - if !bytes.Equal(self.address, log.Address()) { + if !includes(self.address, log.Address()) { + //if !bytes.Equal(self.address, log.Address()) { continue } @@ -163,8 +164,18 @@ Logs: } func (self *Filter) bloomFilter(block *types.Block) bool { - if len(self.address) > 0 && !types.BloomLookup(block.Bloom(), self.address) { - return false + if len(self.address) > 0 { + var included bool + for _, addr := range self.address { + if types.BloomLookup(block.Bloom(), addr) { + included = true + break + } + } + + if !included { + return false + } } for _, topic := range self.topics { -- cgit From 7fc9b5b3f9ca0111cc4bc1b2a6b4bb2eccd3e048 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 17 Feb 2015 22:20:47 +0100 Subject: Changed to ChainEvent and fixed a nil pointer in transact --- core/chain_manager.go | 2 -- 1 file changed, 2 deletions(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index 025615676..22d54be03 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -393,8 +393,6 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { } } self.mu.Unlock() - - self.eventMux.Post(NewBlockEvent{block}) } return nil -- cgit