aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ethchain/block.go13
-rw-r--r--ethchain/block_chain.go2
-rw-r--r--ethchain/error.go18
-rw-r--r--ethchain/state_manager.go73
-rw-r--r--ethminer/miner.go2
-rw-r--r--ethvm/vm.go57
-rw-r--r--peer.go2
7 files changed, 101 insertions, 66 deletions
diff --git a/ethchain/block.go b/ethchain/block.go
index d2d012e55..fde6ff04a 100644
--- a/ethchain/block.go
+++ b/ethchain/block.go
@@ -31,11 +31,22 @@ func (bi *BlockInfo) RlpEncode() []byte {
return ethutil.Encode([]interface{}{bi.Number, bi.Hash, bi.Parent})
}
+type Blocks []*Block
+
+func (self Blocks) AsSet() ethutil.UniqueSet {
+ set := make(ethutil.UniqueSet)
+ for _, block := range self {
+ set.Insert(block.Hash())
+ }
+
+ return set
+}
+
type Block struct {
// Hash to the previous block
PrevHash []byte
// Uncles of this block
- Uncles []*Block
+ Uncles Blocks
UncleSha []byte
// The coin base address
Coinbase []byte
diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go
index 74f47aa90..2d88a0f53 100644
--- a/ethchain/block_chain.go
+++ b/ethchain/block_chain.go
@@ -60,7 +60,7 @@ func (bc *BlockChain) NewBlock(coinbase []byte) *Block {
if bc.CurrentBlock != nil {
var mul *big.Int
- if block.Time < lastBlockTime+42 {
+ if block.Time < lastBlockTime+5 {
mul = big.NewInt(1)
} else {
mul = big.NewInt(-1)
diff --git a/ethchain/error.go b/ethchain/error.go
index 2cf09a1ec..82949141a 100644
--- a/ethchain/error.go
+++ b/ethchain/error.go
@@ -25,6 +25,24 @@ func IsParentErr(err error) bool {
return ok
}
+type UncleErr struct {
+ Message string
+}
+
+func (err *UncleErr) Error() string {
+ return err.Message
+}
+
+func UncleError(str string) error {
+ return &UncleErr{Message: str}
+}
+
+func IsUncleErr(err error) bool {
+ _, ok := err.(*UncleErr)
+
+ return ok
+}
+
// Block validation error. If any validation fails, this error will be thrown
type ValidationErr struct {
Message string
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 33af259cf..a165ed79d 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -219,7 +219,7 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
// 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); err != nil {
+ if err = sm.AccumelateRewards(state, block, parent); err != nil {
statelogger.Errorln("Error accumulating reward", err)
return err
}
@@ -334,36 +334,44 @@ func (sm *StateManager) ValidateBlock(block *Block) error {
return nil
}
-func CalculateBlockReward(block *Block, uncleLength int) *big.Int {
- base := new(big.Int)
- for i := 0; i < uncleLength; i++ {
- base.Add(base, UncleInclusionReward)
- }
+func (sm *StateManager) AccumelateRewards(state *ethstate.State, block, parent *Block) error {
+ reward := new(big.Int)
- return base.Add(base, BlockReward)
-}
+ knownUncles := ethutil.Set(parent.Uncles)
+ nonces := ethutil.NewSet(block.Nonce)
+ for _, uncle := range block.Uncles {
+ if nonces.Include(uncle.Nonce) {
+ // Error not unique
+ return UncleError("Uncle not unique")
+ }
-func CalculateUncleReward(block *Block) *big.Int {
- return UncleReward
-}
+ uncleParent := sm.bc.GetBlock(uncle.PrevHash)
+ if uncleParent == nil {
+ return UncleError("Uncle's parent unknown")
+ }
-func (sm *StateManager) AccumelateRewards(state *ethstate.State, block *Block) error {
- // Get the account associated with the coinbase
- account := state.GetAccount(block.Coinbase)
- // Reward amount of ether to the coinbase address
- account.AddAmount(CalculateBlockReward(block, len(block.Uncles)))
+ if uncleParent.Number.Cmp(new(big.Int).Sub(parent.Number, big.NewInt(6))) < 0 {
+ return UncleError("Uncle too old")
+ }
- addr := make([]byte, len(block.Coinbase))
- copy(addr, block.Coinbase)
- state.UpdateStateObject(account)
+ if knownUncles.Include(uncle.Hash()) {
+ return UncleError("Uncle in chain")
+ }
+
+ r := new(big.Int)
+ r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16))
- for _, uncle := range block.Uncles {
uncleAccount := state.GetAccount(uncle.Coinbase)
- uncleAccount.AddAmount(CalculateUncleReward(uncle))
+ uncleAccount.AddAmount(r)
- state.UpdateStateObject(uncleAccount)
+ reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
}
+ // Get the account associated with the coinbase
+ account := state.GetAccount(block.Coinbase)
+ // Reward amount of ether to the coinbase address
+ account.AddAmount(reward)
+
return nil
}
@@ -375,14 +383,6 @@ func (sm *StateManager) Stop() {
func (sm *StateManager) createBloomFilter(state *ethstate.State) *BloomFilter {
bloomf := NewBloomFilter(nil)
- /*
- for addr, stateObject := range state.Manifest().ObjectChanges {
- // Set the bloom filter's bin
- bloomf.Set([]byte(addr))
-
- sm.Ethereum.Reactor().Post("object:"+addr, stateObject)
- }
- */
for _, msg := range state.Manifest().Messages {
bloomf.Set(msg.To)
bloomf.Set(msg.From)
@@ -390,17 +390,6 @@ func (sm *StateManager) createBloomFilter(state *ethstate.State) *BloomFilter {
sm.Ethereum.Reactor().Post("messages", state.Manifest().Messages)
- /*
- for stateObjectAddr, mappedObjects := range state.Manifest().StorageChanges {
- for addr, value := range mappedObjects {
- // Set the bloom filter's bin
- bloomf.Set(ethcrypto.Sha3Bin([]byte(stateObjectAddr + addr)))
-
- sm.Ethereum.Reactor().Post("storage:"+stateObjectAddr+":"+addr, &ethstate.StorageState{[]byte(stateObjectAddr), []byte(addr), value})
- }
- }
- */
-
return bloomf
}
@@ -420,7 +409,7 @@ func (sm *StateManager) GetMessages(block *Block) (messages []*ethstate.Message,
sm.ApplyDiff(state, parent, block)
- sm.AccumelateRewards(state, block)
+ sm.AccumelateRewards(state, block, parent)
return state.Manifest().Messages, nil
}
diff --git a/ethminer/miner.go b/ethminer/miner.go
index 799db79f1..083d9ecde 100644
--- a/ethminer/miner.go
+++ b/ethminer/miner.go
@@ -187,7 +187,7 @@ func (self *Miner) mineNewBlock() {
self.block.SetReceipts(receipts, txs)
// Accumulate the rewards included for this block
- stateManager.AccumelateRewards(self.block.State(), self.block)
+ stateManager.AccumelateRewards(self.block.State(), self.block, parent)
self.block.State().Update()
diff --git a/ethvm/vm.go b/ethvm/vm.go
index fba8c4a0e..2c516f4f8 100644
--- a/ethvm/vm.go
+++ b/ethvm/vm.go
@@ -3,7 +3,6 @@ package ethvm
import (
"container/list"
"fmt"
- "math"
"math/big"
"github.com/ethereum/eth-go/ethcrypto"
@@ -67,6 +66,19 @@ func New(env Environment) *Vm {
return &Vm{env: env, logTy: lt, Recoverable: true, queue: list.New()}
}
+func calcMemSize(off, l *big.Int) *big.Int {
+ if l.Cmp(ethutil.Big0) == 0 {
+ return ethutil.Big0
+ }
+
+ return new(big.Int).Add(off, l)
+}
+
+// Simple helper
+func u256(n int64) *big.Int {
+ return big.NewInt(n)
+}
+
func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
if self.Recoverable {
// Recover from any require exception
@@ -147,7 +159,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
addStepGasUsage(GasStep)
- var newMemSize uint64 = 0
+ var newMemSize *big.Int = ethutil.Big0
switch op {
case STOP:
gas.Set(ethutil.Big0)
@@ -171,57 +183,62 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
gas.Set(GasBalance)
case MSTORE:
require(2)
- newMemSize = stack.Peek().Uint64() + 32
+ newMemSize = calcMemSize(stack.Peek(), u256(32))
case MLOAD:
require(1)
- newMemSize = stack.Peek().Uint64() + 32
+ newMemSize = calcMemSize(stack.Peek(), u256(32))
case MSTORE8:
require(2)
- newMemSize = stack.Peek().Uint64() + 1
+ newMemSize = calcMemSize(stack.Peek(), u256(1))
case RETURN:
require(2)
- newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-2].Uint64()
+ newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
case SHA3:
require(2)
gas.Set(GasSha)
- newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-2].Uint64()
+ newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
case CALLDATACOPY:
require(3)
- newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-3].Uint64()
+ newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
case CODECOPY:
require(3)
- newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-3].Uint64()
+ newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
case EXTCODECOPY:
require(4)
- newMemSize = stack.data[stack.Len()-1].Uint64() + stack.data[stack.Len()-4].Uint64()
+ newMemSize = calcMemSize(stack.data[stack.Len()-1], stack.data[stack.Len()-4])
case CALL, CALLSTATELESS:
require(7)
gas.Set(GasCall)
addStepGasUsage(stack.data[stack.Len()-1])
- x := stack.data[stack.Len()-6].Uint64() + stack.data[stack.Len()-7].Uint64()
- y := stack.data[stack.Len()-4].Uint64() + stack.data[stack.Len()-5].Uint64()
+ x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7])
+ y := calcMemSize(stack.data[stack.Len()-4], stack.data[stack.Len()-5])
- newMemSize = uint64(math.Max(float64(x), float64(y)))
+ newMemSize = ethutil.BigMax(x, y)
case CREATE:
require(3)
gas.Set(GasCreate)
- newMemSize = stack.data[stack.Len()-2].Uint64() + stack.data[stack.Len()-3].Uint64()
+ newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3])
}
- // BUG This will break on overflows. https://github.com/ethereum/eth-go/issues/47
- newMemSize = (newMemSize + 31) / 32 * 32
- if newMemSize > uint64(mem.Len()) {
- m := GasMemory.Uint64() * (newMemSize - uint64(mem.Len())) / 32
- addStepGasUsage(big.NewInt(int64(m)))
+ if newMemSize.Cmp(ethutil.Big0) > 0 {
+ //newMemSize = (newMemSize + 31) / 32 * 32
+ newMemSize = newMemSize.Add(newMemSize, u256(31)).Div(newMemSize, u256(32)).Mul(newMemSize, u256(32))
+ //if newMemSize > uint64(mem.Len()) {
+ if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
+ newMemSize = newMemSize.Sub(newMemSize, u256(int64(mem.Len())))
+ memGasUsage := newMemSize.Mul(GasMemory, newMemSize).Div(newMemSize, u256(32))
+ //m := GasMemory.Uint64() * (newMemSize - uint64(mem.Len())) / 32
+ addStepGasUsage(memGasUsage)
+ }
}
if !closure.UseGas(gas) {
@@ -235,7 +252,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf("(pc) %-3d -o- %-14s", pc, op.String())
self.Printf(" (g) %-3v (%v)", gas, closure.Gas)
- mem.Resize(newMemSize)
+ mem.Resize(newMemSize.Uint64())
switch op {
case LOG:
diff --git a/peer.go b/peer.go
index 4cc62887c..349d02097 100644
--- a/peer.go
+++ b/peer.go
@@ -675,7 +675,7 @@ func (self *Peer) handleStatus(msg *ethwire.Msg) {
func (p *Peer) pushHandshake() error {
pubkey := p.ethereum.KeyManager().PublicKey()
msg := ethwire.NewMessage(ethwire.MsgHandshakeTy, []interface{}{
- P2PVersion, []byte(p.version), []interface{}{"eth"}, uint32(30303) /*p.port*/, pubkey[1:],
+ P2PVersion, []byte(p.version), []interface{}{"eth"}, p.port, pubkey[1:],
})
p.QueueMessage(msg)