aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-10-27 18:44:16 +0800
committerobscuren <geffobscura@gmail.com>2014-10-27 18:44:16 +0800
commit272d58662c885ab1cef8930e96fb832ae5377d96 (patch)
treee040eaec5c7e895dd6aaadedbbe30054aaa5e805
parent6623500c6b2e5fe9fa41a1ce75269955af6026e8 (diff)
downloadgo-tangerine-272d58662c885ab1cef8930e96fb832ae5377d96.tar
go-tangerine-272d58662c885ab1cef8930e96fb832ae5377d96.tar.gz
go-tangerine-272d58662c885ab1cef8930e96fb832ae5377d96.tar.bz2
go-tangerine-272d58662c885ab1cef8930e96fb832ae5377d96.tar.lz
go-tangerine-272d58662c885ab1cef8930e96fb832ae5377d96.tar.xz
go-tangerine-272d58662c885ab1cef8930e96fb832ae5377d96.tar.zst
go-tangerine-272d58662c885ab1cef8930e96fb832ae5377d96.zip
Implemented LOG. Closes #159
-rw-r--r--ethchain/state_transition.go6
-rw-r--r--ethchain/transaction.go7
-rw-r--r--ethchain/types.go4
-rw-r--r--ethchain/vm_env.go3
-rw-r--r--ethpipe/vm_env.go1
-rw-r--r--ethutil/common.go1
-rw-r--r--tests/helper/vm.go1
-rw-r--r--utils/vm_env.go1
-rw-r--r--vm/common.go1
-rw-r--r--vm/environment.go1
-rw-r--r--vm/log.go9
-rw-r--r--vm/stack.go12
-rw-r--r--vm/types.go10
-rw-r--r--vm/vm.go2
-rw-r--r--vm/vm_debug.go33
15 files changed, 81 insertions, 11 deletions
diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go
index 1274915d5..542b7be13 100644
--- a/ethchain/state_transition.go
+++ b/ethchain/state_transition.go
@@ -237,6 +237,12 @@ func (self *StateTransition) TransitionState() (err error) {
}
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})
}
}
diff --git a/ethchain/transaction.go b/ethchain/transaction.go
index c78c27ed6..b0743097d 100644
--- a/ethchain/transaction.go
+++ b/ethchain/transaction.go
@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/ethcrypto"
"github.com/ethereum/go-ethereum/ethstate"
"github.com/ethereum/go-ethereum/ethutil"
+ "github.com/ethereum/go-ethereum/vm"
"github.com/obscuren/secp256k1-go"
)
@@ -28,6 +29,8 @@ type Transaction struct {
v byte
r, s []byte
+ logs []vm.Log
+
// Indicates whether this tx is a contract creation transaction
contractCreation bool
}
@@ -54,6 +57,10 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
return tx
}
+func (self *Transaction) addLog(log vm.Log) {
+ self.logs = append(self.logs, log)
+}
+
func (self *Transaction) GasValue() *big.Int {
return new(big.Int).Mul(self.Gas, self.GasPrice)
}
diff --git a/ethchain/types.go b/ethchain/types.go
index 29084c749..d0e7fcfb0 100644
--- a/ethchain/types.go
+++ b/ethchain/types.go
@@ -18,7 +18,7 @@ const (
MOD = 0x06
SMOD = 0x07
EXP = 0x08
- NEG = 0x09
+ BNOT = 0x09
LT = 0x0a
GT = 0x0b
SLT = 0x0c
@@ -166,7 +166,7 @@ var opCodeToString = map[OpCode]string{
MOD: "MOD",
SMOD: "SMOD",
EXP: "EXP",
- NEG: "NEG",
+ BNOT: "BNOT",
LT: "LT",
GT: "GT",
SLT: "SLT",
diff --git a/ethchain/vm_env.go b/ethchain/vm_env.go
index 6dda27c6f..4dc96e8b1 100644
--- a/ethchain/vm_env.go
+++ b/ethchain/vm_env.go
@@ -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) State() *ethstate.State { return self.state }
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 {
return vm.Transfer(from, to, amount)
}
diff --git a/ethpipe/vm_env.go b/ethpipe/vm_env.go
index 140726bfe..9d11ecf34 100644
--- a/ethpipe/vm_env.go
+++ b/ethpipe/vm_env.go
@@ -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) State() *ethstate.State { return self.state }
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 {
return vm.Transfer(from, to, amount)
}
diff --git a/ethutil/common.go b/ethutil/common.go
index 8532d80f2..e60f237cf 100644
--- a/ethutil/common.go
+++ b/ethutil/common.go
@@ -77,6 +77,7 @@ func CurrencyToString(num *big.Int) string {
var (
Big1 = big.NewInt(1)
Big2 = big.NewInt(2)
+ Big3 = big.NewInt(3)
Big0 = big.NewInt(0)
BigTrue = Big1
BigFalse = Big0
diff --git a/tests/helper/vm.go b/tests/helper/vm.go
index 5660caf64..c56c5bae7 100644
--- a/tests/helper/vm.go
+++ b/tests/helper/vm.go
@@ -50,6 +50,7 @@ func (self *Env) Difficulty() *big.Int { return self.difficulty }
func (self *Env) BlockHash() []byte { return nil }
func (self *Env) State() *ethstate.State { return self.state }
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 {
return vm.Transfer(from, to, amount)
}
diff --git a/utils/vm_env.go b/utils/vm_env.go
index 1946b6fac..034d4a16e 100644
--- a/utils/vm_env.go
+++ b/utils/vm_env.go
@@ -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) State() *ethstate.State { return self.state }
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 {
return vm.Transfer(from, to, amount)
}
diff --git a/vm/common.go b/vm/common.go
index 3b0d735ba..c73744506 100644
--- a/vm/common.go
+++ b/vm/common.go
@@ -29,6 +29,7 @@ var (
GasMemory = big.NewInt(1)
GasData = big.NewInt(5)
GasTx = big.NewInt(500)
+ GasLog = big.NewInt(32)
Pow256 = ethutil.BigPow(2, 256)
diff --git a/vm/environment.go b/vm/environment.go
index af67c4179..b8013856e 100644
--- a/vm/environment.go
+++ b/vm/environment.go
@@ -20,6 +20,7 @@ type Environment interface {
BlockHash() []byte
GasLimit() *big.Int
Transfer(from, to Account, amount *big.Int) error
+ AddLog(Log)
}
type Object interface {
diff --git a/vm/log.go b/vm/log.go
new file mode 100644
index 000000000..954d2ec91
--- /dev/null
+++ b/vm/log.go
@@ -0,0 +1,9 @@
+package vm
+
+import "math/big"
+
+type Log struct {
+ Address []byte
+ Topics []*big.Int
+ Data []byte
+}
diff --git a/vm/stack.go b/vm/stack.go
index 55fdb6d15..69ded6562 100644
--- a/vm/stack.go
+++ b/vm/stack.go
@@ -139,6 +139,18 @@ func (m *Memory) Get(offset, size int64) []byte {
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 {
return len(m.store)
}
diff --git a/vm/types.go b/vm/types.go
index 6fb9a5c95..53178fa43 100644
--- a/vm/types.go
+++ b/vm/types.go
@@ -18,7 +18,7 @@ const (
MOD = 0x06
SMOD = 0x07
EXP = 0x08
- NEG = 0x09
+ BNOT = 0x09
LT = 0x0a
GT = 0x0b
SLT = 0x0c
@@ -144,6 +144,12 @@ const (
SWAP15 = 0x9e
SWAP16 = 0x9f
+ LOG0 = 0xa0
+ LOG1 = 0xa1
+ LOG2 = 0xa2
+ LOG3 = 0xa3
+ LOG4 = 0xa4
+
// 0xf0 range - closures
CREATE = 0xf0
CALL = 0xf1
@@ -166,7 +172,7 @@ var opCodeToString = map[OpCode]string{
MOD: "MOD",
SMOD: "SMOD",
EXP: "EXP",
- NEG: "NEG",
+ BNOT: "BNOT",
LT: "LT",
GT: "GT",
SLT: "SLT",
diff --git a/vm/vm.go b/vm/vm.go
index 291f1cda4..599c8ca41 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -268,7 +268,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
U256(base)
stack.Push(base)
- case NEG:
+ case BNOT:
require(1)
base.Sub(Pow256, stack.Pop())
diff --git a/vm/vm_debug.go b/vm/vm_debug.go
index a30339e2b..13446d6c0 100644
--- a/vm/vm_debug.go
+++ b/vm/vm_debug.go
@@ -141,7 +141,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// Stack Check, memory resize & gas phase
switch op {
// Stack checks only
- case NOT, CALLDATALOAD, POP, JUMP, NEG: // 1
+ case NOT, CALLDATALOAD, POP, JUMP, BNOT: // 1
require(1)
case ADD, SUB, DIV, SDIV, MOD, SMOD, EXP, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE: // 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:
n := int(op - DUP1 + 1)
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
case STOP:
gas.Set(ethutil.Big0)
@@ -168,13 +176,16 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
y, x := stack.Peekn()
val := closure.GetStorage(x)
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 {
+ //state.AddBalance(closure.caller.Address(), new(big.Int).Mul(big.NewInt(100), closure.Price))
mult = ethutil.Big0
} else {
+ // non 0 => non 0
mult = ethutil.Big1
}
- gas = new(big.Int).Mul(mult, GasSStore)
+ gas.Set(new(big.Int).Mul(mult, GasSStore))
case BALANCE:
require(1)
gas.Set(GasBalance)
@@ -375,10 +386,11 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" = %v", base)
stack.Push(base)
- case NEG:
- base.Sub(Pow256, stack.Pop())
+ case BNOT:
+ base.Sub(Pow256, stack.Pop()).Sub(base, ethutil.Big1)
- base = U256(base)
+ // Not needed
+ //base = U256(base)
stack.Push(base)
case LT:
@@ -685,6 +697,15 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
x, y := stack.Swapn(n)
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:
offset := stack.Pop()
val := ethutil.BigD(mem.Get(offset.Int64(), 32))