aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block_pool.go6
-rw-r--r--cmd/ethereum/main.go2
-rw-r--r--ethchain/block.go138
-rw-r--r--ethchain/bloom9.go47
-rw-r--r--ethchain/bloom9_test.go17
-rw-r--r--ethchain/chain_manager.go2
-rw-r--r--ethchain/derive_sha.go20
-rw-r--r--ethchain/filter.go13
-rw-r--r--ethchain/genesis.go11
-rw-r--r--ethchain/helper_test.go6
-rw-r--r--ethchain/state_manager.go35
-rw-r--r--ethchain/state_transition.go12
-rw-r--r--ethchain/transaction.go52
-rw-r--r--ethcrypto/crypto_test.go33
-rw-r--r--ethminer/miner.go33
-rw-r--r--ethpipe/pipe_test.go58
-rw-r--r--ethstate/state.go26
-rw-r--r--ethtrie/trie.go40
-rw-r--r--ethutil/rlp.go6
-rw-r--r--ethutil/value.go4
-rw-r--r--ethwire/client_identity_test.go12
-rw-r--r--vm/common.go23
-rw-r--r--vm/log.go33
-rw-r--r--vm/vm_debug.go11
-rw-r--r--vm/vm_test.go54
25 files changed, 405 insertions, 289 deletions
diff --git a/block_pool.go b/block_pool.go
index f65d9d576..334db9c1b 100644
--- a/block_pool.go
+++ b/block_pool.go
@@ -309,9 +309,13 @@ out:
}
}
+ // TODO figure out whether we were catching up
+ // If caught up and just a new block has been propagated:
+ // sm.eth.EventMux().Post(NewBlockEvent{block})
+ // otherwise process and don't emit anything
var err error
for i, block := range blocks {
- err = self.eth.StateManager().Process(block, false)
+ err = self.eth.StateManager().Process(block)
if err != nil {
poollogger.Infoln(err)
poollogger.Debugf("Block #%v failed (%x...)\n", block.Number, block.Hash()[0:4])
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 9e9a3e356..b78d49cae 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -98,6 +98,8 @@ func main() {
// Leave the Println. This needs clean output for piping
fmt.Printf("%s\n", block.State().Dump())
+ fmt.Println(block)
+
os.Exit(0)
}
diff --git a/ethchain/block.go b/ethchain/block.go
index b98d806d8..b31d68e4d 100644
--- a/ethchain/block.go
+++ b/ethchain/block.go
@@ -5,7 +5,6 @@ import (
"fmt"
"math/big"
"sort"
- _ "strconv"
"time"
"github.com/ethereum/go-ethereum/ethcrypto"
@@ -96,9 +95,10 @@ type Block struct {
// Block Nonce for verification
Nonce ethutil.Bytes
// List of transactions and/or contracts
- transactions []*Transaction
- receipts []*Receipt
- TxSha []byte
+ transactions Transactions
+ receipts Receipts
+ TxSha, ReceiptSha []byte
+ LogsBloom []byte
}
func NewBlockFromBytes(raw []byte) *Block {
@@ -151,7 +151,7 @@ func (block *Block) Hash() ethutil.Bytes {
func (block *Block) HashNoNonce() []byte {
return ethcrypto.Sha3(ethutil.Encode([]interface{}{block.PrevHash,
block.UncleSha, block.Coinbase, block.state.Trie.Root,
- block.TxSha, block.Difficulty, block.Number, block.MinGasPrice,
+ block.ReceiptSha, block.Difficulty, block.Number, block.MinGasPrice,
block.GasLimit, block.GasUsed, block.Time, block.Extra}))
}
@@ -191,9 +191,9 @@ func (block *Block) BlockInfo() BlockInfo {
}
func (self *Block) GetTransaction(hash []byte) *Transaction {
- for _, receipt := range self.receipts {
- if bytes.Compare(receipt.Tx.Hash(), hash) == 0 {
- return receipt.Tx
+ for _, tx := range self.transactions {
+ if bytes.Compare(tx.Hash(), hash) == 0 {
+ return tx
}
}
@@ -236,45 +236,34 @@ func (block *Block) rlpUncles() interface{} {
func (block *Block) SetUncles(uncles []*Block) {
block.Uncles = uncles
- // Sha of the concatenated uncles
- if len(uncles) > 0 {
- block.UncleSha = ethcrypto.Sha3(ethutil.Encode(block.rlpUncles()))
- }
+ block.UncleSha = ethcrypto.Sha3(ethutil.Encode(block.rlpUncles()))
}
-func (self *Block) SetReceipts(receipts []*Receipt, txs []*Transaction) {
+func (self *Block) SetReceipts(receipts Receipts) {
self.receipts = receipts
+ self.SetReceiptHash(receipts)
+}
+
+func (self *Block) SetTransactions(txs Transactions) {
self.setTransactions(txs)
+ self.SetTransactionHash(txs)
}
-func (block *Block) setTransactions(txs []*Transaction) {
+func (block *Block) setTransactions(txs Transactions) {
block.transactions = txs
+ block.LogsBloom = CreateBloom(block)
}
-func CreateTxSha(receipts Receipts) (sha []byte) {
- trie := ethtrie.New(ethutil.Config.Db, "")
- for i, receipt := range receipts {
- trie.Update(string(ethutil.NewValue(i).Encode()), string(ethutil.NewValue(receipt.RlpData()).Encode()))
- }
-
- switch trie.Root.(type) {
- case string:
- sha = []byte(trie.Root.(string))
- case []byte:
- sha = trie.Root.([]byte)
- default:
- panic(fmt.Sprintf("invalid root type %T", trie.Root))
- }
-
- return sha
+func (self *Block) SetTransactionHash(transactions Transactions) {
+ self.TxSha = DeriveSha(transactions)
}
-func (self *Block) SetTxHash(receipts Receipts) {
- self.TxSha = CreateTxSha(receipts)
+func (self *Block) SetReceiptHash(receipts Receipts) {
+ self.ReceiptSha = DeriveSha(receipts)
}
func (block *Block) Value() *ethutil.Value {
- return ethutil.NewValue([]interface{}{block.header(), block.rlpReceipts(), block.rlpUncles()})
+ return ethutil.NewValue([]interface{}{block.header(), block.transactions, block.rlpUncles()})
}
func (block *Block) RlpEncode() []byte {
@@ -289,33 +278,20 @@ func (block *Block) RlpDecode(data []byte) {
}
func (block *Block) RlpValueDecode(decoder *ethutil.Value) {
- header := decoder.Get(0)
-
- block.PrevHash = header.Get(0).Bytes()
- block.UncleSha = header.Get(1).Bytes()
- block.Coinbase = header.Get(2).Bytes()
- block.state = ethstate.New(ethtrie.New(ethutil.Config.Db, header.Get(3).Val))
- block.TxSha = header.Get(4).Bytes()
- block.Difficulty = header.Get(5).BigInt()
- block.Number = header.Get(6).BigInt()
- //fmt.Printf("#%v : %x\n", block.Number, block.Coinbase)
- block.MinGasPrice = header.Get(7).BigInt()
- block.GasLimit = header.Get(8).BigInt()
- block.GasUsed = header.Get(9).BigInt()
- block.Time = int64(header.Get(10).BigInt().Uint64())
- block.Extra = header.Get(11).Str()
- block.Nonce = header.Get(12).Bytes()
+ block.setHeader(decoder.Get(0))
// Tx list might be empty if this is an uncle. Uncles only have their
// header set.
if decoder.Get(1).IsNil() == false { // Yes explicitness
- receipts := decoder.Get(1)
- block.transactions = make([]*Transaction, receipts.Len())
- block.receipts = make([]*Receipt, receipts.Len())
- for i := 0; i < receipts.Len(); i++ {
- receipt := NewRecieptFromValue(receipts.Get(i))
- block.transactions[i] = receipt.Tx
- block.receipts[i] = receipt
+ //receipts := decoder.Get(1)
+ //block.receipts = make([]*Receipt, receipts.Len())
+ it := decoder.Get(1).NewIterator()
+ block.transactions = make(Transactions, it.Len())
+ for it.Next() {
+ block.transactions[it.Idx()] = NewTransactionFromValue(it.Value())
+ //receipt := NewRecieptFromValue(receipts.Get(i))
+ //block.transactions[i] = receipt.Tx
+ //block.receipts[i] = receipt
}
}
@@ -330,22 +306,27 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) {
}
+func (self *Block) setHeader(header *ethutil.Value) {
+ self.PrevHash = header.Get(0).Bytes()
+ self.UncleSha = header.Get(1).Bytes()
+ self.Coinbase = header.Get(2).Bytes()
+ self.state = ethstate.New(ethtrie.New(ethutil.Config.Db, header.Get(3).Val))
+ self.TxSha = header.Get(4).Bytes()
+ self.ReceiptSha = header.Get(5).Bytes()
+ self.LogsBloom = header.Get(6).Bytes()
+ self.Difficulty = header.Get(7).BigInt()
+ self.Number = header.Get(8).BigInt()
+ self.MinGasPrice = header.Get(9).BigInt()
+ self.GasLimit = header.Get(10).BigInt()
+ self.GasUsed = header.Get(11).BigInt()
+ self.Time = int64(header.Get(12).BigInt().Uint64())
+ self.Extra = header.Get(13).Str()
+ self.Nonce = header.Get(14).Bytes()
+}
+
func NewUncleBlockFromValue(header *ethutil.Value) *Block {
block := &Block{}
-
- block.PrevHash = header.Get(0).Bytes()
- block.UncleSha = header.Get(1).Bytes()
- block.Coinbase = header.Get(2).Bytes()
- block.state = ethstate.New(ethtrie.New(ethutil.Config.Db, header.Get(3).Val))
- block.TxSha = header.Get(4).Bytes()
- block.Difficulty = header.Get(5).BigInt()
- block.Number = header.Get(6).BigInt()
- block.MinGasPrice = header.Get(7).BigInt()
- block.GasLimit = header.Get(8).BigInt()
- block.GasUsed = header.Get(9).BigInt()
- block.Time = int64(header.Get(10).BigInt().Uint64())
- block.Extra = header.Get(11).Str()
- block.Nonce = header.Get(12).Bytes()
+ block.setHeader(header)
return block
}
@@ -376,8 +357,12 @@ func (block *Block) header() []interface{} {
block.Coinbase,
// root state
block.state.Trie.Root,
- // Sha of tx
+ // tx root
block.TxSha,
+ // Sha of tx
+ block.ReceiptSha,
+ // Bloom
+ block.LogsBloom,
// Current block Difficulty
block.Difficulty,
// The block number
@@ -404,7 +389,9 @@ func (block *Block) String() string {
UncleSha: %x
Coinbase: %x
Root: %x
- TxSha: %x
+ TxSha %x
+ ReceiptSha: %x
+ Bloom: %x
Difficulty: %v
Number: %v
MinGas: %v
@@ -422,6 +409,8 @@ func (block *Block) String() string {
block.Coinbase,
block.state.Trie.Root,
block.TxSha,
+ block.ReceiptSha,
+ block.LogsBloom,
block.Difficulty,
block.Number,
block.MinGasPrice,
@@ -437,3 +426,8 @@ func (block *Block) String() string {
func (self *Block) Size() ethutil.StorageSize {
return ethutil.StorageSize(len(self.RlpEncode()))
}
+
+// Implement RlpEncodable
+func (self *Block) RlpData() interface{} {
+ return self.Value().Val
+}
diff --git a/ethchain/bloom9.go b/ethchain/bloom9.go
index 65be6c7a2..4028231a3 100644
--- a/ethchain/bloom9.go
+++ b/ethchain/bloom9.go
@@ -1,38 +1,55 @@
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)
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/ethutil"
+ "github.com/ethereum/go-ethereum/vm"
+)
+
+func CreateBloom(block *Block) []byte {
+ bin := new(big.Int)
+ bin.Or(bin, bloom9(block.Coinbase))
+ for _, tx := range block.Transactions() {
+ bin.Or(bin, LogsBloom(tx.logs))
}
- return bin
+ return bin.Bytes()
}
-func logsBloom(logs []vm.Log) uint64 {
- var bin uint64
+func LogsBloom(logs []vm.Log) *big.Int {
+ bin := new(big.Int)
for _, log := range logs {
data := [][]byte{log.Address}
for _, topic := range log.Topics {
- data = append(data, topic.Bytes())
+ data = append(data, topic)
+ }
+
+ if log.Data != nil {
+ data = append(data, log.Data)
}
- data = append(data, log.Data)
for _, b := range data {
- bin |= bloom9(b)
+ bin.Or(bin, bloom9(b))
}
}
return bin
}
-func bloom9(b []byte) uint64 {
- var r uint64
+func bloom9(b []byte) *big.Int {
+ r := new(big.Int)
for _, i := range []int{0, 2, 4} {
- r |= 1 << (uint64(b[i+1]) + 256*(uint64(b[i])&1))
+ t := big.NewInt(1)
+ r.Or(r, t.Lsh(t, uint(b[i+1])+256*(uint(b[i])&1)))
}
return r
}
+
+func BloomLookup(bin, topic []byte) bool {
+ bloom := ethutil.BigD(bin)
+ cmp := bloom9(topic)
+
+ return bloom.And(bloom, cmp).Cmp(cmp) == 0
+}
diff --git a/ethchain/bloom9_test.go b/ethchain/bloom9_test.go
new file mode 100644
index 000000000..40f30f35d
--- /dev/null
+++ b/ethchain/bloom9_test.go
@@ -0,0 +1,17 @@
+package ethchain
+
+import (
+ "testing"
+
+ "github.com/ethereum/go-ethereum/vm"
+)
+
+func TestBloom9(t *testing.T) {
+ testCase := []byte("testtest")
+ bin := LogsBloom([]vm.Log{vm.Log{testCase, [][]byte{[]byte("hellohello")}, nil}}).Bytes()
+ res := BloomLookup(bin, testCase)
+
+ if !res {
+ t.Errorf("Bloom lookup failed")
+ }
+}
diff --git a/ethchain/chain_manager.go b/ethchain/chain_manager.go
index d949f0ce7..46990bb22 100644
--- a/ethchain/chain_manager.go
+++ b/ethchain/chain_manager.go
@@ -87,8 +87,6 @@ func (bc *ChainManager) Reset() {
bc.genesisBlock.state.Trie.Sync()
// Prepare the genesis block
bc.Add(bc.genesisBlock)
- fk := append([]byte("bloom"), bc.genesisBlock.Hash()...)
- bc.Ethereum.Db().Put(fk, make([]byte, 255))
bc.CurrentBlock = bc.genesisBlock
bc.SetTotalDifficulty(ethutil.Big("0"))
diff --git a/ethchain/derive_sha.go b/ethchain/derive_sha.go
new file mode 100644
index 000000000..b41252e39
--- /dev/null
+++ b/ethchain/derive_sha.go
@@ -0,0 +1,20 @@
+package ethchain
+
+import (
+ "github.com/ethereum/go-ethereum/ethtrie"
+ "github.com/ethereum/go-ethereum/ethutil"
+)
+
+type DerivableList interface {
+ Len() int
+ GetRlp(i int) []byte
+}
+
+func DeriveSha(list DerivableList) []byte {
+ trie := ethtrie.New(ethutil.Config.Db, "")
+ for i := 0; i < list.Len(); i++ {
+ trie.Update(string(ethutil.NewValue(i).Encode()), string(list.GetRlp(i)))
+ }
+
+ return trie.GetRoot()
+}
diff --git a/ethchain/filter.go b/ethchain/filter.go
index 4e7fe68a8..b0edea7a0 100644
--- a/ethchain/filter.go
+++ b/ethchain/filter.go
@@ -2,7 +2,6 @@ package ethchain
import (
"bytes"
- "fmt"
"math"
"github.com/ethereum/go-ethereum/ethstate"
@@ -171,18 +170,10 @@ func (self *Filter) FilterMessages(msgs []*ethstate.Message) []*ethstate.Message
}
func (self *Filter) bloomFilter(block *Block) bool {
- fk := append([]byte("bloom"), block.Hash()...)
- bin, err := self.eth.Db().Get(fk)
- if err != nil {
- fmt.Println(err)
- }
-
- bloom := NewBloomFilter(bin)
-
var fromIncluded, toIncluded bool
if len(self.from) > 0 {
for _, from := range self.from {
- if bloom.Search(from) {
+ if BloomLookup(block.LogsBloom, from) {
fromIncluded = true
break
}
@@ -193,7 +184,7 @@ func (self *Filter) bloomFilter(block *Block) bool {
if len(self.to) > 0 {
for _, to := range self.to {
- if bloom.Search(to) {
+ if BloomLookup(block.LogsBloom, to) {
toIncluded = true
break
}
diff --git a/ethchain/genesis.go b/ethchain/genesis.go
index 232986d53..d94e658b6 100644
--- a/ethchain/genesis.go
+++ b/ethchain/genesis.go
@@ -13,19 +13,24 @@ import (
var ZeroHash256 = make([]byte, 32)
var ZeroHash160 = make([]byte, 20)
+var ZeroHash512 = make([]byte, 64)
var EmptyShaList = ethcrypto.Sha3(ethutil.Encode([]interface{}{}))
var GenesisHeader = []interface{}{
// Previous hash (none)
ZeroHash256,
// Empty uncles
- "",
+ EmptyShaList,
// Coinbase
ZeroHash160,
// Root state
- "",
+ EmptyShaList,
// tx sha
- "",
+ EmptyShaList,
+ // receipt list
+ EmptyShaList,
+ // bloom
+ ZeroHash512,
// Difficulty
//ethutil.BigPow(2, 22),
big.NewInt(131072),
diff --git a/ethchain/helper_test.go b/ethchain/helper_test.go
index e4aef67d0..a863c7541 100644
--- a/ethchain/helper_test.go
+++ b/ethchain/helper_test.go
@@ -18,7 +18,7 @@ type TestManager struct {
db ethutil.Database
txPool *TxPool
- blockChain *BlockChain
+ blockChain *ChainManager
Blocks []*Block
}
@@ -38,7 +38,7 @@ func (s *TestManager) Peers() *list.List {
return list.New()
}
-func (s *TestManager) BlockChain() *BlockChain {
+func (s *TestManager) ChainManager() *ChainManager {
return s.blockChain
}
@@ -82,7 +82,7 @@ func NewTestManager() *TestManager {
testManager.eventMux = new(event.TypeMux)
testManager.db = db
testManager.txPool = NewTxPool(testManager)
- testManager.blockChain = NewBlockChain(testManager)
+ testManager.blockChain = NewChainManager(testManager)
testManager.stateManager = NewStateManager(testManager)
// Start the tx pool
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index dba3ff202..e45d44752 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -101,7 +101,7 @@ func (self *StateManager) Stop() {
func (self *StateManager) updateThread() {
for ev := range self.events.Chan() {
for _, block := range ev.(Blocks) {
- err := self.Process(block, false)
+ err := self.Process(block)
if err != nil {
statelogger.Infoln(err)
statelogger.Debugf("Block #%v failed (%x...)\n", block.Number, block.Hash()[0:4])
@@ -173,8 +173,9 @@ done:
state.Update()
txGas.Sub(txGas, st.gas)
- accumelative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas))
- receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative}
+ cumulative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas))
+ //receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative}
+ receipt := &Receipt{ethutil.CopyBytes(state.Root().([]byte)), cumulative, LogsBloom(tx.logs).Bytes(), tx.logs}
if i < len(block.Receipts()) {
original := block.Receipts()[i]
@@ -183,7 +184,7 @@ done:
os.Exit(1)
}
- err := fmt.Errorf("#%d receipt failed (r) %v ~ %x <=> (c) %v ~ %x (%x...)", i+1, original.CumulativeGasUsed, original.PostState[0:4], receipt.CumulativeGasUsed, receipt.PostState[0:4], receipt.Tx.Hash()[0:4])
+ err := fmt.Errorf("#%d receipt failed (r) %v ~ %x <=> (c) %v ~ %x (%x...)", i+1, original.CumulativeGasUsed, original.PostState[0:4], receipt.CumulativeGasUsed, receipt.PostState[0:4], tx.Hash()[0:4])
return nil, nil, nil, nil, err
}
@@ -205,7 +206,7 @@ done:
return receipts, handled, unhandled, erroneous, err
}
-func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
+func (sm *StateManager) Process(block *Block) (err error) {
// Processing a blocks may never happen simultaneously
sm.mutex.Lock()
defer sm.mutex.Unlock()
@@ -235,14 +236,19 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
fmt.Printf("## %x %x ##\n", block.Hash(), block.Number)
}
+ txSha := DeriveSha(block.transactions)
+ if bytes.Compare(txSha, block.TxSha) != 0 {
+ return fmt.Errorf("Error validating transaction sha. Received %x, got %x", block.ReceiptSha, txSha)
+ }
+
receipts, err := sm.ApplyDiff(state, parent, block)
if err != nil {
return err
}
- txSha := CreateTxSha(receipts)
- if bytes.Compare(txSha, block.TxSha) != 0 {
- return fmt.Errorf("Error validating tx sha. Received %x, got %x", block.TxSha, txSha)
+ receiptSha := DeriveSha(receipts)
+ if bytes.Compare(receiptSha, block.ReceiptSha) != 0 {
+ return fmt.Errorf("Error validating receipt sha. Received %x, got %x", block.ReceiptSha, receiptSha)
}
// Block validation
@@ -271,20 +277,13 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
// Add the block to the chain
sm.bc.Add(block)
- sm.transState = state.Copy()
+ // TODO at this point we should also insert LOGS in to a database
- // Create a bloom bin for this block
- filter := sm.createBloomFilter(state)
- // Persist the data
- fk := append([]byte("bloom"), block.Hash()...)
- sm.eth.Db().Put(fk, filter.Bin())
+ sm.transState = state.Copy()
statelogger.Infof("Imported block #%d (%x...)\n", block.Number, block.Hash()[0:4])
- if dontReact == false {
- sm.eth.EventMux().Post(NewBlockEvent{block})
- state.Manifest().Reset()
- }
+ state.Manifest().Reset()
sm.eth.TxPool().RemoveSet(block.Transactions())
} else {
diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go
index e6863b61f..809e5ad6a 100644
--- a/ethchain/state_transition.go
+++ b/ethchain/state_transition.go
@@ -5,7 +5,6 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/ethstate"
- "github.com/ethereum/go-ethereum/ethtrie"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/vm"
)
@@ -231,11 +230,9 @@ 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})
+ // Add default LOG. Default = big(sender.addr) + 1
+ addr := ethutil.BigD(receiver.Address())
+ tx.addLog(vm.Log{sender.Address(), [][]byte{addr.Add(addr, ethutil.Big1).Bytes()}, nil})
}
}
@@ -250,9 +247,7 @@ func (self *StateTransition) Eval(msg *ethstate.Message, script []byte, context
callerClosure = vm.NewClosure(msg, transactor, context, script, self.gas, self.gasPrice)
)
- //vm := vm.New(env, vm.Type(ethutil.Config.VmType))
evm := vm.New(env, vm.DebugVmTy)
-
ret, _, err = callerClosure.Call(evm, self.tx.Data)
return
@@ -264,7 +259,6 @@ func MakeContract(tx *Transaction, state *ethstate.State) *ethstate.StateObject
contract := state.GetOrNewStateObject(addr)
contract.InitCode = tx.Data
- contract.State = ethstate.New(ethtrie.New(ethutil.Config.Db, ""))
return contract
}
diff --git a/ethchain/transaction.go b/ethchain/transaction.go
index abf2e37ac..10bf5bc8e 100644
--- a/ethchain/transaction.go
+++ b/ethchain/transaction.go
@@ -113,7 +113,8 @@ func (tx *Transaction) PublicKey() []byte {
sig := append(r, s...)
sig = append(sig, tx.v-27)
- pubkey, _ := secp256k1.RecoverPubkey(hash, sig)
+ pubkey := ethcrypto.Ecrecover(append(hash, sig...))
+ //pubkey, _ := secp256k1.RecoverPubkey(hash, sig)
return pubkey
}
@@ -208,11 +209,11 @@ func (tx *Transaction) String() string {
}
type Receipt struct {
- Tx *Transaction
PostState []byte
CumulativeGasUsed *big.Int
+ Bloom []byte
+ Logs vm.Logs
}
-type Receipts []*Receipt
func NewRecieptFromValue(val *ethutil.Value) *Receipt {
r := &Receipt{}
@@ -222,25 +223,22 @@ func NewRecieptFromValue(val *ethutil.Value) *Receipt {
}
func (self *Receipt) RlpValueDecode(decoder *ethutil.Value) {
- self.Tx = NewTransactionFromValue(decoder.Get(0))
- self.PostState = decoder.Get(1).Bytes()
- self.CumulativeGasUsed = decoder.Get(2).BigInt()
+ self.PostState = decoder.Get(0).Bytes()
+ self.CumulativeGasUsed = decoder.Get(1).BigInt()
+ self.Bloom = decoder.Get(2).Bytes()
+
+ it := decoder.Get(3).NewIterator()
+ for it.Next() {
+ self.Logs = append(self.Logs, vm.NewLogFromValue(it.Value()))
+ }
}
func (self *Receipt) RlpData() interface{} {
- return []interface{}{self.Tx.RlpData(), self.PostState, self.CumulativeGasUsed}
+ return []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.Logs.RlpData()}
}
-func (self *Receipt) String() string {
- return fmt.Sprintf(`
- R
- Tx:[ %v]
- PostState: 0x%x
- CumulativeGasUsed: %v
- `,
- self.Tx,
- self.PostState,
- self.CumulativeGasUsed)
+func (self *Receipt) RlpEncode() []byte {
+ return ethutil.Encode(self.RlpData())
}
func (self *Receipt) Cmp(other *Receipt) bool {
@@ -251,11 +249,27 @@ func (self *Receipt) Cmp(other *Receipt) bool {
return true
}
+type Receipts []*Receipt
+
+func (self Receipts) Len() int { return len(self) }
+func (self Receipts) GetRlp(i int) []byte { return ethutil.Rlp(self[i]) }
+
// Transaction slice type for basic sorting
type Transactions []*Transaction
-func (s Transactions) Len() int { return len(s) }
-func (s Transactions) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (self Transactions) RlpData() interface{} {
+ // Marshal the transactions of this block
+ enc := make([]interface{}, len(self))
+ for i, tx := range self {
+ // Cast it to a string (safe)
+ enc[i] = tx.RlpData()
+ }
+
+ return enc
+}
+func (s Transactions) Len() int { return len(s) }
+func (s Transactions) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s Transactions) GetRlp(i int) []byte { return ethutil.Rlp(s[i]) }
type TxByNonce struct{ Transactions }
diff --git a/ethcrypto/crypto_test.go b/ethcrypto/crypto_test.go
index 689bcecb4..e8db6362f 100644
--- a/ethcrypto/crypto_test.go
+++ b/ethcrypto/crypto_test.go
@@ -2,16 +2,35 @@ package ethcrypto
import (
"bytes"
+ "encoding/hex"
"testing"
-
- "github.com/ethereum/go-ethereum/ethutil"
)
-// FIPS 202 test (reverted back to FIPS 180)
+// These tests are sanity checks.
+// They should ensure that we don't e.g. use Sha3-224 instead of Sha3-256
+// and that the sha3 library uses keccak-f permutation.
+
func TestSha3(t *testing.T) {
- const exp = "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"
- sha3_256 := Sha3Bin([]byte("abc"))
- if bytes.Compare(sha3_256, ethutil.Hex2Bytes(exp)) != 0 {
- t.Errorf("Sha3_256 failed. Incorrect result %x", sha3_256)
+ msg := []byte("abc")
+ exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45")
+ checkhash(t, "Sha3-256", Sha3, msg, exp)
+}
+
+func TestSha256(t *testing.T) {
+ msg := []byte("abc")
+ exp, _ := hex.DecodeString("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
+ checkhash(t, "Sha256", Sha256, msg, exp)
+}
+
+func TestRipemd160(t *testing.T) {
+ msg := []byte("abc")
+ exp, _ := hex.DecodeString("8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")
+ checkhash(t, "Ripemd160", Ripemd160, msg, exp)
+}
+
+func checkhash(t *testing.T, name string, f func([]byte) []byte, msg, exp []byte) {
+ sum := f(msg)
+ if bytes.Compare(exp, sum) != 0 {
+ t.Errorf("hash %s returned wrong result.\ngot: %x\nwant: %x", name, sum, exp)
}
}
diff --git a/ethminer/miner.go b/ethminer/miner.go
index e0bef078b..24af7fbcb 100644
--- a/ethminer/miner.go
+++ b/ethminer/miner.go
@@ -85,11 +85,7 @@ func (miner *Miner) listener() {
for {
select {
- case event, isopen := <-miner.events.Chan():
- if !isopen {
- return
- }
-
+ case event := <-miner.events.Chan():
switch event := event.(type) {
case ethchain.NewBlockEvent:
miner.stopMining()
@@ -114,16 +110,13 @@ func (miner *Miner) listener() {
}
}
miner.txs = newtxs
-
- // Setup a fresh state to mine on
- //miner.block = miner.ethereum.ChainManager().NewBlock(miner.coinbase, miner.txs)
-
} else {
if bytes.Compare(block.PrevHash, miner.ethereum.ChainManager().CurrentBlock.PrevHash) == 0 {
logger.Infoln("Adding uncle block")
miner.uncles = append(miner.uncles, block)
}
}
+ miner.startMining()
case ethchain.TxEvent:
if event.Type == ethchain.TxPre {
@@ -141,6 +134,8 @@ func (miner *Miner) listener() {
// Apply new transactions
miner.txs = append(miner.txs, event.Tx)
}
+
+ miner.startMining()
}
}
@@ -159,8 +154,12 @@ func (miner *Miner) startMining() {
}
func (miner *Miner) stopMining() {
- close(miner.powQuitChan)
- <-miner.powDone
+ println("stop mining")
+ _, isopen := <-miner.powQuitChan
+ if isopen {
+ close(miner.powQuitChan)
+ }
+ //<-miner.powDone
}
func (self *Miner) mineNewBlock() {
@@ -187,10 +186,9 @@ func (self *Miner) mineNewBlock() {
}
self.ethereum.TxPool().RemoveSet(erroneous)
self.txs = append(txs, unhandledTxs...)
- self.block.SetTxHash(receipts)
- // Set the transactions to the block so the new SHA3 can be calculated
- self.block.SetReceipts(receipts, txs)
+ self.block.SetReceipts(receipts)
+ self.block.SetTransactions(txs)
// Accumulate the rewards included for this block
stateManager.AccumelateRewards(self.block.State(), self.block, parent)
@@ -203,7 +201,7 @@ func (self *Miner) mineNewBlock() {
nonce := self.pow.Search(self.block, self.powQuitChan)
if nonce != nil {
self.block.Nonce = nonce
- err := self.ethereum.StateManager().Process(self.block, false)
+ err := self.ethereum.StateManager().Process(self.block)
if err != nil {
logger.Infoln(err)
} else {
@@ -212,7 +210,10 @@ func (self *Miner) mineNewBlock() {
logger.Infoln(self.block)
// Gather the new batch of transactions currently in the tx pool
self.txs = self.ethereum.TxPool().CurrentTransactions()
+ self.ethereum.EventMux().Post(ethchain.NewBlockEvent{self.block})
}
+
+ // Continue mining on the next block
+ self.startMining()
}
- self.powDone <- struct{}{}
}
diff --git a/ethpipe/pipe_test.go b/ethpipe/pipe_test.go
deleted file mode 100644
index 3b5dc5e4c..000000000
--- a/ethpipe/pipe_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package ethpipe
-
-import (
- "testing"
-
- "github.com/ethereum/go-ethereum/ethcrypto"
- "github.com/ethereum/go-ethereum/ethstate"
- "github.com/ethereum/go-ethereum/ethutil"
-)
-
-func Val(v interface{}) *ethutil.Value {
- return ethutil.NewValue(v)
-}
-
-func TestNew(t *testing.T) {
- pipe := New(nil)
-
- var addr, privy, recp, data []byte
- var object *ethstate.StateObject
- var key *ethcrypto.KeyPair
-
- world := pipe.World()
- world.Get(addr)
- world.Coinbase()
- world.IsMining()
- world.IsListening()
- world.State()
- peers := world.Peers()
- peers.Len()
-
- // Shortcut functions
- pipe.Balance(addr)
- pipe.Nonce(addr)
- pipe.Block(addr)
- pipe.Storage(addr, addr)
- pipe.ToAddress(privy)
- pipe.Exists(addr)
- // Doesn't change state
- pipe.Execute(addr, nil, Val(0), Val(1000000), Val(10))
- // Doesn't change state
- pipe.ExecuteObject(object, nil, Val(0), Val(1000000), Val(10))
-
- conf := world.Config()
- namereg := conf.Get("NameReg")
- namereg.Storage(addr)
-
- var err error
- // Transact
- err = pipe.Transact(key, recp, ethutil.NewValue(0), ethutil.NewValue(0), ethutil.NewValue(0), nil)
- if err != nil {
- t.Error(err)
- }
- // Create
- err = pipe.Transact(key, nil, ethutil.NewValue(0), ethutil.NewValue(0), ethutil.NewValue(0), data)
- if err != nil {
- t.Error(err)
- }
-}
diff --git a/ethstate/state.go b/ethstate/state.go
index c23dab330..97958cc0a 100644
--- a/ethstate/state.go
+++ b/ethstate/state.go
@@ -22,11 +22,13 @@ type State struct {
stateObjects map[string]*StateObject
manifest *Manifest
+
+ refund map[string]*big.Int
}
// Create a new state from a given trie
func New(trie *ethtrie.Trie) *State {
- return &State{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest()}
+ return &State{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string]*big.Int)}
}
// Retrieve the balance from the given address or 0 if object not found
@@ -39,6 +41,16 @@ func (self *State) GetBalance(addr []byte) *big.Int {
return ethutil.Big0
}
+func (self *State) Refund(addr []byte, gas, price *big.Int) {
+ amount := new(big.Int).Mul(gas, price)
+
+ if self.refund[string(addr)] == nil {
+ self.refund[string(addr)] = new(big.Int)
+ }
+
+ self.refund[string(addr)] = new(big.Int).Add(self.refund[string(addr)], amount)
+}
+
func (self *State) AddBalance(addr []byte, amount *big.Int) {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
@@ -186,6 +198,10 @@ func (self *State) Copy() *State {
state.stateObjects[k] = stateObject.Copy()
}
+ for addr, refund := range self.refund {
+ state.refund[addr] = refund
+ }
+
return state
}
@@ -199,6 +215,7 @@ func (self *State) Set(state *State) {
self.Trie = state.Trie
self.stateObjects = state.stateObjects
+ self.refund = state.refund
}
func (s *State) Root() interface{} {
@@ -240,10 +257,17 @@ func (s *State) Sync() {
func (self *State) Empty() {
self.stateObjects = make(map[string]*StateObject)
+ self.refund = make(map[string]*big.Int)
}
func (self *State) Update() {
var deleted bool
+
+ // Refund any gas that's left
+ for addr, amount := range self.refund {
+ self.GetStateObject([]byte(addr)).AddBalance(amount)
+ }
+
for _, stateObject := range self.stateObjects {
if stateObject.remove {
self.DeleteStateObject(stateObject)
diff --git a/ethtrie/trie.go b/ethtrie/trie.go
index 686971985..6db25db05 100644
--- a/ethtrie/trie.go
+++ b/ethtrie/trie.go
@@ -168,7 +168,24 @@ func New(db ethutil.Database, Root interface{}) *Trie {
r := copyRoot(Root)
p := copyRoot(Root)
- return &Trie{cache: NewCache(db), Root: r, prevRoot: p}
+ trie := &Trie{cache: NewCache(db), Root: r, prevRoot: p}
+ trie.setRoot(Root)
+
+ return trie
+}
+
+func (self *Trie) setRoot(root interface{}) {
+ switch t := root.(type) {
+ case string:
+ if t == "" {
+ root = ethcrypto.Sha3([]byte(""))
+ }
+ self.Root = root
+ case []byte:
+ self.Root = root
+ default:
+ self.Root = self.cache.PutValue(root, true)
+ }
}
/*
@@ -182,14 +199,7 @@ func (t *Trie) Update(key, value string) {
k := CompactHexDecode(key)
root := t.UpdateState(t.Root, k, value)
- switch root.(type) {
- case string:
- t.Root = root
- case []byte:
- t.Root = root
- default:
- t.Root = t.cache.PutValue(root, true)
- }
+ t.setRoot(root)
}
func (t *Trie) Get(key string) string {
@@ -209,13 +219,17 @@ func (t *Trie) Delete(key string) {
k := CompactHexDecode(key)
root := t.deleteState(t.Root, k)
- switch root.(type) {
+ t.setRoot(root)
+}
+
+func (self *Trie) GetRoot() []byte {
+ switch self.Root.(type) {
case string:
- t.Root = root
+ return []byte(self.Root.(string))
case []byte:
- t.Root = root
+ return self.Root.([]byte)
default:
- t.Root = t.cache.PutValue(root, true)
+ panic(fmt.Sprintf("invalid root type %T", self.Root))
}
}
diff --git a/ethutil/rlp.go b/ethutil/rlp.go
index 55406133b..1fff2b28a 100644
--- a/ethutil/rlp.go
+++ b/ethutil/rlp.go
@@ -15,6 +15,10 @@ type RlpEncodeDecode interface {
RlpValue() []interface{}
}
+type RlpEncodable interface {
+ RlpData() interface{}
+}
+
func Rlp(encoder RlpEncode) []byte {
return encoder.RlpEncode()
}
@@ -100,6 +104,8 @@ func Encode(object interface{}) []byte {
switch t := object.(type) {
case *Value:
buff.Write(Encode(t.Raw()))
+ case RlpEncodable:
+ buff.Write(Encode(t.RlpData()))
// Code dup :-/
case int:
buff.Write(Encode(big.NewInt(int64(t))))
diff --git a/ethutil/value.go b/ethutil/value.go
index dd777fa43..6417b0008 100644
--- a/ethutil/value.go
+++ b/ethutil/value.go
@@ -377,6 +377,10 @@ func (val *Value) NewIterator() *ValueIterator {
return &ValueIterator{value: val}
}
+func (it *ValueIterator) Len() int {
+ return it.value.Len()
+}
+
func (it *ValueIterator) Next() bool {
if it.idx >= it.value.Len() {
return false
diff --git a/ethwire/client_identity_test.go b/ethwire/client_identity_test.go
index f3c8bfd50..1724fe57b 100644
--- a/ethwire/client_identity_test.go
+++ b/ethwire/client_identity_test.go
@@ -9,22 +9,22 @@ import (
func TestClientIdentity(t *testing.T) {
clientIdentity := NewSimpleClientIdentity("Ethereum(G)", "0.5.16", "test")
clientString := clientIdentity.String()
- expected := fmt.Sprintf("Ethereum(G)/v0.5.16/test/%s/Go", runtime.GOOS)
+ expected := fmt.Sprintf("Ethereum(G)/v0.5.16/test/%s/%s", runtime.GOOS, runtime.Version())
if clientString != expected {
- t.Error("Expected clientIdentity to be %v, got %v", expected, clientString)
+ t.Errorf("Expected clientIdentity to be %q, got %q", expected, clientString)
}
customIdentifier := clientIdentity.GetCustomIdentifier()
if customIdentifier != "test" {
- t.Error("Expected clientIdentity.GetCustomIdentifier() to be 'test', got %v", customIdentifier)
+ t.Errorf("Expected clientIdentity.GetCustomIdentifier() to be 'test', got %q", customIdentifier)
}
clientIdentity.SetCustomIdentifier("test2")
customIdentifier = clientIdentity.GetCustomIdentifier()
if customIdentifier != "test2" {
- t.Error("Expected clientIdentity.GetCustomIdentifier() to be 'test2', got %v", customIdentifier)
+ t.Errorf("Expected clientIdentity.GetCustomIdentifier() to be 'test2', got %q", customIdentifier)
}
clientString = clientIdentity.String()
- expected = fmt.Sprintf("Ethereum(G)/v0.5.16/test2/%s/Go", runtime.GOOS)
+ expected = fmt.Sprintf("Ethereum(G)/v0.5.16/test2/%s/%s", runtime.GOOS, runtime.Version())
if clientString != expected {
- t.Error("Expected clientIdentity to be %v, got %v", expected, clientString)
+ t.Errorf("Expected clientIdentity to be %q, got %q", expected, clientString)
}
}
diff --git a/vm/common.go b/vm/common.go
index c73744506..16a0b5523 100644
--- a/vm/common.go
+++ b/vm/common.go
@@ -19,17 +19,18 @@ const (
)
var (
- GasStep = big.NewInt(1)
- GasSha = big.NewInt(20)
- GasSLoad = big.NewInt(20)
- GasSStore = big.NewInt(100)
- GasBalance = big.NewInt(20)
- GasCreate = big.NewInt(100)
- GasCall = big.NewInt(20)
- GasMemory = big.NewInt(1)
- GasData = big.NewInt(5)
- GasTx = big.NewInt(500)
- GasLog = big.NewInt(32)
+ GasStep = big.NewInt(1)
+ GasSha = big.NewInt(20)
+ GasSLoad = big.NewInt(20)
+ GasSStore = big.NewInt(100)
+ GasSStoreRefund = big.NewInt(100)
+ GasBalance = big.NewInt(20)
+ GasCreate = big.NewInt(100)
+ GasCall = big.NewInt(20)
+ 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/log.go b/vm/log.go
index 954d2ec91..bc72a0423 100644
--- a/vm/log.go
+++ b/vm/log.go
@@ -1,9 +1,38 @@
package vm
-import "math/big"
+import "github.com/ethereum/go-ethereum/ethutil"
type Log struct {
Address []byte
- Topics []*big.Int
+ Topics [][]byte
Data []byte
}
+
+func NewLogFromValue(decoder *ethutil.Value) Log {
+ log := Log{
+ Address: decoder.Get(0).Bytes(),
+ Data: decoder.Get(2).Bytes(),
+ }
+
+ it := decoder.Get(1).NewIterator()
+ for it.Next() {
+ log.Topics = append(log.Topics, it.Value().Bytes())
+ }
+
+ return log
+}
+
+func (self Log) RlpData() interface{} {
+ return []interface{}{self.Address, ethutil.ByteSliceToInterface(self.Topics), self.Data}
+}
+
+type Logs []Log
+
+func (self Logs) RlpData() interface{} {
+ data := make([]interface{}, len(self))
+ for i, log := range self {
+ data[i] = log.RlpData()
+ }
+
+ return data
+}
diff --git a/vm/vm_debug.go b/vm/vm_debug.go
index 13446d6c0..b3fbfe341 100644
--- a/vm/vm_debug.go
+++ b/vm/vm_debug.go
@@ -169,9 +169,13 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
gas.Set(ethutil.Big0)
case SLOAD:
+ require(1)
+
gas.Set(GasSLoad)
// Memory resize & Gas
case SSTORE:
+ require(2)
+
var mult *big.Int
y, x := stack.Peekn()
val := closure.GetStorage(x)
@@ -179,7 +183,8 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// 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))
+ state.Refund(closure.caller.Address(), GasSStoreRefund, closure.Price)
+
mult = ethutil.Big0
} else {
// non 0 => non 0
@@ -699,11 +704,11 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
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)
+ topics := make([][]byte, n)
mSize, mStart := stack.Pop().Int64(), stack.Pop().Int64()
data := mem.Geti(mStart, mSize)
for i := 0; i < n; i++ {
- topics[i] = stack.Pop()
+ topics[i] = stack.Pop().Bytes()
}
self.env.AddLog(Log{closure.Address(), topics, data})
case MLOAD:
diff --git a/vm/vm_test.go b/vm/vm_test.go
index 84cca3a9d..8818cc8ec 100644
--- a/vm/vm_test.go
+++ b/vm/vm_test.go
@@ -14,22 +14,30 @@ import (
"github.com/ethereum/go-ethereum/ethstate"
"github.com/ethereum/go-ethereum/ethtrie"
"github.com/ethereum/go-ethereum/ethutil"
+ "github.com/obscuren/mutan"
)
-type TestEnv struct {
+type TestEnv struct{}
+
+func (TestEnv) Origin() []byte { return nil }
+func (TestEnv) BlockNumber() *big.Int { return nil }
+func (TestEnv) BlockHash() []byte { return nil }
+func (TestEnv) PrevHash() []byte { return nil }
+func (TestEnv) Coinbase() []byte { return nil }
+func (TestEnv) Time() int64 { return 0 }
+func (TestEnv) GasLimit() *big.Int { return nil }
+func (TestEnv) Difficulty() *big.Int { return nil }
+func (TestEnv) Value() *big.Int { return nil }
+func (TestEnv) AddLog(Log) {}
+
+func (TestEnv) Transfer(from, to Account, amount *big.Int) error {
+ return nil
}
-func (self TestEnv) Origin() []byte { return nil }
-func (self TestEnv) BlockNumber() *big.Int { return nil }
-func (self TestEnv) BlockHash() []byte { return nil }
-func (self TestEnv) PrevHash() []byte { return nil }
-func (self TestEnv) Coinbase() []byte { return nil }
-func (self TestEnv) Time() int64 { return 0 }
-func (self TestEnv) Difficulty() *big.Int { return nil }
-func (self TestEnv) Value() *big.Int { return nil }
-
// This is likely to fail if anything ever gets looked up in the state trie :-)
-func (self TestEnv) State() *ethstate.State { return ethstate.New(ethtrie.New(nil, "")) }
+func (TestEnv) State() *ethstate.State {
+ return ethstate.New(ethtrie.New(nil, ""))
+}
const mutcode = `
var x = 0;
@@ -56,27 +64,35 @@ func setup(level ethlog.LogLevel, typ Type) (*Closure, VirtualMachine) {
return callerClosure, New(TestEnv{}, typ)
}
+var big9 = ethutil.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000009")
+
func TestDebugVm(t *testing.T) {
+ if mutan.Version < "0.6" {
+ t.Skip("skipping for mutan version", mutan.Version, " < 0.6")
+ }
+
closure, vm := setup(ethlog.DebugLevel, DebugVmTy)
ret, _, e := closure.Call(vm, nil)
if e != nil {
- fmt.Println("error", e)
+ t.Fatalf("Call returned error: %v", e)
}
-
- if ret[len(ret)-1] != 9 {
- t.Errorf("Expected VM to return 9, got", ret, "instead.")
+ if !bytes.Equal(ret, big9) {
+ t.Errorf("Wrong return value '%x', want '%x'", ret, big9)
}
}
func TestVm(t *testing.T) {
+ if mutan.Version < "0.6" {
+ t.Skip("skipping for mutan version", mutan.Version, " < 0.6")
+ }
+
closure, vm := setup(ethlog.DebugLevel, StandardVmTy)
ret, _, e := closure.Call(vm, nil)
if e != nil {
- fmt.Println("error", e)
+ t.Fatalf("Call returned error: %v", e)
}
-
- if ret[len(ret)-1] != 9 {
- t.Errorf("Expected VM to return 9, got", ret, "instead.")
+ if !bytes.Equal(ret, big9) {
+ t.Errorf("Wrong return value '%x', want '%x'", ret, big9)
}
}