Fixed minor issue with gas and added state object init
This commit is contained in:
parent
61cd1594b5
commit
3a9a252f6e
|
@ -91,11 +91,15 @@ func (sm *StateManager) BlockChain() *BlockChain {
|
||||||
return sm.bc
|
return sm.bc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *StateManager) MakeContract(tx *Transaction) {
|
func (sm *StateManager) MakeContract(tx *Transaction) *StateObject {
|
||||||
contract := MakeContract(tx, sm.procState)
|
contract := MakeContract(tx, sm.procState)
|
||||||
if contract != nil {
|
if contract != nil {
|
||||||
sm.procState.states[string(tx.Hash()[12:])] = contract.state
|
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
|
// 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) {
|
func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) {
|
||||||
// Process each transaction/contract
|
// Process each transaction/contract
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
|
fmt.Printf("Processing Tx: %x\n", tx.Hash())
|
||||||
// If there's no recipient, it's a contract
|
// If there's no recipient, it's a contract
|
||||||
// Check if this is a contract creation traction and if so
|
// Check if this is a contract creation traction and if so
|
||||||
// create a contract of this tx.
|
// create a contract of this tx.
|
||||||
if tx.IsContract() {
|
if tx.IsContract() {
|
||||||
sm.MakeContract(tx)
|
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() {
|
||||||
|
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 {
|
} else {
|
||||||
// Figure out if the address this transaction was sent to is a
|
// 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
|
// 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) {
|
func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Transaction, block *Block) {
|
||||||
// Recovering function in case the VM had any errors
|
// Recovering function in case the VM had any errors
|
||||||
defer func() {
|
/*
|
||||||
if r := recover(); r != nil {
|
defer func() {
|
||||||
fmt.Println("Recovered from VM execution with err =", r)
|
if r := recover(); r != nil {
|
||||||
}
|
fmt.Println("Recovered from VM execution with err =", r)
|
||||||
}()
|
}
|
||||||
|
}()
|
||||||
|
*/
|
||||||
|
|
||||||
caller := sm.procState.GetAccount(tx.Sender())
|
caller := sm.procState.GetAccount(tx.Sender())
|
||||||
closure := NewClosure(caller, object, script, sm.procState, tx.Gas, tx.GasPrice, tx.Value)
|
closure := NewClosure(caller, object, script, sm.procState, tx.Gas, tx.GasPrice, tx.Value)
|
||||||
|
|
|
@ -23,12 +23,12 @@ type Transaction struct {
|
||||||
contractCreation bool
|
contractCreation bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContractCreationTx(value, gasprice *big.Int, script []byte, init []byte) *Transaction {
|
func NewContractCreationTx(value, gas, gasPrice *big.Int, script []byte, init []byte) *Transaction {
|
||||||
return &Transaction{Value: value, GasPrice: gasprice, Data: script, Init: init, contractCreation: true}
|
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 {
|
func NewTransactionMessage(to []byte, value, gas, gasPrice *big.Int, data []byte) *Transaction {
|
||||||
return &Transaction{Recipient: to, Value: value, GasPrice: gasprice, Gas: gas, Data: data}
|
return &Transaction{Recipient: to, Value: value, GasPrice: gasPrice, Gas: gas, Data: data}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTransactionFromBytes(data []byte) *Transaction {
|
func NewTransactionFromBytes(data []byte) *Transaction {
|
||||||
|
@ -46,9 +46,10 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) Hash() []byte {
|
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 {
|
if tx.contractCreation {
|
||||||
data = append(data, string(tx.Init))
|
data = append(data, tx.Init)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ethutil.Sha3Bin(ethutil.NewValue(data).Encode())
|
return ethutil.Sha3Bin(ethutil.NewValue(data).Encode())
|
||||||
|
@ -112,7 +113,6 @@ func (tx *Transaction) RlpData() interface{} {
|
||||||
if tx.contractCreation {
|
if tx.contractCreation {
|
||||||
data = append(data, tx.Init)
|
data = append(data, tx.Init)
|
||||||
}
|
}
|
||||||
//d := ethutil.NewSliceValue(tx.Data).Slice()
|
|
||||||
|
|
||||||
return append(data, tx.v, tx.r, tx.s)
|
return append(data, tx.v, tx.r, tx.s)
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract
|
||||||
// funds won't invalidate this transaction but simple ignores it.
|
// funds won't invalidate this transaction but simple ignores it.
|
||||||
totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat))
|
totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat))
|
||||||
if sender.Amount.Cmp(totAmount) < 0 {
|
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 {
|
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 {
|
if bytes.Compare(tx.Recipient, tx.Sender()) == 0 {
|
||||||
// Subtract the fee
|
// Subtract the fee
|
||||||
sender.SubAmount(new(big.Int).Mul(TxFee, TxFeeRat))
|
sender.SubAmount(new(big.Int).Mul(TxFee, TxFeeRat))
|
||||||
} else if toContract {
|
|
||||||
sender.SubAmount(new(big.Int).Mul(TxFee, TxFeeRat))
|
|
||||||
} else {
|
} else {
|
||||||
// Subtract the amount from the senders account
|
// Subtract the amount from the senders account
|
||||||
sender.SubAmount(totAmount)
|
sender.SubAmount(totAmount)
|
||||||
|
|
|
@ -35,7 +35,7 @@ const (
|
||||||
oORIGIN = 0x32
|
oORIGIN = 0x32
|
||||||
oCALLER = 0x33
|
oCALLER = 0x33
|
||||||
oCALLVALUE = 0x34
|
oCALLVALUE = 0x34
|
||||||
oCALLDATA = 0x35
|
oCALLDATALOAD = 0x35
|
||||||
oCALLDATASIZE = 0x36
|
oCALLDATASIZE = 0x36
|
||||||
oGASPRICE = 0x37
|
oGASPRICE = 0x37
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ var opCodeToString = map[OpCode]string{
|
||||||
oORIGIN: "ORIGIN",
|
oORIGIN: "ORIGIN",
|
||||||
oCALLER: "CALLER",
|
oCALLER: "CALLER",
|
||||||
oCALLVALUE: "CALLVALUE",
|
oCALLVALUE: "CALLVALUE",
|
||||||
oCALLDATA: "CALLDATA",
|
oCALLDATALOAD: "CALLDATALOAD",
|
||||||
oCALLDATASIZE: "CALLDATASIZE",
|
oCALLDATASIZE: "CALLDATASIZE",
|
||||||
oGASPRICE: "TXGASPRICE",
|
oGASPRICE: "TXGASPRICE",
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ var OpCodes = map[string]byte{
|
||||||
"ORIGIN": 0x32,
|
"ORIGIN": 0x32,
|
||||||
"CALLER": 0x33,
|
"CALLER": 0x33,
|
||||||
"CALLVALUE": 0x34,
|
"CALLVALUE": 0x34,
|
||||||
"CALLDATA": 0x35,
|
"CALLDATALOAD": 0x35,
|
||||||
"CALLDATASIZE": 0x36,
|
"CALLDATASIZE": 0x36,
|
||||||
"GASPRICE": 0x38,
|
"GASPRICE": 0x38,
|
||||||
|
|
||||||
|
|
|
@ -84,11 +84,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||||
// The base for all big integer arithmetic
|
// The base for all big integer arithmetic
|
||||||
base := new(big.Int)
|
base := new(big.Int)
|
||||||
|
|
||||||
/*
|
if ethutil.Config.Debug {
|
||||||
if ethutil.Config.Debug {
|
ethutil.Config.Log.Debugf("# op\n")
|
||||||
ethutil.Config.Log.Debugf("# op\n")
|
}
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
step++
|
step++
|
||||||
|
@ -96,11 +94,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||||
val := closure.Get(pc)
|
val := closure.Get(pc)
|
||||||
// Get the opcode (it must be an opcode!)
|
// Get the opcode (it must be an opcode!)
|
||||||
op := OpCode(val.Uint())
|
op := OpCode(val.Uint())
|
||||||
/*
|
if ethutil.Config.Debug {
|
||||||
if ethutil.Config.Debug {
|
ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
|
||||||
ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
|
}
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
gas := new(big.Int)
|
gas := new(big.Int)
|
||||||
useGas := func(amount *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:
|
case oCALLVALUE:
|
||||||
// FIXME: Original value of the call, not the current value
|
// FIXME: Original value of the call, not the current value
|
||||||
stack.Push(closure.Value)
|
stack.Push(closure.Value)
|
||||||
case oCALLDATA:
|
case oCALLDATALOAD:
|
||||||
require(1)
|
require(1)
|
||||||
offset := stack.Pop()
|
offset := stack.Pop().Int64()
|
||||||
mem.Set(offset.Int64(), int64(len(closure.Args)), closure.Args)
|
val := closure.Args[offset : offset+31]
|
||||||
|
|
||||||
|
stack.Push(ethutil.BigD(val))
|
||||||
case oCALLDATASIZE:
|
case oCALLDATASIZE:
|
||||||
stack.Push(big.NewInt(int64(len(closure.Args))))
|
stack.Push(big.NewInt(int64(len(closure.Args))))
|
||||||
case oGASPRICE:
|
case oGASPRICE:
|
||||||
|
|
|
@ -3,7 +3,7 @@ package ethutil
|
||||||
import (
|
import (
|
||||||
_ "fmt"
|
_ "fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"regexp"
|
_ "regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Op codes
|
// Op codes
|
||||||
|
@ -143,7 +143,6 @@ init() {
|
||||||
main() {
|
main() {
|
||||||
// main something
|
// main something
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
func PreProcess(data string) (mainInput, initInput string) {
|
func PreProcess(data string) (mainInput, initInput string) {
|
||||||
reg := "\\(\\)\\s*{([\\d\\w\\W\\n\\s]+?)}"
|
reg := "\\(\\)\\s*{([\\d\\w\\W\\n\\s]+?)}"
|
||||||
mainReg := regexp.MustCompile("main" + reg)
|
mainReg := regexp.MustCompile("main" + reg)
|
||||||
|
@ -163,3 +162,49 @@ func PreProcess(data string) (mainInput, initInput string) {
|
||||||
|
|
||||||
return
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1,32 +1,31 @@
|
||||||
package ethutil
|
package ethutil
|
||||||
|
|
||||||
/*
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCompile(t *testing.T) {
|
func TestPreProcess(t *testing.T) {
|
||||||
instr, err := CompileInstr("PUSH")
|
main, init := PreProcess(`
|
||||||
|
init {
|
||||||
if err != nil {
|
// init
|
||||||
t.Error("Failed compiling instruction")
|
if a > b {
|
||||||
|
if {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
calc := (48 + 0*256 + 0*int64(math.Pow(256, 2)))
|
main {
|
||||||
if BigD(instr).Int64() != calc {
|
// main
|
||||||
t.Error("Expected", calc, ", got:", instr)
|
if a > b {
|
||||||
|
if c > d {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`)
|
||||||
|
|
||||||
func TestValidInstr(t *testing.T) {
|
|
||||||
op, args, err := Instr("68163")
|
|
||||||
if err != nil {
|
|
||||||
t.Error("Error decoding instruction")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fmt.Println("main")
|
||||||
|
fmt.Println(main)
|
||||||
|
fmt.Println("init")
|
||||||
|
fmt.Println(init)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalidInstr(t *testing.T) {
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
Loading…
Reference in New Issue