converted vm
This commit is contained in:
parent
8ce6a36478
commit
515d9432fc
@ -4,6 +4,7 @@ import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/state"
|
||||
"github.com/ethereum/go-ethereum/vm"
|
||||
@ -11,26 +12,23 @@ import (
|
||||
|
||||
type Execution struct {
|
||||
env vm.Environment
|
||||
address, input []byte
|
||||
address *common.Address
|
||||
input []byte
|
||||
Gas, price, value *big.Int
|
||||
}
|
||||
|
||||
func NewExecution(env vm.Environment, address, input []byte, gas, gasPrice, value *big.Int) *Execution {
|
||||
func NewExecution(env vm.Environment, address *common.Address, input []byte, gas, gasPrice, value *big.Int) *Execution {
|
||||
return &Execution{env: env, address: address, input: input, Gas: gas, price: gasPrice, value: value}
|
||||
}
|
||||
|
||||
func (self *Execution) Addr() []byte {
|
||||
return self.address
|
||||
}
|
||||
|
||||
func (self *Execution) Call(codeAddr []byte, caller vm.ContextRef) ([]byte, error) {
|
||||
func (self *Execution) Call(codeAddr common.Address, caller vm.ContextRef) ([]byte, error) {
|
||||
// Retrieve the executing code
|
||||
code := self.env.State().GetCode(codeAddr)
|
||||
|
||||
return self.exec(code, codeAddr, caller)
|
||||
return self.exec(&codeAddr, code, caller)
|
||||
}
|
||||
|
||||
func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret []byte, err error) {
|
||||
func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.ContextRef) (ret []byte, err error) {
|
||||
env := self.env
|
||||
evm := vm.NewVm(env)
|
||||
if env.Depth() == vm.MaxCallDepth {
|
||||
@ -40,14 +38,15 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret
|
||||
}
|
||||
|
||||
vsnapshot := env.State().Copy()
|
||||
if len(self.address) == 0 {
|
||||
if self.address == nil {
|
||||
// Generate a new address
|
||||
nonce := env.State().GetNonce(caller.Address())
|
||||
self.address = crypto.CreateAddress(caller.Address(), nonce)
|
||||
addr := crypto.CreateAddress(caller.Address(), nonce)
|
||||
self.address = &addr
|
||||
env.State().SetNonce(caller.Address(), nonce+1)
|
||||
}
|
||||
|
||||
from, to := env.State().GetStateObject(caller.Address()), env.State().GetOrNewStateObject(self.address)
|
||||
from, to := env.State().GetStateObject(caller.Address()), env.State().GetOrNewStateObject(*self.address)
|
||||
err = env.Transfer(from, to, self.value)
|
||||
if err != nil {
|
||||
env.State().Set(vsnapshot)
|
||||
@ -73,8 +72,8 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret
|
||||
}
|
||||
|
||||
func (self *Execution) Create(caller vm.ContextRef) (ret []byte, err error, account *state.StateObject) {
|
||||
ret, err = self.exec(self.input, nil, caller)
|
||||
account = self.env.State().GetStateObject(self.address)
|
||||
ret, err = self.exec(nil, self.input, caller)
|
||||
account = self.env.State().GetStateObject(*self.address)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/state"
|
||||
)
|
||||
@ -16,8 +16,8 @@ type FilterOptions struct {
|
||||
Earliest int64
|
||||
Latest int64
|
||||
|
||||
Address [][]byte
|
||||
Topics [][][]byte
|
||||
Address []common.Address
|
||||
Topics [][]common.Hash
|
||||
|
||||
Skip int
|
||||
Max int
|
||||
@ -29,9 +29,9 @@ type Filter struct {
|
||||
earliest int64
|
||||
latest int64
|
||||
skip int
|
||||
address [][]byte
|
||||
address []common.Address
|
||||
max int
|
||||
topics [][][]byte
|
||||
topics [][]common.Hash
|
||||
|
||||
BlockCallback func(*types.Block)
|
||||
PendingCallback func(*types.Block)
|
||||
@ -67,11 +67,11 @@ func (self *Filter) SetLatestBlock(latest int64) {
|
||||
self.latest = latest
|
||||
}
|
||||
|
||||
func (self *Filter) SetAddress(addr [][]byte) {
|
||||
func (self *Filter) SetAddress(addr []common.Address) {
|
||||
self.address = addr
|
||||
}
|
||||
|
||||
func (self *Filter) SetTopics(topics [][][]byte) {
|
||||
func (self *Filter) SetTopics(topics [][]common.Hash) {
|
||||
self.topics = topics
|
||||
}
|
||||
|
||||
@ -131,9 +131,9 @@ func (self *Filter) Find() state.Logs {
|
||||
return logs[skip:]
|
||||
}
|
||||
|
||||
func includes(addresses [][]byte, a []byte) bool {
|
||||
func includes(addresses []common.Address, a common.Address) bool {
|
||||
for _, addr := range addresses {
|
||||
if !bytes.Equal(addr, a) {
|
||||
if addr != a {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -151,13 +151,13 @@ Logs:
|
||||
continue
|
||||
}
|
||||
|
||||
logTopics := make([][]byte, len(self.topics))
|
||||
logTopics := make([]common.Hash, len(self.topics))
|
||||
copy(logTopics, log.Topics())
|
||||
|
||||
for i, topics := range self.topics {
|
||||
for _, topic := range topics {
|
||||
var match bool
|
||||
if bytes.Equal(log.Topics()[i], topic) {
|
||||
if log.Topics()[i] == topic {
|
||||
match = true
|
||||
}
|
||||
if !match {
|
||||
@ -176,7 +176,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool {
|
||||
if len(self.address) > 0 {
|
||||
var included bool
|
||||
for _, addr := range self.address {
|
||||
if types.BloomLookup(block.Bloom(), addr) {
|
||||
if types.BloomLookup(block.Bloom(), addr.Hash()) {
|
||||
included = true
|
||||
break
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ import (
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/state"
|
||||
)
|
||||
|
||||
@ -26,12 +26,11 @@ var GenesisDiff = big.NewInt(131072)
|
||||
var GenesisGasLimit = big.NewInt(3141592)
|
||||
|
||||
func GenesisBlock(db common.Database) *types.Block {
|
||||
genesis := types.NewBlock(ZeroHash256, ZeroHash160, nil, GenesisDiff, 42, "")
|
||||
genesis := types.NewBlock(common.Hash{}, common.Address{}, common.Hash{}, GenesisDiff, 42, "")
|
||||
genesis.Header().Number = common.Big0
|
||||
genesis.Header().GasLimit = GenesisGasLimit
|
||||
genesis.Header().GasUsed = common.Big0
|
||||
genesis.Header().Time = 0
|
||||
genesis.Header().MixDigest = make([]byte, 32)
|
||||
|
||||
genesis.Td = common.Big0
|
||||
|
||||
@ -49,7 +48,7 @@ func GenesisBlock(db common.Database) *types.Block {
|
||||
statedb := state.New(genesis.Root(), db)
|
||||
for addr, account := range accounts {
|
||||
codedAddr := common.Hex2Bytes(addr)
|
||||
accountState := statedb.GetAccount(codedAddr)
|
||||
accountState := statedb.GetAccount(common.BytesToAddress(codedAddr))
|
||||
accountState.SetBalance(common.Big(account.Balance))
|
||||
statedb.UpdateStateObject(accountState)
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ var ()
|
||||
* 6) Derive new state root
|
||||
*/
|
||||
type StateTransition struct {
|
||||
coinbase []byte
|
||||
coinbase common.Address
|
||||
msg Message
|
||||
gas, gasPrice *big.Int
|
||||
initialGas *big.Int
|
||||
@ -119,7 +119,7 @@ func (self *StateTransition) BuyGas() error {
|
||||
|
||||
sender := self.From()
|
||||
if sender.Balance().Cmp(MessageGasValue(self.msg)) < 0 {
|
||||
return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address()[:4], MessageGasValue(self.msg), sender.Balance())
|
||||
return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address().Bytes()[:4], MessageGasValue(self.msg), sender.Balance())
|
||||
}
|
||||
|
||||
coinbase := self.Coinbase()
|
||||
@ -195,8 +195,9 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
|
||||
vmenv := self.env
|
||||
var ref vm.ContextRef
|
||||
if MessageCreatesContract(msg) {
|
||||
contract := makeContract(msg, self.state)
|
||||
ret, err, ref = vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value)
|
||||
//contract := makeContract(msg, self.state)
|
||||
//addr := contract.Address()
|
||||
ret, err, ref = vmenv.Create(sender, self.msg.Data(), self.gas, self.gasPrice, self.value)
|
||||
if err == nil {
|
||||
dataGas := big.NewInt(int64(len(ret)))
|
||||
dataGas.Mul(dataGas, vm.GasCreateByte)
|
||||
@ -230,7 +231,7 @@ func (self *StateTransition) refundGas() {
|
||||
for addr, ref := range self.state.Refunds() {
|
||||
refund := common.BigMin(uhalf, ref)
|
||||
self.gas.Add(self.gas, refund)
|
||||
self.state.AddBalance([]byte(addr), refund.Mul(refund, self.msg.GasPrice()))
|
||||
self.state.AddBalance(common.StringToAddress(addr), refund.Mul(refund, self.msg.GasPrice()))
|
||||
}
|
||||
|
||||
coinbase.RefundGas(self.gas, self.msg.GasPrice())
|
||||
@ -242,10 +243,13 @@ func (self *StateTransition) gasUsed() *big.Int {
|
||||
|
||||
// Converts an message in to a state object
|
||||
func makeContract(msg Message, state *state.StateDB) *state.StateObject {
|
||||
/*
|
||||
addr := AddressFromMessage(msg)
|
||||
|
||||
contract := state.GetOrNewStateObject(addr)
|
||||
contract.SetInitCode(msg.Data())
|
||||
|
||||
return contract
|
||||
*/
|
||||
return nil
|
||||
}
|
||||
|
@ -47,9 +47,9 @@ func bloom9(b []byte) *big.Int {
|
||||
return r
|
||||
}
|
||||
|
||||
func BloomLookup(bin, topic []byte) bool {
|
||||
bloom := common.BigD(bin)
|
||||
cmp := bloom9(crypto.Sha3(topic))
|
||||
func BloomLookup(bin Bloom, topic common.Hash) bool {
|
||||
bloom := bin.Big()
|
||||
cmp := bloom9(crypto.Sha3(topic[:]))
|
||||
|
||||
return bloom.And(bloom, cmp).Cmp(cmp) == 0
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
package types
|
||||
|
||||
import "math/big"
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
type BlockProcessor interface {
|
||||
Process(*Block) (*big.Int, error)
|
||||
@ -24,3 +28,7 @@ func (b *Bloom) SetBytes(d []byte) {
|
||||
b[i] = b[i]
|
||||
}
|
||||
}
|
||||
|
||||
func (b Bloom) Big() *big.Int {
|
||||
return common.Bytes2Big(b[:])
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types
|
||||
|
||||
func (self *VMEnv) Origin() common.Address { return self.msg.From() }
|
||||
func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() }
|
||||
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() }
|
||||
func (self *VMEnv) Coinbase() common.Address { 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) GasLimit() *big.Int { return self.block.GasLimit() }
|
||||
@ -40,12 +40,12 @@ func (self *VMEnv) Depth() int { return self.depth }
|
||||
func (self *VMEnv) SetDepth(i int) { self.depth = i }
|
||||
func (self *VMEnv) VmType() vm.Type { return self.typ }
|
||||
func (self *VMEnv) SetVmType(t vm.Type) { self.typ = t }
|
||||
func (self *VMEnv) GetHash(n uint64) []byte {
|
||||
func (self *VMEnv) GetHash(n uint64) common.Hash {
|
||||
if block := self.chain.GetBlockByNumber(n); block != nil {
|
||||
return block.Hash()
|
||||
}
|
||||
|
||||
return nil
|
||||
return common.Hash{}
|
||||
}
|
||||
func (self *VMEnv) AddLog(log state.Log) {
|
||||
self.state.AddLog(log)
|
||||
@ -54,20 +54,21 @@ func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
|
||||
return vm.Transfer(from, to, amount)
|
||||
}
|
||||
|
||||
func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *Execution {
|
||||
func (self *VMEnv) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *Execution {
|
||||
return NewExecution(self, addr, data, gas, price, value)
|
||||
}
|
||||
|
||||
func (self *VMEnv) Call(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
|
||||
exe := self.vm(addr, data, gas, price, value)
|
||||
exe := self.vm(&addr, data, gas, price, value)
|
||||
return exe.Call(addr, me)
|
||||
}
|
||||
func (self *VMEnv) CallCode(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
|
||||
exe := self.vm(me.Address(), data, gas, price, value)
|
||||
maddr := me.Address()
|
||||
exe := self.vm(&maddr, data, gas, price, value)
|
||||
return exe.Call(addr, me)
|
||||
}
|
||||
|
||||
func (self *VMEnv) Create(me vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) {
|
||||
exe := self.vm(common.Address{}, data, gas, price, value)
|
||||
exe := self.vm(nil, data, gas, price, value)
|
||||
return exe.Create(me)
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/crypto/ecies"
|
||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||
"github.com/ethereum/go-ethereum/crypto/sha3"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
)
|
||||
@ -47,8 +48,10 @@ func Sha3Hash(data ...[]byte) (h common.Hash) {
|
||||
}
|
||||
|
||||
// Creates an ethereum address given the bytes and the nonce
|
||||
func CreateAddress(b []byte, nonce uint64) []byte {
|
||||
return Sha3(common.NewValue([]interface{}{b, nonce}).Encode())[12:]
|
||||
func CreateAddress(b common.Address, nonce uint64) common.Address {
|
||||
data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
|
||||
return common.BytesToAddress(Sha3(data)[12:])
|
||||
//return Sha3(common.NewValue([]interface{}{b, nonce}).Encode())[12:]
|
||||
}
|
||||
|
||||
func Sha256(data []byte) []byte {
|
||||
|
@ -18,7 +18,7 @@ type Context struct {
|
||||
self ContextRef
|
||||
|
||||
Code []byte
|
||||
CodeAddr common.Address
|
||||
CodeAddr *common.Address
|
||||
|
||||
value, Gas, UsedGas, Price *big.Int
|
||||
|
||||
@ -108,7 +108,7 @@ func (self *Context) SetCode(code []byte) {
|
||||
self.Code = code
|
||||
}
|
||||
|
||||
func (self *Context) SetCallCode(addr common.Address, code []byte) {
|
||||
func (self *Context) SetCallCode(addr *common.Address, code []byte) {
|
||||
self.Code = code
|
||||
self.CodeAddr = addr
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ type Environment interface {
|
||||
|
||||
Origin() common.Address
|
||||
BlockNumber() *big.Int
|
||||
GetHash(n uint64) []byte
|
||||
Coinbase() []byte
|
||||
GetHash(n uint64) common.Hash
|
||||
Coinbase() common.Address
|
||||
Time() int64
|
||||
Difficulty() *big.Int
|
||||
GasLimit() *big.Int
|
||||
@ -38,7 +38,7 @@ type Account interface {
|
||||
SubBalance(amount *big.Int)
|
||||
AddBalance(amount *big.Int)
|
||||
Balance() *big.Int
|
||||
Address() []byte
|
||||
Address() common.Address
|
||||
}
|
||||
|
||||
// generic transfer method
|
||||
|
6
vm/vm.go
6
vm/vm.go
@ -58,9 +58,11 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
||||
}()
|
||||
}
|
||||
|
||||
if context.CodeAddr != nil {
|
||||
if p := Precompiled[context.CodeAddr.Str()]; p != nil {
|
||||
return self.RunPrecompiled(p, callData, context)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
op OpCode
|
||||
@ -500,7 +502,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
||||
|
||||
n := new(big.Int).Sub(self.env.BlockNumber(), common.Big257)
|
||||
if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 {
|
||||
stack.push(common.BigD(self.env.GetHash(num.Uint64())))
|
||||
stack.push(self.env.GetHash(num.Uint64()).Big())
|
||||
} else {
|
||||
stack.push(common.Big0)
|
||||
}
|
||||
@ -509,7 +511,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
|
||||
case COINBASE:
|
||||
coinbase := self.env.Coinbase()
|
||||
|
||||
stack.push(common.BigD(coinbase))
|
||||
stack.push(coinbase.Big())
|
||||
|
||||
self.Printf(" => 0x%x", coinbase)
|
||||
case TIMESTAMP:
|
||||
|
Loading…
Reference in New Issue
Block a user