Updated GHOST

This commit is contained in:
obscuren 2014-09-15 01:11:01 +02:00
parent 4db4ec1621
commit 2f614900e8
7 changed files with 104 additions and 69 deletions

View File

@ -31,11 +31,22 @@ func (bi *BlockInfo) RlpEncode() []byte {
return ethutil.Encode([]interface{}{bi.Number, bi.Hash, bi.Parent}) 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 { type Block struct {
// Hash to the previous block // Hash to the previous block
PrevHash []byte PrevHash []byte
// Uncles of this block // Uncles of this block
Uncles []*Block Uncles Blocks
UncleSha []byte UncleSha []byte
// The coin base address // The coin base address
Coinbase []byte Coinbase []byte

View File

@ -60,7 +60,7 @@ func (bc *BlockChain) NewBlock(coinbase []byte) *Block {
if bc.CurrentBlock != nil { if bc.CurrentBlock != nil {
var mul *big.Int var mul *big.Int
if block.Time < lastBlockTime+42 { if block.Time < lastBlockTime+5 {
mul = big.NewInt(1) mul = big.NewInt(1)
} else { } else {
mul = big.NewInt(-1) mul = big.NewInt(-1)

View File

@ -25,6 +25,24 @@ func IsParentErr(err error) bool {
return ok 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 // Block validation error. If any validation fails, this error will be thrown
type ValidationErr struct { type ValidationErr struct {
Message string Message string

View File

@ -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 // I'm not sure, but I don't know if there should be thrown
// any errors at this time. // 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) statelogger.Errorln("Error accumulating reward", err)
return err return err
} }
@ -334,35 +334,43 @@ func (sm *StateManager) ValidateBlock(block *Block) error {
return nil return nil
} }
func CalculateBlockReward(block *Block, uncleLength int) *big.Int { func (sm *StateManager) AccumelateRewards(state *ethstate.State, block, parent *Block) error {
base := new(big.Int) reward := new(big.Int)
for i := 0; i < uncleLength; i++ {
base.Add(base, UncleInclusionReward) 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")
} }
return base.Add(base, BlockReward) uncleParent := sm.bc.GetBlock(uncle.PrevHash)
if uncleParent == nil {
return UncleError("Uncle's parent unknown")
} }
func CalculateUncleReward(block *Block) *big.Int { if uncleParent.Number.Cmp(new(big.Int).Sub(parent.Number, big.NewInt(6))) < 0 {
return UncleReward return UncleError("Uncle too old")
}
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))
uncleAccount := state.GetAccount(uncle.Coinbase)
uncleAccount.AddAmount(r)
reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
} }
func (sm *StateManager) AccumelateRewards(state *ethstate.State, block *Block) error {
// Get the account associated with the coinbase // Get the account associated with the coinbase
account := state.GetAccount(block.Coinbase) account := state.GetAccount(block.Coinbase)
// Reward amount of ether to the coinbase address // Reward amount of ether to the coinbase address
account.AddAmount(CalculateBlockReward(block, len(block.Uncles))) account.AddAmount(reward)
addr := make([]byte, len(block.Coinbase))
copy(addr, block.Coinbase)
state.UpdateStateObject(account)
for _, uncle := range block.Uncles {
uncleAccount := state.GetAccount(uncle.Coinbase)
uncleAccount.AddAmount(CalculateUncleReward(uncle))
state.UpdateStateObject(uncleAccount)
}
return nil return nil
} }
@ -375,14 +383,6 @@ func (sm *StateManager) Stop() {
func (sm *StateManager) createBloomFilter(state *ethstate.State) *BloomFilter { func (sm *StateManager) createBloomFilter(state *ethstate.State) *BloomFilter {
bloomf := NewBloomFilter(nil) 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 { for _, msg := range state.Manifest().Messages {
bloomf.Set(msg.To) bloomf.Set(msg.To)
bloomf.Set(msg.From) bloomf.Set(msg.From)
@ -390,17 +390,6 @@ func (sm *StateManager) createBloomFilter(state *ethstate.State) *BloomFilter {
sm.Ethereum.Reactor().Post("messages", state.Manifest().Messages) 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 return bloomf
} }
@ -420,7 +409,7 @@ func (sm *StateManager) GetMessages(block *Block) (messages []*ethstate.Message,
sm.ApplyDiff(state, parent, block) sm.ApplyDiff(state, parent, block)
sm.AccumelateRewards(state, block) sm.AccumelateRewards(state, block, parent)
return state.Manifest().Messages, nil return state.Manifest().Messages, nil
} }

View File

@ -187,7 +187,7 @@ func (self *Miner) mineNewBlock() {
self.block.SetReceipts(receipts, txs) self.block.SetReceipts(receipts, txs)
// Accumulate the rewards included for this block // 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() self.block.State().Update()

View File

@ -3,7 +3,6 @@ package ethvm
import ( import (
"container/list" "container/list"
"fmt" "fmt"
"math"
"math/big" "math/big"
"github.com/ethereum/eth-go/ethcrypto" "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()} 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) { func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
if self.Recoverable { if self.Recoverable {
// Recover from any require exception // Recover from any require exception
@ -147,7 +159,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
addStepGasUsage(GasStep) addStepGasUsage(GasStep)
var newMemSize uint64 = 0 var newMemSize *big.Int = ethutil.Big0
switch op { switch op {
case STOP: case STOP:
gas.Set(ethutil.Big0) gas.Set(ethutil.Big0)
@ -171,57 +183,62 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
gas.Set(GasBalance) gas.Set(GasBalance)
case MSTORE: case MSTORE:
require(2) require(2)
newMemSize = stack.Peek().Uint64() + 32 newMemSize = calcMemSize(stack.Peek(), u256(32))
case MLOAD: case MLOAD:
require(1) require(1)
newMemSize = stack.Peek().Uint64() + 32 newMemSize = calcMemSize(stack.Peek(), u256(32))
case MSTORE8: case MSTORE8:
require(2) require(2)
newMemSize = stack.Peek().Uint64() + 1 newMemSize = calcMemSize(stack.Peek(), u256(1))
case RETURN: case RETURN:
require(2) require(2)
newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-2].Uint64() newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
case SHA3: case SHA3:
require(2) require(2)
gas.Set(GasSha) gas.Set(GasSha)
newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-2].Uint64() newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
case CALLDATACOPY: case CALLDATACOPY:
require(3) require(3)
newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-3].Uint64() newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
case CODECOPY: case CODECOPY:
require(3) require(3)
newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-3].Uint64() newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
case EXTCODECOPY: case EXTCODECOPY:
require(4) 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: case CALL, CALLSTATELESS:
require(7) require(7)
gas.Set(GasCall) gas.Set(GasCall)
addStepGasUsage(stack.data[stack.Len()-1]) addStepGasUsage(stack.data[stack.Len()-1])
x := stack.data[stack.Len()-6].Uint64() + stack.data[stack.Len()-7].Uint64() x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7])
y := stack.data[stack.Len()-4].Uint64() + stack.data[stack.Len()-5].Uint64() 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: case CREATE:
require(3) require(3)
gas.Set(GasCreate) 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 if newMemSize.Cmp(ethutil.Big0) > 0 {
newMemSize = (newMemSize + 31) / 32 * 32 //newMemSize = (newMemSize + 31) / 32 * 32
if newMemSize > uint64(mem.Len()) { newMemSize = newMemSize.Add(newMemSize, u256(31)).Div(newMemSize, u256(32)).Mul(newMemSize, u256(32))
m := GasMemory.Uint64() * (newMemSize - uint64(mem.Len())) / 32 //if newMemSize > uint64(mem.Len()) {
addStepGasUsage(big.NewInt(int64(m))) 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) { 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("(pc) %-3d -o- %-14s", pc, op.String())
self.Printf(" (g) %-3v (%v)", gas, closure.Gas) self.Printf(" (g) %-3v (%v)", gas, closure.Gas)
mem.Resize(newMemSize) mem.Resize(newMemSize.Uint64())
switch op { switch op {
case LOG: case LOG:

View File

@ -675,7 +675,7 @@ func (self *Peer) handleStatus(msg *ethwire.Msg) {
func (p *Peer) pushHandshake() error { func (p *Peer) pushHandshake() error {
pubkey := p.ethereum.KeyManager().PublicKey() pubkey := p.ethereum.KeyManager().PublicKey()
msg := ethwire.NewMessage(ethwire.MsgHandshakeTy, []interface{}{ 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) p.QueueMessage(msg)