diff options
-rw-r--r-- | cmd/mist/flags.go | 2 | ||||
-rw-r--r-- | ethchain/bloom9.go | 38 | ||||
-rw-r--r-- | ethchain/state_transition.go | 6 | ||||
-rw-r--r-- | ethchain/transaction.go | 7 | ||||
-rw-r--r-- | ethchain/types.go | 4 | ||||
-rw-r--r-- | ethchain/vm_env.go | 3 | ||||
-rw-r--r-- | ethpipe/vm_env.go | 1 | ||||
-rw-r--r-- | ethstate/state.go | 7 | ||||
-rw-r--r-- | ethtrie/trie.go | 3 | ||||
-rw-r--r-- | ethutil/common.go | 1 | ||||
-rw-r--r-- | javascript/javascript_runtime.go | 8 | ||||
-rw-r--r-- | tests/helper/vm.go | 1 | ||||
-rw-r--r-- | utils/cmd.go | 2 | ||||
-rw-r--r-- | utils/vm_env.go | 1 | ||||
-rw-r--r-- | vm/common.go | 1 | ||||
-rw-r--r-- | vm/environment.go | 1 | ||||
-rw-r--r-- | vm/log.go | 9 | ||||
-rw-r--r-- | vm/stack.go | 12 | ||||
-rw-r--r-- | vm/types.go | 10 | ||||
-rw-r--r-- | vm/vm.go | 2 | ||||
-rw-r--r-- | vm/vm_debug.go | 33 |
21 files changed, 132 insertions, 20 deletions
diff --git a/cmd/mist/flags.go b/cmd/mist/flags.go index 5283c332b..3aa2e21c8 100644 --- a/cmd/mist/flags.go +++ b/cmd/mist/flags.go @@ -67,7 +67,7 @@ func defaultAssetPath() string { // assume a debug build and use the source directory as // asset directory. pwd, _ := os.Getwd() - if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "mist") { + if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") { assetPath = path.Join(pwd, "assets") } else { switch runtime.GOOS { diff --git a/ethchain/bloom9.go b/ethchain/bloom9.go new file mode 100644 index 000000000..65be6c7a2 --- /dev/null +++ b/ethchain/bloom9.go @@ -0,0 +1,38 @@ +package ethchain + +import "github.com/ethereum/go-ethereum/vm" + +func CreateBloom(txs Transactions) uint64 { + var bin uint64 + for _, tx := range txs { + bin |= logsBloom(tx.logs) + } + + return bin +} + +func logsBloom(logs []vm.Log) uint64 { + var bin uint64 + for _, log := range logs { + data := [][]byte{log.Address} + for _, topic := range log.Topics { + data = append(data, topic.Bytes()) + } + data = append(data, log.Data) + + for _, b := range data { + bin |= bloom9(b) + } + } + + return bin +} + +func bloom9(b []byte) uint64 { + var r uint64 + for _, i := range []int{0, 2, 4} { + r |= 1 << (uint64(b[i+1]) + 256*(uint64(b[i])&1)) + } + + return r +} 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/ethstate/state.go b/ethstate/state.go index fd6fa65a5..c23dab330 100644 --- a/ethstate/state.go +++ b/ethstate/state.go @@ -39,6 +39,13 @@ func (self *State) GetBalance(addr []byte) *big.Int { return ethutil.Big0 } +func (self *State) AddBalance(addr []byte, amount *big.Int) { + stateObject := self.GetStateObject(addr) + if stateObject != nil { + stateObject.AddBalance(amount) + } +} + func (self *State) GetNonce(addr []byte) uint64 { stateObject := self.GetStateObject(addr) if stateObject != nil { diff --git a/ethtrie/trie.go b/ethtrie/trie.go index 7a86e79bd..686971985 100644 --- a/ethtrie/trie.go +++ b/ethtrie/trie.go @@ -3,15 +3,12 @@ package ethtrie import ( "bytes" "fmt" - _ "reflect" "sync" "github.com/ethereum/go-ethereum/ethcrypto" "github.com/ethereum/go-ethereum/ethutil" ) -func __ignore() { fmt.Println("") } - func ParanoiaCheck(t1 *Trie) (bool, *Trie) { t2 := New(ethutil.Config.Db, "") 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/javascript/javascript_runtime.go b/javascript/javascript_runtime.go index b0d7c81b5..704635d97 100644 --- a/javascript/javascript_runtime.go +++ b/javascript/javascript_runtime.go @@ -41,7 +41,7 @@ func (jsre *JSRE) LoadExtFile(path string) { } func (jsre *JSRE) LoadIntFile(file string) { - assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "mist", "assets", "ext") + assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext") jsre.LoadExtFile(path.Join(assetPath, file)) } @@ -62,13 +62,13 @@ func NewJSRE(ethereum *eth.Ethereum) *JSRE { re.LoadIntFile("string.js") re.LoadIntFile("big.js") - // We have to make sure that, whoever calls this, calls "Stop" - go re.mainLoop() - // Subscribe to events mux := ethereum.EventMux() re.events = mux.Subscribe(ethchain.NewBlockEvent{}) + // We have to make sure that, whoever calls this, calls "Stop" + go re.mainLoop() + re.Bind("eth", &JSEthereum{re.pipe, re.Vm, ethereum}) re.initStdFuncs() 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/cmd.go b/utils/cmd.go index 76faa5dac..c46e1f00d 100644 --- a/utils/cmd.go +++ b/utils/cmd.go @@ -192,7 +192,7 @@ func DefaultAssetPath() string { // assume a debug build and use the source directory as // asset directory. pwd, _ := os.Getwd() - if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "mist") { + if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") { assetPath = path.Join(pwd, "assets") } else { switch runtime.GOOS { 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", @@ -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)) |