aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ethchain/state_manager.go53
-rw-r--r--ethchain/transaction.go14
-rw-r--r--ethchain/transaction_pool.go4
-rw-r--r--ethchain/types.go6
-rw-r--r--ethchain/vm.go24
-rw-r--r--ethutil/parsing.go49
-rw-r--r--ethutil/parsing_test.go41
7 files changed, 135 insertions, 56 deletions
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 75a78e9f3..23da77fae 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -91,11 +91,15 @@ func (sm *StateManager) BlockChain() *BlockChain {
return sm.bc
}
-func (sm *StateManager) MakeContract(tx *Transaction) {
+func (sm *StateManager) MakeContract(tx *Transaction) *StateObject {
contract := MakeContract(tx, sm.procState)
if contract != nil {
sm.procState.states[string(tx.Hash()[12:])] = contract.state
+
+ return contract
}
+
+ return nil
}
// Apply transactions uses the transaction passed to it and applies them onto
@@ -103,11 +107,44 @@ func (sm *StateManager) MakeContract(tx *Transaction) {
func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) {
// Process each transaction/contract
for _, tx := range txs {
+ fmt.Printf("Processing Tx: %x\n", tx.Hash())
+ // If there's no recipient, it's a contract
+ // Check if this is a contract creation traction and if so
+ // create a contract of this tx.
+ if tx.IsContract() {
+ err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
+ if err == nil {
+ contract := sm.MakeContract(tx)
+ if contract != nil {
+ sm.EvalScript(contract.Init(), contract, tx, block)
+ } else {
+ ethutil.Config.Log.Infoln("[STATE] Unable to create contract")
+ }
+ } else {
+ ethutil.Config.Log.Infoln("[STATE] contract create:", err)
+ }
+ } else {
+ err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
+ contract := sm.procState.GetContract(tx.Recipient)
+ if err == nil && len(contract.Script()) > 0 {
+ sm.EvalScript(contract.Script(), contract, tx, block)
+ } else if err != nil {
+ ethutil.Config.Log.Infoln("[STATE] process:", err)
+ }
+ }
+ }
+ // Process each transaction/contract
+ for _, tx := range txs {
// If there's no recipient, it's a contract
// Check if this is a contract creation traction and if so
// create a contract of this tx.
if tx.IsContract() {
- sm.MakeContract(tx)
+ contract := sm.MakeContract(tx)
+ if contract != nil {
+ sm.EvalScript(contract.Init(), contract, tx, block)
+ } else {
+ ethutil.Config.Log.Infoln("[STATE] Unable to create contract")
+ }
} else {
// Figure out if the address this transaction was sent to is a
// contract or an actual account. In case of a contract, we process that
@@ -303,11 +340,13 @@ func (sm *StateManager) Stop() {
func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Transaction, block *Block) {
// Recovering function in case the VM had any errors
- defer func() {
- if r := recover(); r != nil {
- fmt.Println("Recovered from VM execution with err =", r)
- }
- }()
+ /*
+ defer func() {
+ if r := recover(); r != nil {
+ fmt.Println("Recovered from VM execution with err =", r)
+ }
+ }()
+ */
caller := sm.procState.GetAccount(tx.Sender())
closure := NewClosure(caller, object, script, sm.procState, tx.Gas, tx.GasPrice, tx.Value)
diff --git a/ethchain/transaction.go b/ethchain/transaction.go
index 1e43a2bae..421f26c98 100644
--- a/ethchain/transaction.go
+++ b/ethchain/transaction.go
@@ -23,12 +23,12 @@ type Transaction struct {
contractCreation bool
}
-func NewContractCreationTx(value, gasprice *big.Int, script []byte, init []byte) *Transaction {
- return &Transaction{Value: value, GasPrice: gasprice, Data: script, Init: init, contractCreation: true}
+func NewContractCreationTx(value, gas, gasPrice *big.Int, script []byte, init []byte) *Transaction {
+ return &Transaction{Value: value, Gas: gas, GasPrice: gasPrice, Data: script, Init: init, contractCreation: true}
}
-func NewTransactionMessage(to []byte, value, gasprice, gas *big.Int, data []byte) *Transaction {
- return &Transaction{Recipient: to, Value: value, GasPrice: gasprice, Gas: gas, Data: data}
+func NewTransactionMessage(to []byte, value, gas, gasPrice *big.Int, data []byte) *Transaction {
+ return &Transaction{Recipient: to, Value: value, GasPrice: gasPrice, Gas: gas, Data: data}
}
func NewTransactionFromBytes(data []byte) *Transaction {
@@ -46,9 +46,10 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
}
func (tx *Transaction) Hash() []byte {
- data := []interface{}{tx.Nonce, tx.Value, tx.GasPrice, tx.Gas, tx.Recipient, string(tx.Data)}
+ data := []interface{}{tx.Nonce, tx.Value, tx.GasPrice, tx.Gas, tx.Recipient, tx.Data}
+
if tx.contractCreation {
- data = append(data, string(tx.Init))
+ data = append(data, tx.Init)
}
return ethutil.Sha3Bin(ethutil.NewValue(data).Encode())
@@ -112,7 +113,6 @@ func (tx *Transaction) RlpData() interface{} {
if tx.contractCreation {
data = append(data, tx.Init)
}
- //d := ethutil.NewSliceValue(tx.Data).Slice()
return append(data, tx.v, tx.r, tx.s)
}
diff --git a/ethchain/transaction_pool.go b/ethchain/transaction_pool.go
index 5cdda17e2..957381ac7 100644
--- a/ethchain/transaction_pool.go
+++ b/ethchain/transaction_pool.go
@@ -104,7 +104,7 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract
// funds won't invalidate this transaction but simple ignores it.
totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat))
if sender.Amount.Cmp(totAmount) < 0 {
- return errors.New("[TXPL] Insufficient amount in sender's account")
+ return fmt.Errorf("[TXPL] Insufficient amount in sender's (%x) account", tx.Sender())
}
if sender.Nonce != tx.Nonce {
@@ -119,8 +119,6 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract
if bytes.Compare(tx.Recipient, tx.Sender()) == 0 {
// Subtract the fee
sender.SubAmount(new(big.Int).Mul(TxFee, TxFeeRat))
- } else if toContract {
- sender.SubAmount(new(big.Int).Mul(TxFee, TxFeeRat))
} else {
// Subtract the amount from the senders account
sender.SubAmount(totAmount)
diff --git a/ethchain/types.go b/ethchain/types.go
index 24aad82c3..827d4f27f 100644
--- a/ethchain/types.go
+++ b/ethchain/types.go
@@ -35,7 +35,7 @@ const (
oORIGIN = 0x32
oCALLER = 0x33
oCALLVALUE = 0x34
- oCALLDATA = 0x35
+ oCALLDATALOAD = 0x35
oCALLDATASIZE = 0x36
oGASPRICE = 0x37
@@ -106,7 +106,7 @@ var opCodeToString = map[OpCode]string{
oORIGIN: "ORIGIN",
oCALLER: "CALLER",
oCALLVALUE: "CALLVALUE",
- oCALLDATA: "CALLDATA",
+ oCALLDATALOAD: "CALLDATALOAD",
oCALLDATASIZE: "CALLDATASIZE",
oGASPRICE: "TXGASPRICE",
@@ -180,7 +180,7 @@ var OpCodes = map[string]byte{
"ORIGIN": 0x32,
"CALLER": 0x33,
"CALLVALUE": 0x34,
- "CALLDATA": 0x35,
+ "CALLDATALOAD": 0x35,
"CALLDATASIZE": 0x36,
"GASPRICE": 0x38,
diff --git a/ethchain/vm.go b/ethchain/vm.go
index c249adfeb..33541cb3b 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -84,11 +84,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// The base for all big integer arithmetic
base := new(big.Int)
- /*
- if ethutil.Config.Debug {
- ethutil.Config.Log.Debugf("# op\n")
- }
- */
+ if ethutil.Config.Debug {
+ ethutil.Config.Log.Debugf("# op\n")
+ }
for {
step++
@@ -96,11 +94,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
val := closure.Get(pc)
// Get the opcode (it must be an opcode!)
op := OpCode(val.Uint())
- /*
- if ethutil.Config.Debug {
- ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
- }
- */
+ if ethutil.Config.Debug {
+ ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
+ }
gas := new(big.Int)
useGas := func(amount *big.Int) {
@@ -316,10 +312,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case oCALLVALUE:
// FIXME: Original value of the call, not the current value
stack.Push(closure.Value)
- case oCALLDATA:
+ case oCALLDATALOAD:
require(1)
- offset := stack.Pop()
- mem.Set(offset.Int64(), int64(len(closure.Args)), closure.Args)
+ offset := stack.Pop().Int64()
+ val := closure.Args[offset : offset+31]
+
+ stack.Push(ethutil.BigD(val))
case oCALLDATASIZE:
stack.Push(big.NewInt(int64(len(closure.Args))))
case oGASPRICE:
diff --git a/ethutil/parsing.go b/ethutil/parsing.go
index 328704cae..9775cf328 100644
--- a/ethutil/parsing.go
+++ b/ethutil/parsing.go
@@ -3,7 +3,7 @@ package ethutil
import (
_ "fmt"
"math/big"
- "regexp"
+ _ "regexp"
)
// Op codes
@@ -143,7 +143,6 @@ init() {
main() {
// main something
}
-*/
func PreProcess(data string) (mainInput, initInput string) {
reg := "\\(\\)\\s*{([\\d\\w\\W\\n\\s]+?)}"
mainReg := regexp.MustCompile("main" + reg)
@@ -163,3 +162,49 @@ func PreProcess(data string) (mainInput, initInput string) {
return
}
+*/
+
+// Very, very dumb parser. Heed no attention :-)
+func FindFor(blockMatcher, input string) string {
+ curCount := -1
+ length := len(blockMatcher)
+ matchfst := rune(blockMatcher[0])
+ var currStr string
+
+ for i, run := range input {
+ // Find init
+ if curCount == -1 && run == matchfst && input[i:i+length] == blockMatcher {
+ curCount = 0
+ } else if curCount > -1 {
+ if run == '{' {
+ curCount++
+ if curCount == 1 {
+ continue
+ }
+ } else if run == '}' {
+ curCount--
+ if curCount == 0 {
+ // we are done
+ curCount = -1
+ break
+ }
+ }
+
+ if curCount > 0 {
+ currStr += string(run)
+ }
+ }
+ }
+
+ return currStr
+}
+
+func PreProcess(data string) (mainInput, initInput string) {
+ mainInput = FindFor("main", data)
+ if mainInput == "" {
+ mainInput = data
+ }
+ initInput = FindFor("init", data)
+
+ return
+}
diff --git a/ethutil/parsing_test.go b/ethutil/parsing_test.go
index 6b59777e6..a9ad347dd 100644
--- a/ethutil/parsing_test.go
+++ b/ethutil/parsing_test.go
@@ -1,32 +1,31 @@
package ethutil
-/*
import (
- "math"
+ "fmt"
"testing"
)
-func TestCompile(t *testing.T) {
- instr, err := CompileInstr("PUSH")
-
- if err != nil {
- t.Error("Failed compiling instruction")
+func TestPreProcess(t *testing.T) {
+ main, init := PreProcess(`
+ init {
+ // init
+ if a > b {
+ if {
+ }
+ }
}
- calc := (48 + 0*256 + 0*int64(math.Pow(256, 2)))
- if BigD(instr).Int64() != calc {
- t.Error("Expected", calc, ", got:", instr)
+ main {
+ // main
+ if a > b {
+ if c > d {
+ }
+ }
}
-}
-
-func TestValidInstr(t *testing.T) {
- op, args, err := Instr("68163")
- if err != nil {
- t.Error("Error decoding instruction")
- }
-
-}
+ `)
-func TestInvalidInstr(t *testing.T) {
+ fmt.Println("main")
+ fmt.Println(main)
+ fmt.Println("init")
+ fmt.Println(init)
}
-*/