Updated GHOST
This commit is contained in:
parent
4db4ec1621
commit
2f614900e8
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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, ðstate.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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
57
ethvm/vm.go
57
ethvm/vm.go
|
@ -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:
|
||||||
|
|
2
peer.go
2
peer.go
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue