Changed prev_hash to block_hash, state transition now uses vm env
* PREVHASH => BLOCKHASH( N ) * State transition object uses VMEnv as it's query interface * Updated vm.Enviroment has GetHash( n ) for BLOCKHASH instruction * Added GetHash to xeth, core, utils & test environments
This commit is contained in:
parent
16f417f5af
commit
ca1b2a1a91
@ -151,7 +151,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
||||
|
||||
block := self.lib.eth.ChainManager().CurrentBlock()
|
||||
|
||||
env := utils.NewEnv(statedb, block, account.Address(), value)
|
||||
env := utils.NewEnv(self.lib.eth.ChainManager(), statedb, block, account.Address(), value)
|
||||
|
||||
self.Logf("callsize %d", len(script))
|
||||
go func() {
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
)
|
||||
|
||||
type VMEnv struct {
|
||||
chain *core.ChainManager
|
||||
state *state.StateDB
|
||||
block *types.Block
|
||||
|
||||
@ -20,8 +21,9 @@ type VMEnv struct {
|
||||
Gas *big.Int
|
||||
}
|
||||
|
||||
func NewEnv(state *state.StateDB, block *types.Block, transactor []byte, value *big.Int) *VMEnv {
|
||||
func NewEnv(chain *core.ChainManager, state *state.StateDB, block *types.Block, transactor []byte, value *big.Int) *VMEnv {
|
||||
return &VMEnv{
|
||||
chain: chain,
|
||||
state: state,
|
||||
block: block,
|
||||
transactor: transactor,
|
||||
@ -35,12 +37,18 @@ func (self *VMEnv) PrevHash() []byte { return self.block.ParentHash() }
|
||||
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() }
|
||||
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
||||
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
|
||||
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
|
||||
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() }
|
||||
func (self *VMEnv) Value() *big.Int { return self.value }
|
||||
func (self *VMEnv) State() *state.StateDB { return self.state }
|
||||
func (self *VMEnv) Depth() int { return self.depth }
|
||||
func (self *VMEnv) SetDepth(i int) { self.depth = i }
|
||||
func (self *VMEnv) GetHash(n uint64) []byte {
|
||||
if block := self.chain.GetBlockByNumber(n); block != nil {
|
||||
return block.Hash()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func (self *VMEnv) AddLog(log state.Log) {
|
||||
self.state.AddLog(log)
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ done:
|
||||
txGas := new(big.Int).Set(tx.Gas())
|
||||
|
||||
cb := state.GetStateObject(coinbase.Address())
|
||||
st := NewStateTransition(cb, tx, state, block)
|
||||
st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb)
|
||||
_, err = st.TransitionState()
|
||||
if err != nil {
|
||||
switch {
|
||||
@ -232,6 +232,8 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I
|
||||
// Sync the current block's state to the database and cancelling out the deferred Undo
|
||||
state.Sync()
|
||||
|
||||
state.Manifest().SetHash(block.Hash())
|
||||
|
||||
messages := state.Manifest().Messages
|
||||
state.Manifest().Reset()
|
||||
|
||||
@ -339,10 +341,10 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent
|
||||
account.AddAmount(reward)
|
||||
|
||||
statedb.Manifest().AddMessage(&state.Message{
|
||||
To: block.Header().Coinbase,
|
||||
Input: nil,
|
||||
Origin: nil,
|
||||
Block: block.Hash(), Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number,
|
||||
To: block.Header().Coinbase,
|
||||
Input: nil,
|
||||
Origin: nil,
|
||||
Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number,
|
||||
Value: new(big.Int).Add(reward, block.Reward),
|
||||
})
|
||||
|
||||
|
@ -271,15 +271,15 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
|
||||
self.mu.RLock()
|
||||
defer self.mu.RUnlock()
|
||||
|
||||
block := self.currentBlock
|
||||
for ; block != nil; block = self.GetBlock(block.Header().ParentHash) {
|
||||
if block.Header().Number.Uint64() == num {
|
||||
break
|
||||
}
|
||||
}
|
||||
var block *types.Block
|
||||
|
||||
if block != nil && block.Header().Number.Uint64() == 0 && num != 0 {
|
||||
return nil
|
||||
if num <= self.currentBlock.Number().Uint64() {
|
||||
block = self.currentBlock
|
||||
for ; block != nil; block = self.GetBlock(block.Header().ParentHash) {
|
||||
if block.Header().Number.Uint64() == num {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return block
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethutil"
|
||||
"github.com/ethereum/go-ethereum/state"
|
||||
@ -28,18 +27,17 @@ import (
|
||||
* 6) Derive new state root
|
||||
*/
|
||||
type StateTransition struct {
|
||||
coinbase, receiver []byte
|
||||
msg Message
|
||||
gas, gasPrice *big.Int
|
||||
initialGas *big.Int
|
||||
value *big.Int
|
||||
data []byte
|
||||
state *state.StateDB
|
||||
block *types.Block
|
||||
coinbase []byte
|
||||
msg Message
|
||||
gas, gasPrice *big.Int
|
||||
initialGas *big.Int
|
||||
value *big.Int
|
||||
data []byte
|
||||
state *state.StateDB
|
||||
|
||||
cb, rec, sen *state.StateObject
|
||||
|
||||
Env vm.Environment
|
||||
env vm.Environment
|
||||
}
|
||||
|
||||
type Message interface {
|
||||
@ -69,16 +67,19 @@ func MessageGasValue(msg Message) *big.Int {
|
||||
return new(big.Int).Mul(msg.Gas(), msg.GasPrice())
|
||||
}
|
||||
|
||||
func NewStateTransition(coinbase *state.StateObject, msg Message, state *state.StateDB, block *types.Block) *StateTransition {
|
||||
return &StateTransition{coinbase.Address(), msg.To(), msg, new(big.Int), new(big.Int).Set(msg.GasPrice()), new(big.Int), msg.Value(), msg.Data(), state, block, coinbase, nil, nil, nil}
|
||||
}
|
||||
|
||||
func (self *StateTransition) VmEnv() vm.Environment {
|
||||
if self.Env == nil {
|
||||
self.Env = NewEnv(self.state, self.msg, self.block)
|
||||
func NewStateTransition(env vm.Environment, msg Message, coinbase *state.StateObject) *StateTransition {
|
||||
return &StateTransition{
|
||||
coinbase: coinbase.Address(),
|
||||
env: env,
|
||||
msg: msg,
|
||||
gas: new(big.Int),
|
||||
gasPrice: new(big.Int).Set(msg.GasPrice()),
|
||||
initialGas: new(big.Int),
|
||||
value: msg.Value(),
|
||||
data: msg.Data(),
|
||||
state: env.State(),
|
||||
cb: coinbase,
|
||||
}
|
||||
|
||||
return self.Env
|
||||
}
|
||||
|
||||
func (self *StateTransition) Coinbase() *state.StateObject {
|
||||
@ -183,7 +184,7 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
vmenv := self.VmEnv()
|
||||
vmenv := self.env
|
||||
var ref vm.ContextRef
|
||||
if MessageCreatesContract(msg) {
|
||||
contract := MakeContract(msg, self.state)
|
||||
|
@ -13,10 +13,12 @@ type VMEnv struct {
|
||||
block *types.Block
|
||||
msg Message
|
||||
depth int
|
||||
chain *ChainManager
|
||||
}
|
||||
|
||||
func NewEnv(state *state.StateDB, msg Message, block *types.Block) *VMEnv {
|
||||
func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types.Block) *VMEnv {
|
||||
return &VMEnv{
|
||||
chain: chain,
|
||||
state: state,
|
||||
block: block,
|
||||
msg: msg,
|
||||
@ -25,16 +27,21 @@ func NewEnv(state *state.StateDB, msg Message, block *types.Block) *VMEnv {
|
||||
|
||||
func (self *VMEnv) Origin() []byte { return self.msg.From() }
|
||||
func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() }
|
||||
func (self *VMEnv) PrevHash() []byte { return self.block.ParentHash() }
|
||||
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() }
|
||||
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
||||
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
|
||||
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
|
||||
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() }
|
||||
func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
|
||||
func (self *VMEnv) State() *state.StateDB { return self.state }
|
||||
func (self *VMEnv) Depth() int { return self.depth }
|
||||
func (self *VMEnv) SetDepth(i int) { self.depth = i }
|
||||
func (self *VMEnv) GetHash(n uint64) []byte {
|
||||
if block := self.chain.GetBlockByNumber(n); block != nil {
|
||||
return block.Hash()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func (self *VMEnv) AddLog(log state.Log) {
|
||||
self.state.AddLog(log)
|
||||
}
|
||||
|
@ -30,6 +30,12 @@ func (self *Manifest) AddMessage(msg *Message) *Message {
|
||||
return msg
|
||||
}
|
||||
|
||||
func (self *Manifest) SetHash(hash []byte) {
|
||||
for _, message := range self.Messages {
|
||||
message.Block = hash
|
||||
}
|
||||
}
|
||||
|
||||
type Messages []*Message
|
||||
type Message struct {
|
||||
To, From []byte
|
||||
|
@ -55,9 +55,11 @@ func (self *Env) PrevHash() []byte { return self.parent }
|
||||
func (self *Env) Coinbase() []byte { return self.coinbase }
|
||||
func (self *Env) Time() int64 { return self.time }
|
||||
func (self *Env) Difficulty() *big.Int { return self.difficulty }
|
||||
func (self *Env) BlockHash() []byte { return nil }
|
||||
func (self *Env) State() *state.StateDB { return self.state }
|
||||
func (self *Env) GasLimit() *big.Int { return self.gasLimit }
|
||||
func (self *Env) GetHash(n uint64) []byte {
|
||||
return nil
|
||||
}
|
||||
func (self *Env) AddLog(log state.Log) {
|
||||
self.logs = append(self.logs, log)
|
||||
}
|
||||
@ -126,10 +128,9 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.
|
||||
|
||||
message := NewMessage(keyPair.Address(), to, data, value, gas, price)
|
||||
Log.DebugDetailf("message{ to: %x, from %x, value: %v, gas: %v, price: %v }\n", message.to[:4], message.from[:4], message.value, message.gas, message.price)
|
||||
st := core.NewStateTransition(coinbase, message, statedb, nil)
|
||||
vmenv := NewEnvFromMap(statedb, env, tx)
|
||||
st := core.NewStateTransition(vmenv, message, coinbase)
|
||||
vmenv.origin = keyPair.Address()
|
||||
st.Env = vmenv
|
||||
ret, err := st.TransitionState()
|
||||
statedb.Update(vmenv.Gas)
|
||||
|
||||
|
@ -14,11 +14,10 @@ type Environment interface {
|
||||
|
||||
Origin() []byte
|
||||
BlockNumber() *big.Int
|
||||
PrevHash() []byte
|
||||
GetHash(n uint64) []byte
|
||||
Coinbase() []byte
|
||||
Time() int64
|
||||
Difficulty() *big.Int
|
||||
BlockHash() []byte
|
||||
GasLimit() *big.Int
|
||||
Transfer(from, to Account, amount *big.Int) error
|
||||
AddLog(state.Log)
|
||||
|
@ -59,7 +59,7 @@ const (
|
||||
const (
|
||||
|
||||
// 0x40 range - block operations
|
||||
PREVHASH OpCode = 0x40 + iota
|
||||
BLOCKHASH OpCode = 0x40 + iota
|
||||
COINBASE
|
||||
TIMESTAMP
|
||||
NUMBER
|
||||
@ -216,7 +216,7 @@ var opCodeToString = map[OpCode]string{
|
||||
GASPRICE: "TXGASPRICE",
|
||||
|
||||
// 0x40 range - block operations
|
||||
PREVHASH: "PREVHASH",
|
||||
BLOCKHASH: "BLOCKHASH",
|
||||
COINBASE: "COINBASE",
|
||||
TIMESTAMP: "TIMESTAMP",
|
||||
NUMBER: "NUMBER",
|
||||
|
@ -42,9 +42,9 @@ func (self *DebugVm) Run(me, caller ContextRef, code []byte, value, gas, price *
|
||||
|
||||
msg := self.env.State().Manifest().AddMessage(&state.Message{
|
||||
To: me.Address(), From: caller.Address(),
|
||||
Input: callData,
|
||||
Origin: self.env.Origin(),
|
||||
Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(),
|
||||
Input: callData,
|
||||
Origin: self.env.Origin(),
|
||||
Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(),
|
||||
Value: value,
|
||||
})
|
||||
context := NewContext(msg, caller, me, code, gas, price)
|
||||
@ -516,12 +516,15 @@ func (self *DebugVm) Run(me, caller ContextRef, code []byte, value, gas, price *
|
||||
self.Printf(" => %v", context.Price)
|
||||
|
||||
// 0x40 range
|
||||
case PREVHASH:
|
||||
prevHash := self.env.PrevHash()
|
||||
case BLOCKHASH:
|
||||
num := stack.Pop()
|
||||
if num.Cmp(new(big.Int).Sub(self.env.BlockNumber(), ethutil.Big256)) < 0 {
|
||||
stack.Push(ethutil.Big0)
|
||||
} else {
|
||||
stack.Push(ethutil.BigD(self.env.GetHash(num.Uint64())))
|
||||
}
|
||||
|
||||
stack.Push(ethutil.BigD(prevHash))
|
||||
|
||||
self.Printf(" => 0x%x", prevHash)
|
||||
self.Printf(" => 0x%x", stack.Peek().Bytes())
|
||||
case COINBASE:
|
||||
coinbase := self.env.Coinbase()
|
||||
|
||||
|
@ -87,7 +87,7 @@ func (self *XEth) ExecuteObject(object *Object, data []byte, value, gas, price *
|
||||
|
||||
self.Vm.State = self.World().State().Copy()
|
||||
|
||||
vmenv := NewEnv(self.Vm.State, block, value.BigInt(), initiator.Address())
|
||||
vmenv := NewEnv(self.chainManager, self.Vm.State, block, value.BigInt(), initiator.Address())
|
||||
return vmenv.Call(initiator, object.Address(), data, gas.BigInt(), price.BigInt(), value.BigInt())
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
)
|
||||
|
||||
type VMEnv struct {
|
||||
chain *core.ChainManager
|
||||
state *state.StateDB
|
||||
block *types.Block
|
||||
value *big.Int
|
||||
@ -18,7 +19,7 @@ type VMEnv struct {
|
||||
depth int
|
||||
}
|
||||
|
||||
func NewEnv(state *state.StateDB, block *types.Block, value *big.Int, sender []byte) *VMEnv {
|
||||
func NewEnv(chain *core.ChainManager, state *state.StateDB, block *types.Block, value *big.Int, sender []byte) *VMEnv {
|
||||
return &VMEnv{
|
||||
state: state,
|
||||
block: block,
|
||||
@ -33,12 +34,18 @@ func (self *VMEnv) PrevHash() []byte { return self.block.ParentHash() }
|
||||
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() }
|
||||
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
||||
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
|
||||
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
|
||||
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() }
|
||||
func (self *VMEnv) Value() *big.Int { return self.value }
|
||||
func (self *VMEnv) State() *state.StateDB { return self.state }
|
||||
func (self *VMEnv) Depth() int { return self.depth }
|
||||
func (self *VMEnv) SetDepth(i int) { self.depth = i }
|
||||
func (self *VMEnv) GetHash(n uint64) []byte {
|
||||
if block := self.chain.GetBlockByNumber(n); block != nil {
|
||||
return block.Hash()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func (self *VMEnv) AddLog(log state.Log) {
|
||||
self.state.AddLog(log)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user