aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-09-15 21:42:12 +0800
committerobscuren <geffobscura@gmail.com>2014-09-15 21:42:12 +0800
commit33a0dec8a157b9687ca6038f4deb011f3f1f7bdc (patch)
tree197b792e06dc3952df93957a39fdf6e44582ac96
parent2f614900e82036e3e8f6f6a714efc43e09aca830 (diff)
downloaddexon-33a0dec8a157b9687ca6038f4deb011f3f1f7bdc.tar
dexon-33a0dec8a157b9687ca6038f4deb011f3f1f7bdc.tar.gz
dexon-33a0dec8a157b9687ca6038f4deb011f3f1f7bdc.tar.bz2
dexon-33a0dec8a157b9687ca6038f4deb011f3f1f7bdc.tar.lz
dexon-33a0dec8a157b9687ca6038f4deb011f3f1f7bdc.tar.xz
dexon-33a0dec8a157b9687ca6038f4deb011f3f1f7bdc.tar.zst
dexon-33a0dec8a157b9687ca6038f4deb011f3f1f7bdc.zip
Improved catching up and refactored
-rw-r--r--block_pool.go59
-rw-r--r--ethchain/block.go33
-rw-r--r--ethchain/block_chain.go25
-rw-r--r--ethchain/state_manager.go8
-rw-r--r--ethstate/dump.go2
-rw-r--r--ethstate/state.go5
-rw-r--r--ethstate/state_object.go15
-rw-r--r--ethutil/bytes.go16
-rw-r--r--ethutil/rlp.go2
-rw-r--r--ethutil/set.go16
-rw-r--r--peer.go46
11 files changed, 125 insertions, 102 deletions
diff --git a/block_pool.go b/block_pool.go
index 38827242d..0a668e111 100644
--- a/block_pool.go
+++ b/block_pool.go
@@ -52,59 +52,34 @@ func (self *BlockPool) AddHash(hash []byte) {
func (self *BlockPool) SetBlock(b *ethchain.Block, peer *Peer) {
hash := string(b.Hash())
- if self.pool[hash] == nil {
+ if self.pool[hash] == nil && !self.eth.BlockChain().HasBlock(b.Hash()) {
self.hashPool = append(self.hashPool, b.Hash())
- self.pool[hash] = &block{peer, nil}
+ self.pool[hash] = &block{peer, b}
+ } else if self.pool[hash] != nil {
+ self.pool[hash].block = b
}
-
- self.pool[hash].block = b
}
-func (self *BlockPool) CheckLinkAndProcess(f func(block *ethchain.Block)) bool {
- self.mut.Lock()
- defer self.mut.Unlock()
-
- if self.IsLinked() {
- for i, hash := range self.hashPool {
- if self.pool[string(hash)] == nil {
- continue
- }
+func (self *BlockPool) CheckLinkAndProcess(f func(block *ethchain.Block)) {
- block := self.pool[string(hash)].block
- if block != nil {
- f(block)
-
- delete(self.pool, string(hash))
- } else {
- self.hashPool = self.hashPool[i:]
-
- return false
- }
+ var blocks ethchain.Blocks
+ for _, item := range self.pool {
+ if item.block != nil {
+ blocks = append(blocks, item.block)
}
-
- return true
}
- return false
-}
-
-func (self *BlockPool) IsLinked() bool {
- if len(self.hashPool) == 0 {
- return false
- }
+ ethchain.BlockBy(ethchain.Number).Sort(blocks)
+ for _, block := range blocks {
+ if self.eth.BlockChain().HasBlock(block.PrevHash) {
+ f(block)
- for i := 0; i < len(self.hashPool); i++ {
- item := self.pool[string(self.hashPool[i])]
- if item != nil && item.block != nil {
- if self.eth.BlockChain().HasBlock(item.block.PrevHash) {
- self.hashPool = self.hashPool[i:]
-
- return true
- }
+ hash := block.Hash()
+ self.hashPool = ethutil.DeleteFromByteSlice(self.hashPool, hash)
+ delete(self.pool, string(hash))
}
- }
- return false
+ }
}
func (self *BlockPool) Take(amount int, peer *Peer) (hashes [][]byte) {
diff --git a/ethchain/block.go b/ethchain/block.go
index fde6ff04a..157be2a52 100644
--- a/ethchain/block.go
+++ b/ethchain/block.go
@@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"math/big"
+ "sort"
_ "strconv"
"time"
@@ -42,9 +43,32 @@ func (self Blocks) AsSet() ethutil.UniqueSet {
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 []byte
+ PrevHash ethutil.Bytes
// Uncles of this block
Uncles Blocks
UncleSha []byte
@@ -68,7 +92,7 @@ type Block struct {
// Extra data
Extra string
// Block Nonce for verification
- Nonce []byte
+ Nonce ethutil.Bytes
// List of transactions and/or contracts
transactions []*Transaction
receipts []*Receipt
@@ -117,8 +141,9 @@ func CreateBlock(root interface{},
}
// Returns a hash of the block
-func (block *Block) Hash() []byte {
- return ethcrypto.Sha3Bin(block.Value().Encode())
+func (block *Block) Hash() ethutil.Bytes {
+ return ethcrypto.Sha3Bin(ethutil.NewValue(block.header()).Encode())
+ //return ethcrypto.Sha3Bin(block.Value().Encode())
}
func (block *Block) HashNoNonce() []byte {
diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go
index 2d88a0f53..5d0d652df 100644
--- a/ethchain/block_chain.go
+++ b/ethchain/block_chain.go
@@ -58,24 +58,20 @@ func (bc *BlockChain) NewBlock(coinbase []byte) *Block {
block.MinGasPrice = big.NewInt(10000000000000)
- if bc.CurrentBlock != nil {
- var mul *big.Int
- if block.Time < lastBlockTime+5 {
- mul = big.NewInt(1)
+ parent := bc.CurrentBlock
+ if parent != nil {
+ diff := new(big.Int)
+
+ adjust := new(big.Int).Rsh(parent.Difficulty, 10)
+ if block.Time >= lastBlockTime+5 {
+ diff.Sub(parent.Difficulty, adjust)
} else {
- mul = big.NewInt(-1)
+ diff.Add(parent.Difficulty, adjust)
}
-
- diff := new(big.Int)
- diff.Add(diff, bc.CurrentBlock.Difficulty)
- diff.Div(diff, big.NewInt(1024))
- diff.Mul(diff, mul)
- diff.Add(diff, bc.CurrentBlock.Difficulty)
block.Difficulty = diff
-
block.Number = new(big.Int).Add(bc.CurrentBlock.Number, ethutil.Big1)
-
block.GasLimit = block.CalcGasLimit(bc.CurrentBlock)
+
}
return block
@@ -159,6 +155,9 @@ func (bc *BlockChain) setLastBlock() {
bc.LastBlockHash = block.Hash()
bc.LastBlockNumber = block.Number.Uint64()
+ if bc.LastBlockNumber == 0 {
+ bc.genesisBlock = block
+ }
} else {
AddTestNetFunds(bc.genesisBlock)
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index a165ed79d..1ccaa560f 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -217,13 +217,13 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
return err
}
- // I'm not sure, but I don't know if there should be thrown
- // any errors at this time.
if err = sm.AccumelateRewards(state, block, parent); err != nil {
statelogger.Errorln("Error accumulating reward", err)
return err
}
+ state.Update()
+
if !block.State().Cmp(state) {
err = fmt.Errorf("Invalid merkle root.\nrec: %x\nis: %x", block.State().Trie.Root, state.Trie.Root)
return
@@ -335,7 +335,7 @@ func (sm *StateManager) ValidateBlock(block *Block) error {
}
func (sm *StateManager) AccumelateRewards(state *ethstate.State, block, parent *Block) error {
- reward := new(big.Int)
+ reward := new(big.Int).Set(BlockReward)
knownUncles := ethutil.Set(parent.Uncles)
nonces := ethutil.NewSet(block.Nonce)
@@ -358,6 +358,8 @@ func (sm *StateManager) AccumelateRewards(state *ethstate.State, block, parent *
return UncleError("Uncle in chain")
}
+ nonces.Insert(uncle.Nonce)
+
r := new(big.Int)
r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16))
diff --git a/ethstate/dump.go b/ethstate/dump.go
index be60a05fc..cdd4228b8 100644
--- a/ethstate/dump.go
+++ b/ethstate/dump.go
@@ -28,7 +28,7 @@ func (self *State) Dump() []byte {
self.Trie.NewIterator().Each(func(key string, value *ethutil.Value) {
stateObject := NewStateObjectFromBytes([]byte(key), value.Bytes())
- account := Account{Balance: stateObject.Balance.String(), Nonce: stateObject.Nonce, CodeHash: ethutil.Bytes2Hex(stateObject.CodeHash)}
+ account := Account{Balance: stateObject.Balance.String(), Nonce: stateObject.Nonce, CodeHash: ethutil.Bytes2Hex(stateObject.codeHash)}
account.Storage = make(map[string]string)
stateObject.EachStorage(func(key string, value *ethutil.Value) {
diff --git a/ethstate/state.go b/ethstate/state.go
index 42bbf021b..0e87659fc 100644
--- a/ethstate/state.go
+++ b/ethstate/state.go
@@ -3,7 +3,6 @@ package ethstate
import (
"math/big"
- "github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
@@ -66,7 +65,9 @@ func (self *State) GetCode(addr []byte) []byte {
func (self *State) UpdateStateObject(stateObject *StateObject) {
addr := stateObject.Address()
- ethutil.Config.Db.Put(ethcrypto.Sha3Bin(stateObject.Code), stateObject.Code)
+ if len(stateObject.CodeHash()) > 0 {
+ ethutil.Config.Db.Put(stateObject.CodeHash(), stateObject.Code)
+ }
self.Trie.Update(string(addr), string(stateObject.RlpEncode()))
}
diff --git a/ethstate/state_object.go b/ethstate/state_object.go
index 6fc0696a8..be083e80a 100644
--- a/ethstate/state_object.go
+++ b/ethstate/state_object.go
@@ -32,7 +32,7 @@ type StateObject struct {
address []byte
// Shared attributes
Balance *big.Int
- CodeHash []byte
+ codeHash []byte
Nonce uint64
// Contract related attributes
State *State
@@ -236,7 +236,7 @@ func (self *StateObject) RefundGas(gas, price *big.Int) {
func (self *StateObject) Copy() *StateObject {
stateObject := NewStateObject(self.Address())
stateObject.Balance.Set(self.Balance)
- stateObject.CodeHash = ethutil.CopyBytes(self.CodeHash)
+ stateObject.codeHash = ethutil.CopyBytes(self.codeHash)
stateObject.Nonce = self.Nonce
if self.State != nil {
stateObject.State = self.State.Copy()
@@ -297,12 +297,17 @@ func (c *StateObject) RlpEncode() []byte {
} else {
root = ""
}
+
+ return ethutil.Encode([]interface{}{c.Nonce, c.Balance, root, c.CodeHash()})
+}
+
+func (c *StateObject) CodeHash() ethutil.Bytes {
var codeHash []byte
if len(c.Code) > 0 {
codeHash = ethcrypto.Sha3Bin(c.Code)
}
- return ethutil.Encode([]interface{}{c.Nonce, c.Balance, root, codeHash})
+ return codeHash
}
func (c *StateObject) RlpDecode(data []byte) {
@@ -314,9 +319,9 @@ func (c *StateObject) RlpDecode(data []byte) {
c.storage = make(map[string]*ethutil.Value)
c.gasPool = new(big.Int)
- c.CodeHash = decoder.Get(3).Bytes()
+ c.codeHash = decoder.Get(3).Bytes()
- c.Code, _ = ethutil.Config.Db.Get(c.CodeHash)
+ c.Code, _ = ethutil.Config.Db.Get(c.codeHash)
}
// Storage change object. Used by the manifest for notifying changes to
diff --git a/ethutil/bytes.go b/ethutil/bytes.go
index e38f89454..f151d16ee 100644
--- a/ethutil/bytes.go
+++ b/ethutil/bytes.go
@@ -9,6 +9,22 @@ import (
"strings"
)
+type Bytes []byte
+
+func (self Bytes) String() string {
+ return string(self)
+}
+
+func DeleteFromByteSlice(s [][]byte, hash []byte) [][]byte {
+ for i, h := range s {
+ if bytes.Compare(h, hash) == 0 {
+ return append(s[:i], s[i+1:]...)
+ }
+ }
+
+ return s
+}
+
// Number to bytes
//
// Returns the number in bytes with the specified base
diff --git a/ethutil/rlp.go b/ethutil/rlp.go
index 17ff627eb..febfb78e1 100644
--- a/ethutil/rlp.go
+++ b/ethutil/rlp.go
@@ -124,6 +124,8 @@ func Encode(object interface{}) []byte {
} else {
buff.Write(Encode(t.Bytes()))
}
+ case Bytes:
+ buff.Write(Encode([]byte(t)))
case []byte:
if len(t) == 1 && t[0] <= 0x7f {
buff.Write(t)
diff --git a/ethutil/set.go b/ethutil/set.go
index 80e2edde2..7955edac0 100644
--- a/ethutil/set.go
+++ b/ethutil/set.go
@@ -4,9 +4,13 @@ type Settable interface {
AsSet() UniqueSet
}
-type UniqueSet map[interface{}]struct{}
+type Stringable interface {
+ String() string
+}
+
+type UniqueSet map[string]struct{}
-func NewSet(v ...interface{}) UniqueSet {
+func NewSet(v ...Stringable) UniqueSet {
set := make(UniqueSet)
for _, val := range v {
set.Insert(val)
@@ -15,14 +19,14 @@ func NewSet(v ...interface{}) UniqueSet {
return set
}
-func (self UniqueSet) Insert(k interface{}) UniqueSet {
- self[k] = struct{}{}
+func (self UniqueSet) Insert(k Stringable) UniqueSet {
+ self[k.String()] = struct{}{}
return self
}
-func (self UniqueSet) Include(k interface{}) bool {
- _, ok := self[k]
+func (self UniqueSet) Include(k Stringable) bool {
+ _, ok := self[k.String()]
return ok
}
diff --git a/peer.go b/peer.go
index 349d02097..32885aed8 100644
--- a/peer.go
+++ b/peer.go
@@ -24,7 +24,7 @@ const (
// The size of the output buffer for writing messages
outputBufferSize = 50
// Current protocol version
- ProtocolVersion = 28
+ ProtocolVersion = 32
// Current P2P version
P2PVersion = 0
// Interval for ping/pong message
@@ -276,13 +276,15 @@ func (p *Peer) writeMessage(msg *ethwire.Msg) {
return
}
} else {
- if !p.statusKnown {
- switch msg.Type {
- case ethwire.MsgStatusTy: // Ok
- default: // Anything but ack is allowed
- return
+ /*
+ if !p.statusKnown {
+ switch msg.Type {
+ case ethwire.MsgStatusTy: // Ok
+ default: // Anything but ack is allowed
+ return
+ }
}
- }
+ */
}
peerlogger.DebugDetailf("(%v) <= %v %v\n", p.conn.RemoteAddr(), msg.Type, msg.Data)
@@ -488,19 +490,25 @@ func (p *Peer) HandleInbound() {
it := msg.Data.NewIterator()
for it.Next() {
block := ethchain.NewBlockFromRlpValue(it.Value())
+ //fmt.Printf("%v %x - %x\n", block.Number, block.Hash()[0:4], block.PrevHash[0:4])
blockPool.SetBlock(block, p)
p.lastBlockReceived = time.Now()
}
- linked := blockPool.CheckLinkAndProcess(func(block *ethchain.Block) {
- p.ethereum.StateManager().Process(block, false)
+ blockPool.CheckLinkAndProcess(func(block *ethchain.Block) {
+ err := p.ethereum.StateManager().Process(block, false)
+ if err != nil {
+ peerlogger.Infoln(err)
+ }
})
- if !linked {
- p.FetchBlocks()
- }
+ /*
+ if !linked {
+ p.FetchBlocks()
+ }
+ */
}
}
}
@@ -596,20 +604,6 @@ func (p *Peer) Stop() {
p.ethereum.RemovePeer(p)
}
-/*
-func (p *Peer) pushHandshake() error {
- pubkey := p.ethereum.KeyManager().PublicKey()
- msg := ethwire.NewMessage(ethwire.MsgHandshakeTy, []interface{}{
- uint32(ProtocolVersion), uint32(0), []byte(p.version), byte(p.caps), p.port, pubkey[1:],
- p.ethereum.BlockChain().TD.Uint64(), p.ethereum.BlockChain().CurrentBlock.Hash(),
- })
-
- p.QueueMessage(msg)
-
- return nil
-}
-*/
-
func (p *Peer) peersMessage() *ethwire.Msg {
outPeers := make([]interface{}, len(p.ethereum.InOutPeers()))
// Serialise each peer