aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/block_processor.go25
-rw-r--r--core/chain_makers.go142
-rw-r--r--core/chain_manager.go10
-rw-r--r--core/chain_manager_test.go194
-rw-r--r--core/error.go18
-rw-r--r--core/execution.go2
-rw-r--r--core/filter.go35
-rw-r--r--core/state_transition.go19
-rw-r--r--core/transaction_pool.go9
-rw-r--r--core/types/block.go29
-rw-r--r--core/types/bloom9.go7
11 files changed, 451 insertions, 39 deletions
diff --git a/core/block_processor.go b/core/block_processor.go
index 7eaeb5be0..8974cd94b 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -12,7 +12,6 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
- "github.com/ethereum/go-ethereum/pow/ezp"
"github.com/ethereum/go-ethereum/state"
"gopkg.in/fatih/set.v0"
)
@@ -46,11 +45,11 @@ type BlockProcessor struct {
eventMux *event.TypeMux
}
-func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
+func NewBlockProcessor(db ethutil.Database, pow pow.PoW, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
sm := &BlockProcessor{
db: db,
mem: make(map[string]*big.Int),
- Pow: ezp.New(),
+ Pow: pow,
bc: chainManager,
eventMux: eventMux,
txpool: txpool,
@@ -105,6 +104,9 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
return receipt, txGas, err
}
+func (self *BlockProcessor) ChainManager() *ChainManager {
+ return self.bc
+}
func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) {
var (
@@ -204,7 +206,6 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
// 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)
err = fmt.Errorf("validating receipt root. received=%x got=%x", header.ReceiptHash, receiptSha)
return
}
@@ -247,9 +248,19 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd)
}
- expl := CalcGasLimit(parent, block)
- if expl.Cmp(block.Header().GasLimit) != 0 {
- return fmt.Errorf("GasLimit check failed for block %v, %v", block.Header().GasLimit, expl)
+ //expl := CalcGasLimit(parent, block)
+ //if expl.Cmp(block.Header().GasLimit) != 0 {
+
+ // block.gasLimit - parent.gasLimit <= parent.gasLimit / 1024
+ a := new(big.Int).Sub(block.Header().GasLimit, parent.Header().GasLimit)
+ b := new(big.Int).Div(parent.Header().GasLimit, big.NewInt(1024))
+ if a.Cmp(b) > 0 {
+ return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.Header().GasLimit, a, b)
+ }
+
+ // There can be at most one uncle
+ if len(block.Uncles()) > 1 {
+ return ValidationError("Block can only contain one uncle (contained %v)", len(block.Uncles()))
}
if block.Time() < parent.Time() {
diff --git a/core/chain_makers.go b/core/chain_makers.go
new file mode 100644
index 000000000..7afdfde0d
--- /dev/null
+++ b/core/chain_makers.go
@@ -0,0 +1,142 @@
+package core
+
+import (
+ "fmt"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/ethutil"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/pow"
+ "github.com/ethereum/go-ethereum/state"
+)
+
+// So we can generate blocks easily
+type FakePow struct{}
+
+func (f FakePow) Search(block pow.Block, stop <-chan struct{}) ([]byte, []byte, []byte) {
+ return nil, nil, nil
+}
+func (f FakePow) Verify(block pow.Block) bool { return true }
+func (f FakePow) GetHashrate() int64 { return 0 }
+func (f FakePow) Turbo(bool) {}
+
+// So we can deterministically seed different blockchains
+var (
+ CanonicalSeed = 1
+ ForkSeed = 2
+)
+
+// Utility functions for making chains on the fly
+// Exposed for sake of testing from other packages (eg. go-ethash)
+func NewBlockFromParent(addr []byte, parent *types.Block) *types.Block {
+ return newBlockFromParent(addr, parent)
+}
+
+func MakeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database, seed int) *types.Block {
+ return makeBlock(bman, parent, i, db, seed)
+}
+
+func MakeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database, seed int) types.Blocks {
+ return makeChain(bman, parent, max, db, seed)
+}
+
+func NewChainMan(block *types.Block, eventMux *event.TypeMux, db ethutil.Database) *ChainManager {
+ return newChainManager(block, eventMux, db)
+}
+
+func NewBlockProc(db ethutil.Database, txpool *TxPool, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
+ return newBlockProcessor(db, txpool, cman, eventMux)
+}
+
+func NewCanonical(n int, db ethutil.Database) (*BlockProcessor, error) {
+ return newCanonical(n, db)
+}
+
+// block time is fixed at 10 seconds
+func newBlockFromParent(addr []byte, parent *types.Block) *types.Block {
+ block := types.NewBlock(parent.Hash(), addr, parent.Root(), ethutil.BigPow(2, 32), nil, "")
+ block.SetUncles(nil)
+ block.SetTransactions(nil)
+ block.SetReceipts(nil)
+
+ header := block.Header()
+ header.Difficulty = CalcDifficulty(block, parent)
+ header.Number = new(big.Int).Add(parent.Header().Number, ethutil.Big1)
+ header.Time = parent.Header().Time + 10
+ header.GasLimit = CalcGasLimit(parent, block)
+
+ block.Td = parent.Td
+
+ return block
+}
+
+// Actually make a block by simulating what miner would do
+// we seed chains by the first byte of the coinbase
+func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database, seed int) *types.Block {
+ addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20)
+ addr[0] = byte(seed)
+ block := newBlockFromParent(addr, parent)
+ state := state.New(block.Root(), db)
+ cbase := state.GetOrNewStateObject(addr)
+ cbase.SetGasPool(CalcGasLimit(parent, block))
+ cbase.AddBalance(BlockReward)
+ state.Update(ethutil.Big0)
+ block.SetRoot(state.Root())
+ return block
+}
+
+// Make a chain with real blocks
+// Runs ProcessWithParent to get proper state roots
+func makeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database, seed int) types.Blocks {
+ bman.bc.currentBlock = parent
+ blocks := make(types.Blocks, max)
+ for i := 0; i < max; i++ {
+ block := makeBlock(bman, parent, i, db, seed)
+ td, err := bman.processWithParent(block, parent)
+ if err != nil {
+ fmt.Println("process with parent failed", err)
+ panic(err)
+ }
+ block.Td = td
+ blocks[i] = block
+ parent = block
+ }
+ return blocks
+}
+
+// Create a new chain manager starting from given block
+// Effectively a fork factory
+func newChainManager(block *types.Block, eventMux *event.TypeMux, db ethutil.Database) *ChainManager {
+ bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: eventMux}
+ if block == nil {
+ bc.Reset()
+ } else {
+ bc.currentBlock = block
+ bc.td = block.Td
+ }
+ return bc
+}
+
+// block processor with fake pow
+func newBlockProcessor(db ethutil.Database, txpool *TxPool, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
+ bman := NewBlockProcessor(db, FakePow{}, txpool, newChainManager(nil, eventMux, db), eventMux)
+ return bman
+}
+
+// Make a new, deterministic canonical chain by running InsertChain
+// on result of makeChain
+func newCanonical(n int, db ethutil.Database) (*BlockProcessor, error) {
+ eventMux := &event.TypeMux{}
+ txpool := NewTxPool(eventMux)
+
+ bman := newBlockProcessor(db, txpool, newChainManager(nil, eventMux, db), eventMux)
+ bman.bc.SetProcessor(bman)
+ parent := bman.bc.CurrentBlock()
+ if n == 0 {
+ return bman, nil
+ }
+ lchain := makeChain(bman, parent, n, db, CanonicalSeed)
+ err := bman.bc.InsertChain(lchain)
+ return bman, err
+}
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 71d36d57d..13edeea95 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -31,11 +31,13 @@ type StateQuery interface {
func CalcDifficulty(block, parent *types.Block) *big.Int {
diff := new(big.Int)
- adjust := new(big.Int).Rsh(parent.Difficulty(), 10)
- if block.Time() >= parent.Time()+8 {
- diff.Sub(parent.Difficulty(), adjust)
- } else {
+ //adjust := new(big.Int).Rsh(parent.Difficulty(), 10)
+ //if block.Time() >= parent.Time()+8 {
+ adjust := new(big.Int).Div(parent.Difficulty(), big.NewInt(2048))
+ if (block.Time() - parent.Time()) < 8 {
diff.Add(parent.Difficulty(), adjust)
+ } else {
+ diff.Sub(parent.Difficulty(), adjust)
}
return diff
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go
index bc3a264d1..b562b677d 100644
--- a/core/chain_manager_test.go
+++ b/core/chain_manager_test.go
@@ -3,6 +3,7 @@ package core
import (
"bytes"
"fmt"
+ "math/big"
"os"
"path"
"runtime"
@@ -21,6 +22,75 @@ func init() {
ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH")
}
+// Test fork of length N starting from block i
+func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big.Int)) {
+ // switch databases to process the new chain
+ db, err := ethdb.NewMemDatabase()
+ if err != nil {
+ t.Fatal("Failed to create db:", err)
+ }
+ // copy old chain up to i into new db with deterministic canonical
+ bman2, err := newCanonical(i, db)
+ if err != nil {
+ t.Fatal("could not make new canonical in testFork", err)
+ }
+ // asert the bmans have the same block at i
+ bi1 := bman.bc.GetBlockByNumber(uint64(i)).Hash()
+ bi2 := bman2.bc.GetBlockByNumber(uint64(i)).Hash()
+ if bytes.Compare(bi1, bi2) != 0 {
+ t.Fatal("chains do not have the same hash at height", i)
+ }
+
+ bman2.bc.SetProcessor(bman2)
+
+ // extend the fork
+ parent := bman2.bc.CurrentBlock()
+ chainB := makeChain(bman2, parent, N, db, ForkSeed)
+ err = bman2.bc.InsertChain(chainB)
+ if err != nil {
+ t.Fatal("Insert chain error for fork:", err)
+ }
+
+ tdpre := bman.bc.Td()
+ // Test the fork's blocks on the original chain
+ td, err := testChain(chainB, bman)
+ if err != nil {
+ t.Fatal("expected chainB not to give errors:", err)
+ }
+ // Compare difficulties
+ f(tdpre, td)
+}
+
+func printChain(bc *ChainManager) {
+ for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- {
+ b := bc.GetBlockByNumber(uint64(i))
+ fmt.Printf("\t%x\n", b.Hash())
+ }
+}
+
+// process blocks against a chain
+func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) {
+ td := new(big.Int)
+ for _, block := range chainB {
+ td2, err := bman.bc.processor.Process(block)
+ if err != nil {
+ if IsKnownBlockErr(err) {
+ continue
+ }
+ return nil, err
+ }
+ block.Td = td2
+ td = td2
+
+ bman.bc.mu.Lock()
+ {
+ bman.bc.write(block)
+ }
+ bman.bc.mu.Unlock()
+ }
+ return td, nil
+}
+
func loadChain(fn string, t *testing.T) (types.Blocks, error) {
fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm)
if err != nil {
@@ -45,6 +115,130 @@ func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *
done <- true
}
+func TestExtendCanonical(t *testing.T) {
+ CanonicalLength := 5
+ db, err := ethdb.NewMemDatabase()
+ if err != nil {
+ t.Fatal("Failed to create db:", err)
+ }
+ // make first chain starting from genesis
+ bman, err := newCanonical(CanonicalLength, db)
+ if err != nil {
+ t.Fatal("Could not make new canonical chain:", err)
+ }
+ f := func(td1, td2 *big.Int) {
+ if td2.Cmp(td1) <= 0 {
+ t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
+ }
+ }
+ // Start fork from current height (CanonicalLength)
+ testFork(t, bman, CanonicalLength, 1, f)
+ testFork(t, bman, CanonicalLength, 2, f)
+ testFork(t, bman, CanonicalLength, 5, f)
+ testFork(t, bman, CanonicalLength, 10, f)
+}
+
+func TestShorterFork(t *testing.T) {
+ db, err := ethdb.NewMemDatabase()
+ if err != nil {
+ t.Fatal("Failed to create db:", err)
+ }
+ // make first chain starting from genesis
+ bman, err := newCanonical(10, db)
+ if err != nil {
+ t.Fatal("Could not make new canonical chain:", err)
+ }
+ f := func(td1, td2 *big.Int) {
+ if td2.Cmp(td1) >= 0 {
+ t.Error("expected chainB to have lower difficulty. Got", td2, "expected less than", td1)
+ }
+ }
+ // Sum of numbers must be less than 10
+ // for this to be a shorter fork
+ testFork(t, bman, 0, 3, f)
+ testFork(t, bman, 0, 7, f)
+ testFork(t, bman, 1, 1, f)
+ testFork(t, bman, 1, 7, f)
+ testFork(t, bman, 5, 3, f)
+ testFork(t, bman, 5, 4, f)
+}
+
+func TestLongerFork(t *testing.T) {
+ db, err := ethdb.NewMemDatabase()
+ if err != nil {
+ t.Fatal("Failed to create db:", err)
+ }
+ // make first chain starting from genesis
+ bman, err := newCanonical(10, db)
+ if err != nil {
+ t.Fatal("Could not make new canonical chain:", err)
+ }
+ f := func(td1, td2 *big.Int) {
+ if td2.Cmp(td1) <= 0 {
+ t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
+ }
+ }
+ // Sum of numbers must be greater than 10
+ // for this to be a longer fork
+ testFork(t, bman, 0, 11, f)
+ testFork(t, bman, 0, 15, f)
+ testFork(t, bman, 1, 10, f)
+ testFork(t, bman, 1, 12, f)
+ testFork(t, bman, 5, 6, f)
+ testFork(t, bman, 5, 8, f)
+}
+
+func TestEqualFork(t *testing.T) {
+ db, err := ethdb.NewMemDatabase()
+ if err != nil {
+ t.Fatal("Failed to create db:", err)
+ }
+ bman, err := newCanonical(10, db)
+ if err != nil {
+ t.Fatal("Could not make new canonical chain:", err)
+ }
+ f := func(td1, td2 *big.Int) {
+ if td2.Cmp(td1) != 0 {
+ t.Error("expected chainB to have equal difficulty. Got", td2, "expected ", td1)
+ }
+ }
+ // Sum of numbers must be equal to 10
+ // for this to be an equal fork
+ testFork(t, bman, 0, 10, f)
+ testFork(t, bman, 1, 9, f)
+ testFork(t, bman, 2, 8, f)
+ testFork(t, bman, 5, 5, f)
+ testFork(t, bman, 6, 4, f)
+ testFork(t, bman, 9, 1, f)
+}
+
+func TestBrokenChain(t *testing.T) {
+ db, err := ethdb.NewMemDatabase()
+ if err != nil {
+ t.Fatal("Failed to create db:", err)
+ }
+ bman, err := newCanonical(10, db)
+ if err != nil {
+ t.Fatal("Could not make new canonical chain:", err)
+ }
+ db2, err := ethdb.NewMemDatabase()
+ if err != nil {
+ t.Fatal("Failed to create db:", err)
+ }
+ bman2, err := newCanonical(10, db2)
+ if err != nil {
+ t.Fatal("Could not make new canonical chain:", err)
+ }
+ bman2.bc.SetProcessor(bman2)
+ parent := bman2.bc.CurrentBlock()
+ chainB := makeChain(bman2, parent, 5, db2, ForkSeed)
+ chainB = chainB[1:]
+ _, err = testChain(chainB, bman)
+ if err == nil {
+ t.Error("expected broken chain to return error")
+ }
+}
+
func TestChainInsertions(t *testing.T) {
t.Skip() // travil fails.
diff --git a/core/error.go b/core/error.go
index e86bacb2d..fb1eaed84 100644
--- a/core/error.go
+++ b/core/error.go
@@ -87,6 +87,24 @@ func IsNonceErr(err error) bool {
return ok
}
+type InvalidTxErr struct {
+ Message string
+}
+
+func (err *InvalidTxErr) Error() string {
+ return err.Message
+}
+
+func InvalidTxError(err error) *InvalidTxErr {
+ return &InvalidTxErr{fmt.Sprintf("%v", err)}
+}
+
+func IsInvalidTxErr(err error) bool {
+ _, ok := err.(*InvalidTxErr)
+
+ return ok
+}
+
type OutOfGasErr struct {
Message string
}
diff --git a/core/execution.go b/core/execution.go
index 5e0cbd37e..f7d5a8945 100644
--- a/core/execution.go
+++ b/core/execution.go
@@ -61,10 +61,10 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret
snapshot := env.State().Copy()
start := time.Now()
ret, err = evm.Run(to, caller, code, self.value, self.Gas, self.price, self.input)
+ chainlogger.Debugf("vm took %v\n", time.Since(start))
if err != nil {
env.State().Set(snapshot)
}
- chainlogger.Debugf("vm took %v\n", time.Since(start))
return
}
diff --git a/core/filter.go b/core/filter.go
index cdf7b282d..c61c9e998 100644
--- a/core/filter.go
+++ b/core/filter.go
@@ -17,7 +17,7 @@ type FilterOptions struct {
Latest int64
Address [][]byte
- Topics [][]byte
+ Topics [][][]byte
Skip int
Max int
@@ -31,7 +31,7 @@ type Filter struct {
skip int
address [][]byte
max int
- topics [][]byte
+ topics [][][]byte
BlockCallback func(*types.Block)
PendingCallback func(*types.Block)
@@ -44,6 +44,8 @@ func NewFilter(eth Backend) *Filter {
return &Filter{eth: eth}
}
+// SetOptions copies the filter options to the filter it self. The reason for this "silly" copy
+// is simply because named arguments in this case is extremely nice and readable.
func (self *Filter) SetOptions(options FilterOptions) {
self.earliest = options.Earliest
self.latest = options.Latest
@@ -69,7 +71,7 @@ func (self *Filter) SetAddress(addr [][]byte) {
self.address = addr
}
-func (self *Filter) SetTopics(topics [][]byte) {
+func (self *Filter) SetTopics(topics [][][]byte) {
self.topics = topics
}
@@ -149,10 +151,18 @@ Logs:
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
+ logTopics := make([][]byte, len(self.topics))
+ copy(logTopics, log.Topics())
+
+ for i, topics := range self.topics {
+ for _, topic := range topics {
+ var match bool
+ if bytes.Equal(log.Topics()[i], topic) {
+ match = true
+ }
+ if !match {
+ continue Logs
+ }
}
}
@@ -177,8 +187,15 @@ func (self *Filter) bloomFilter(block *types.Block) bool {
}
}
- for _, topic := range self.topics {
- if !types.BloomLookup(block.Bloom(), topic) {
+ for _, sub := range self.topics {
+ var included bool
+ for _, topic := range sub {
+ if types.BloomLookup(block.Bloom(), topic) {
+ included = true
+ break
+ }
+ }
+ if !included {
return false
}
}
diff --git a/core/state_transition.go b/core/state_transition.go
index 7331fdd4a..00e383f3f 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -3,7 +3,6 @@ package core
import (
"fmt"
"math/big"
-
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/state"
@@ -12,6 +11,8 @@ import (
const tryJit = false
+var ()
+
/*
* The State transitioning model
*
@@ -144,7 +145,7 @@ func (self *StateTransition) preCheck() (err error) {
// Pre-pay gas / Buy gas of the coinbase account
if err = self.BuyGas(); err != nil {
- return err
+ return InvalidTxError(err)
}
return nil
@@ -165,22 +166,22 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
defer self.RefundGas()
- // Increment the nonce for the next transaction
- self.state.SetNonce(sender.Address(), sender.Nonce()+1)
- //sender.Nonce += 1
-
// Transaction gas
if err = self.UseGas(vm.GasTx); err != nil {
- return
+ return nil, InvalidTxError(err)
}
+ // Increment the nonce for the next transaction
+ self.state.SetNonce(sender.Address(), sender.Nonce()+1)
+ //sender.Nonce += 1
+
// Pay data gas
var dgas int64
for _, byt := range self.data {
if byt != 0 {
- dgas += vm.GasData.Int64()
+ dgas += vm.GasTxDataNonzeroByte.Int64()
} else {
- dgas += 1 // This is 1/5. If GasData changes this fails
+ dgas += vm.GasTxDataZeroByte.Int64()
}
}
if err = self.UseGas(big.NewInt(dgas)); err != nil {
diff --git a/core/transaction_pool.go b/core/transaction_pool.go
index 050cff3d8..bd377f679 100644
--- a/core/transaction_pool.go
+++ b/core/transaction_pool.go
@@ -117,8 +117,13 @@ func (self *TxPool) add(tx *types.Transaction) error {
} else {
to = "[NEW_CONTRACT]"
}
-
- txplogger.Debugf("(t) %x => %s (%v) %x\n", tx.From()[:4], to, tx.Value, tx.Hash())
+ var from string
+ if len(tx.From()) > 0 {
+ from = ethutil.Bytes2Hex(tx.From()[:4])
+ } else {
+ return errors.New(fmt.Sprintf("FROM ADDRESS MUST BE POSITIVE (was %v)", tx.From()))
+ }
+ txplogger.Debugf("(t) %x => %s (%v) %x\n", from, to, tx.Value, tx.Hash())
// Notify the subscribers
go self.eventMux.Post(TxPreEvent{tx})
diff --git a/core/types/block.go b/core/types/block.go
index d57de1311..673c72003 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -41,12 +41,29 @@ type Header struct {
Extra string
// Block Nonce for verification
Nonce ethutil.Bytes
+ // Mix digest for quick checking to prevent DOS
+ MixDigest ethutil.Bytes
+ // SeedHash used for light client verification
+ SeedHash ethutil.Bytes
}
func (self *Header) rlpData(withNonce bool) []interface{} {
- fields := []interface{}{self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra}
+ fields := []interface{}{
+ self.ParentHash,
+ self.UncleHash,
+ self.Coinbase,
+ self.Root,
+ self.TxHash,
+ self.ReceiptHash,
+ self.Bloom,
+ self.Difficulty,
+ self.Number,
+ self.GasLimit,
+ self.GasUsed,
+ self.Time,
+ self.Extra}
if withNonce {
- fields = append(fields, self.Nonce)
+ fields = append(fields, self.Nonce, self.MixDigest, self.SeedHash)
}
return fields
@@ -176,6 +193,8 @@ 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) MixDigest() []byte { return self.header.MixDigest }
+func (self *Block) SeedHash() []byte { return self.header.SeedHash }
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 }
@@ -200,7 +219,6 @@ func (self *Block) GetUncle(i int) *Header {
// Implement pow.Block
func (self *Block) Difficulty() *big.Int { return self.header.Difficulty }
-func (self *Block) N() []byte { return self.header.Nonce }
func (self *Block) HashNoNonce() []byte { return self.header.HashNoNonce() }
func (self *Block) Hash() []byte {
@@ -250,7 +268,10 @@ func (self *Header) String() string {
Time: %v
Extra: %v
Nonce: %x
-`, self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra, self.Nonce)
+ MixDigest: %x
+ SeedHash: %x
+
+`, self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra, self.Nonce, self.MixDigest, self.SeedHash)
}
type Blocks []*Block
diff --git a/core/types/bloom9.go b/core/types/bloom9.go
index c1841e553..578265a34 100644
--- a/core/types/bloom9.go
+++ b/core/types/bloom9.go
@@ -14,7 +14,7 @@ func CreateBloom(receipts Receipts) []byte {
bin.Or(bin, LogsBloom(receipt.logs))
}
- return ethutil.LeftPadBytes(bin.Bytes(), 64)
+ return ethutil.LeftPadBytes(bin.Bytes(), 256)
}
func LogsBloom(logs state.Logs) *big.Int {
@@ -37,9 +37,10 @@ func LogsBloom(logs state.Logs) *big.Int {
func bloom9(b []byte) *big.Int {
r := new(big.Int)
- for _, i := range []int{0, 2, 4} {
+
+ for i := 0; i < 16; i += 2 {
t := big.NewInt(1)
- b := uint(b[i+1]) + 256*(uint(b[i])&1)
+ b := uint(b[i+1]) + 1024*(uint(b[i])&1)
r.Or(r, t.Lsh(t, b))
}