Implemented LOG. Closes #159
This commit is contained in:
parent
6623500c6b
commit
272d58662c
@ -237,6 +237,12 @@ func (self *StateTransition) TransitionState() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg.Output = ret
|
msg.Output = ret
|
||||||
|
} else {
|
||||||
|
// Add default LOG
|
||||||
|
// PUSH1 1 CALLER ADD LOG1
|
||||||
|
addr := ethutil.BigD(sender.Address())
|
||||||
|
addr.Add(addr, ethutil.Big1)
|
||||||
|
tx.addLog(vm.Log{sender.Address(), []*big.Int{addr}, nil})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/ethcrypto"
|
"github.com/ethereum/go-ethereum/ethcrypto"
|
||||||
"github.com/ethereum/go-ethereum/ethstate"
|
"github.com/ethereum/go-ethereum/ethstate"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
|
"github.com/ethereum/go-ethereum/vm"
|
||||||
"github.com/obscuren/secp256k1-go"
|
"github.com/obscuren/secp256k1-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,6 +29,8 @@ type Transaction struct {
|
|||||||
v byte
|
v byte
|
||||||
r, s []byte
|
r, s []byte
|
||||||
|
|
||||||
|
logs []vm.Log
|
||||||
|
|
||||||
// Indicates whether this tx is a contract creation transaction
|
// Indicates whether this tx is a contract creation transaction
|
||||||
contractCreation bool
|
contractCreation bool
|
||||||
}
|
}
|
||||||
@ -54,6 +57,10 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
|
|||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Transaction) addLog(log vm.Log) {
|
||||||
|
self.logs = append(self.logs, log)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Transaction) GasValue() *big.Int {
|
func (self *Transaction) GasValue() *big.Int {
|
||||||
return new(big.Int).Mul(self.Gas, self.GasPrice)
|
return new(big.Int).Mul(self.Gas, self.GasPrice)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ const (
|
|||||||
MOD = 0x06
|
MOD = 0x06
|
||||||
SMOD = 0x07
|
SMOD = 0x07
|
||||||
EXP = 0x08
|
EXP = 0x08
|
||||||
NEG = 0x09
|
BNOT = 0x09
|
||||||
LT = 0x0a
|
LT = 0x0a
|
||||||
GT = 0x0b
|
GT = 0x0b
|
||||||
SLT = 0x0c
|
SLT = 0x0c
|
||||||
@ -166,7 +166,7 @@ var opCodeToString = map[OpCode]string{
|
|||||||
MOD: "MOD",
|
MOD: "MOD",
|
||||||
SMOD: "SMOD",
|
SMOD: "SMOD",
|
||||||
EXP: "EXP",
|
EXP: "EXP",
|
||||||
NEG: "NEG",
|
BNOT: "BNOT",
|
||||||
LT: "LT",
|
LT: "LT",
|
||||||
GT: "GT",
|
GT: "GT",
|
||||||
SLT: "SLT",
|
SLT: "SLT",
|
||||||
|
@ -31,6 +31,9 @@ func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
|
|||||||
func (self *VMEnv) Value() *big.Int { return self.tx.Value }
|
func (self *VMEnv) Value() *big.Int { return self.tx.Value }
|
||||||
func (self *VMEnv) State() *ethstate.State { return self.state }
|
func (self *VMEnv) State() *ethstate.State { return self.state }
|
||||||
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit }
|
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit }
|
||||||
|
func (self *VMEnv) AddLog(log vm.Log) {
|
||||||
|
self.tx.addLog(log)
|
||||||
|
}
|
||||||
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
|
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
|
||||||
return vm.Transfer(from, to, amount)
|
return vm.Transfer(from, to, amount)
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
|
|||||||
func (self *VMEnv) Value() *big.Int { return self.value }
|
func (self *VMEnv) Value() *big.Int { return self.value }
|
||||||
func (self *VMEnv) State() *ethstate.State { return self.state }
|
func (self *VMEnv) State() *ethstate.State { return self.state }
|
||||||
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit }
|
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit }
|
||||||
|
func (self *VMEnv) AddLog(vm.Log) {}
|
||||||
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
|
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
|
||||||
return vm.Transfer(from, to, amount)
|
return vm.Transfer(from, to, amount)
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@ func CurrencyToString(num *big.Int) string {
|
|||||||
var (
|
var (
|
||||||
Big1 = big.NewInt(1)
|
Big1 = big.NewInt(1)
|
||||||
Big2 = big.NewInt(2)
|
Big2 = big.NewInt(2)
|
||||||
|
Big3 = big.NewInt(3)
|
||||||
Big0 = big.NewInt(0)
|
Big0 = big.NewInt(0)
|
||||||
BigTrue = Big1
|
BigTrue = Big1
|
||||||
BigFalse = Big0
|
BigFalse = Big0
|
||||||
|
@ -50,6 +50,7 @@ func (self *Env) Difficulty() *big.Int { return self.difficulty }
|
|||||||
func (self *Env) BlockHash() []byte { return nil }
|
func (self *Env) BlockHash() []byte { return nil }
|
||||||
func (self *Env) State() *ethstate.State { return self.state }
|
func (self *Env) State() *ethstate.State { return self.state }
|
||||||
func (self *Env) GasLimit() *big.Int { return self.gasLimit }
|
func (self *Env) GasLimit() *big.Int { return self.gasLimit }
|
||||||
|
func (self *Env) AddLog(vm.Log) {}
|
||||||
func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error {
|
func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error {
|
||||||
return vm.Transfer(from, to, amount)
|
return vm.Transfer(from, to, amount)
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
|
|||||||
func (self *VMEnv) Value() *big.Int { return self.value }
|
func (self *VMEnv) Value() *big.Int { return self.value }
|
||||||
func (self *VMEnv) State() *ethstate.State { return self.state }
|
func (self *VMEnv) State() *ethstate.State { return self.state }
|
||||||
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit }
|
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit }
|
||||||
|
func (self *VMEnv) AddLog(vm.Log) {}
|
||||||
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
|
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
|
||||||
return vm.Transfer(from, to, amount)
|
return vm.Transfer(from, to, amount)
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ var (
|
|||||||
GasMemory = big.NewInt(1)
|
GasMemory = big.NewInt(1)
|
||||||
GasData = big.NewInt(5)
|
GasData = big.NewInt(5)
|
||||||
GasTx = big.NewInt(500)
|
GasTx = big.NewInt(500)
|
||||||
|
GasLog = big.NewInt(32)
|
||||||
|
|
||||||
Pow256 = ethutil.BigPow(2, 256)
|
Pow256 = ethutil.BigPow(2, 256)
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ type Environment interface {
|
|||||||
BlockHash() []byte
|
BlockHash() []byte
|
||||||
GasLimit() *big.Int
|
GasLimit() *big.Int
|
||||||
Transfer(from, to Account, amount *big.Int) error
|
Transfer(from, to Account, amount *big.Int) error
|
||||||
|
AddLog(Log)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Object interface {
|
type Object interface {
|
||||||
|
9
vm/log.go
Normal file
9
vm/log.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package vm
|
||||||
|
|
||||||
|
import "math/big"
|
||||||
|
|
||||||
|
type Log struct {
|
||||||
|
Address []byte
|
||||||
|
Topics []*big.Int
|
||||||
|
Data []byte
|
||||||
|
}
|
12
vm/stack.go
12
vm/stack.go
@ -139,6 +139,18 @@ func (m *Memory) Get(offset, size int64) []byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Memory) Geti(offset, size int64) (cpy []byte) {
|
||||||
|
if len(self.store) > int(offset) {
|
||||||
|
s := int64(math.Min(float64(len(self.store)), float64(offset+size)))
|
||||||
|
cpy = make([]byte, size)
|
||||||
|
copy(cpy, self.store[offset:offset+s])
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Memory) Len() int {
|
func (m *Memory) Len() int {
|
||||||
return len(m.store)
|
return len(m.store)
|
||||||
}
|
}
|
||||||
|
10
vm/types.go
10
vm/types.go
@ -18,7 +18,7 @@ const (
|
|||||||
MOD = 0x06
|
MOD = 0x06
|
||||||
SMOD = 0x07
|
SMOD = 0x07
|
||||||
EXP = 0x08
|
EXP = 0x08
|
||||||
NEG = 0x09
|
BNOT = 0x09
|
||||||
LT = 0x0a
|
LT = 0x0a
|
||||||
GT = 0x0b
|
GT = 0x0b
|
||||||
SLT = 0x0c
|
SLT = 0x0c
|
||||||
@ -144,6 +144,12 @@ const (
|
|||||||
SWAP15 = 0x9e
|
SWAP15 = 0x9e
|
||||||
SWAP16 = 0x9f
|
SWAP16 = 0x9f
|
||||||
|
|
||||||
|
LOG0 = 0xa0
|
||||||
|
LOG1 = 0xa1
|
||||||
|
LOG2 = 0xa2
|
||||||
|
LOG3 = 0xa3
|
||||||
|
LOG4 = 0xa4
|
||||||
|
|
||||||
// 0xf0 range - closures
|
// 0xf0 range - closures
|
||||||
CREATE = 0xf0
|
CREATE = 0xf0
|
||||||
CALL = 0xf1
|
CALL = 0xf1
|
||||||
@ -166,7 +172,7 @@ var opCodeToString = map[OpCode]string{
|
|||||||
MOD: "MOD",
|
MOD: "MOD",
|
||||||
SMOD: "SMOD",
|
SMOD: "SMOD",
|
||||||
EXP: "EXP",
|
EXP: "EXP",
|
||||||
NEG: "NEG",
|
BNOT: "BNOT",
|
||||||
LT: "LT",
|
LT: "LT",
|
||||||
GT: "GT",
|
GT: "GT",
|
||||||
SLT: "SLT",
|
SLT: "SLT",
|
||||||
|
2
vm/vm.go
2
vm/vm.go
@ -268,7 +268,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
U256(base)
|
U256(base)
|
||||||
|
|
||||||
stack.Push(base)
|
stack.Push(base)
|
||||||
case NEG:
|
case BNOT:
|
||||||
require(1)
|
require(1)
|
||||||
base.Sub(Pow256, stack.Pop())
|
base.Sub(Pow256, stack.Pop())
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
// Stack Check, memory resize & gas phase
|
// Stack Check, memory resize & gas phase
|
||||||
switch op {
|
switch op {
|
||||||
// Stack checks only
|
// Stack checks only
|
||||||
case NOT, CALLDATALOAD, POP, JUMP, NEG: // 1
|
case NOT, CALLDATALOAD, POP, JUMP, BNOT: // 1
|
||||||
require(1)
|
require(1)
|
||||||
case ADD, SUB, DIV, SDIV, MOD, SMOD, EXP, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE: // 2
|
case ADD, SUB, DIV, SDIV, MOD, SMOD, EXP, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE: // 2
|
||||||
require(2)
|
require(2)
|
||||||
@ -153,6 +153,14 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
||||||
n := int(op - DUP1 + 1)
|
n := int(op - DUP1 + 1)
|
||||||
require(n)
|
require(n)
|
||||||
|
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||||
|
n := int(op - LOG0)
|
||||||
|
require(n + 2)
|
||||||
|
|
||||||
|
mSize, mStart := stack.Peekn()
|
||||||
|
gas.Set(GasLog)
|
||||||
|
addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog))
|
||||||
|
addStepGasUsage(new(big.Int).Add(mSize, mStart))
|
||||||
// Gas only
|
// Gas only
|
||||||
case STOP:
|
case STOP:
|
||||||
gas.Set(ethutil.Big0)
|
gas.Set(ethutil.Big0)
|
||||||
@ -168,13 +176,16 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
y, x := stack.Peekn()
|
y, x := stack.Peekn()
|
||||||
val := closure.GetStorage(x)
|
val := closure.GetStorage(x)
|
||||||
if val.BigInt().Cmp(ethutil.Big0) == 0 && len(y.Bytes()) > 0 {
|
if val.BigInt().Cmp(ethutil.Big0) == 0 && len(y.Bytes()) > 0 {
|
||||||
mult = ethutil.Big2
|
// 0 => non 0
|
||||||
|
mult = ethutil.Big3
|
||||||
} else if val.BigInt().Cmp(ethutil.Big0) != 0 && len(y.Bytes()) == 0 {
|
} else if val.BigInt().Cmp(ethutil.Big0) != 0 && len(y.Bytes()) == 0 {
|
||||||
|
//state.AddBalance(closure.caller.Address(), new(big.Int).Mul(big.NewInt(100), closure.Price))
|
||||||
mult = ethutil.Big0
|
mult = ethutil.Big0
|
||||||
} else {
|
} else {
|
||||||
|
// non 0 => non 0
|
||||||
mult = ethutil.Big1
|
mult = ethutil.Big1
|
||||||
}
|
}
|
||||||
gas = new(big.Int).Mul(mult, GasSStore)
|
gas.Set(new(big.Int).Mul(mult, GasSStore))
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
require(1)
|
require(1)
|
||||||
gas.Set(GasBalance)
|
gas.Set(GasBalance)
|
||||||
@ -375,10 +386,11 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
self.Printf(" = %v", base)
|
self.Printf(" = %v", base)
|
||||||
|
|
||||||
stack.Push(base)
|
stack.Push(base)
|
||||||
case NEG:
|
case BNOT:
|
||||||
base.Sub(Pow256, stack.Pop())
|
base.Sub(Pow256, stack.Pop()).Sub(base, ethutil.Big1)
|
||||||
|
|
||||||
base = U256(base)
|
// Not needed
|
||||||
|
//base = U256(base)
|
||||||
|
|
||||||
stack.Push(base)
|
stack.Push(base)
|
||||||
case LT:
|
case LT:
|
||||||
@ -685,6 +697,15 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
|
|||||||
x, y := stack.Swapn(n)
|
x, y := stack.Swapn(n)
|
||||||
|
|
||||||
self.Printf(" => [%d] %x [0] %x", n, x.Bytes(), y.Bytes())
|
self.Printf(" => [%d] %x [0] %x", n, x.Bytes(), y.Bytes())
|
||||||
|
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||||
|
n := int(op - LOG0)
|
||||||
|
topics := make([]*big.Int, n)
|
||||||
|
mSize, mStart := stack.Pop().Int64(), stack.Pop().Int64()
|
||||||
|
data := mem.Geti(mStart, mSize)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
topics[i] = stack.Pop()
|
||||||
|
}
|
||||||
|
self.env.AddLog(Log{closure.Address(), topics, data})
|
||||||
case MLOAD:
|
case MLOAD:
|
||||||
offset := stack.Pop()
|
offset := stack.Pop()
|
||||||
val := ethutil.BigD(mem.Get(offset.Int64(), 32))
|
val := ethutil.BigD(mem.Get(offset.Int64(), 32))
|
||||||
|
Loading…
Reference in New Issue
Block a user