forked from cerc-io/plugeth
Merge branch 'release/poc5-rc11'
This commit is contained in:
commit
95adac7522
@ -6,7 +6,7 @@ Ethereum
|
||||
Ethereum Go Development package (C) Jeffrey Wilcke
|
||||
|
||||
Ethereum is currently in its testing phase. The current state is "Proof
|
||||
of Concept 5.0 RC9". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)).
|
||||
of Concept 5.0 RC11". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)).
|
||||
|
||||
Ethereum Go is split up in several sub packages Please refer to each
|
||||
individual package for more information.
|
||||
|
@ -21,9 +21,9 @@ func Disassemble(script []byte) (asm []string) {
|
||||
asm = append(asm, fmt.Sprintf("%v", op))
|
||||
|
||||
switch op {
|
||||
case oPUSH1, oPUSH2, oPUSH3, oPUSH4, oPUSH5, oPUSH6, oPUSH7, oPUSH8, oPUSH9, oPUSH10, oPUSH11, oPUSH12, oPUSH13, oPUSH14, oPUSH15, oPUSH16, oPUSH17, oPUSH18, oPUSH19, oPUSH20, oPUSH21, oPUSH22, oPUSH23, oPUSH24, oPUSH25, oPUSH26, oPUSH27, oPUSH28, oPUSH29, oPUSH30, oPUSH31, oPUSH32:
|
||||
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
|
||||
pc.Add(pc, ethutil.Big1)
|
||||
a := int64(op) - int64(oPUSH1) + 1
|
||||
a := int64(op) - int64(PUSH1) + 1
|
||||
data := script[pc.Int64() : pc.Int64()+a]
|
||||
val := ethutil.BigD(data)
|
||||
|
||||
|
@ -22,8 +22,7 @@ type Closure struct {
|
||||
Script []byte
|
||||
State *State
|
||||
|
||||
Gas *big.Int
|
||||
Price *big.Int
|
||||
Gas, UsedGas, Price *big.Int
|
||||
|
||||
Args []byte
|
||||
}
|
||||
@ -36,6 +35,7 @@ func NewClosure(callee, object *StateObject, script []byte, state *State, gas, p
|
||||
// and we don't want the transaction's values to change.
|
||||
c.Gas = new(big.Int).Set(gas)
|
||||
c.Price = new(big.Int).Set(price)
|
||||
c.UsedGas = new(big.Int)
|
||||
|
||||
return c
|
||||
}
|
||||
@ -74,10 +74,12 @@ func (c *Closure) Address() []byte {
|
||||
|
||||
type DebugHook func(step int, op OpCode, mem *Memory, stack *Stack, stateObject *StateObject) bool
|
||||
|
||||
func (c *Closure) Call(vm *Vm, args []byte, hook DebugHook) ([]byte, error) {
|
||||
func (c *Closure) Call(vm *Vm, args []byte, hook DebugHook) ([]byte, *big.Int, error) {
|
||||
c.Args = args
|
||||
|
||||
return vm.RunClosure(c, hook)
|
||||
ret, err := vm.RunClosure(c, hook)
|
||||
|
||||
return ret, c.UsedGas, err
|
||||
}
|
||||
|
||||
func (c *Closure) Return(ret []byte) []byte {
|
||||
@ -93,10 +95,23 @@ func (c *Closure) Return(ret []byte) []byte {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *Closure) UseGas(gas *big.Int) bool {
|
||||
if c.Gas.Cmp(gas) < 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Sub the amount of gas from the remaining
|
||||
c.Gas.Sub(c.Gas, gas)
|
||||
c.UsedGas.Add(c.UsedGas, gas)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Implement the Callee interface
|
||||
func (c *Closure) ReturnGas(gas, price *big.Int, state *State) {
|
||||
// Return the gas to the closure
|
||||
c.Gas.Add(c.Gas, gas)
|
||||
c.UsedGas.Sub(c.UsedGas, gas)
|
||||
}
|
||||
|
||||
func (c *Closure) Object() *StateObject {
|
||||
|
@ -105,10 +105,13 @@ func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Tra
|
||||
for _, tx := range txs {
|
||||
usedGas, err := sm.ApplyTransaction(state, block, tx)
|
||||
if err != nil {
|
||||
ethutil.Config.Log.Infoln(err)
|
||||
if IsNonceErr(err) {
|
||||
continue
|
||||
}
|
||||
|
||||
ethutil.Config.Log.Infoln(err)
|
||||
}
|
||||
|
||||
accumelative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, usedGas))
|
||||
receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative}
|
||||
|
||||
@ -116,10 +119,10 @@ func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Tra
|
||||
validTxs = append(validTxs, tx)
|
||||
}
|
||||
|
||||
return receipts, txs
|
||||
return receipts, validTxs
|
||||
}
|
||||
|
||||
func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transaction) (*big.Int, error) {
|
||||
func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transaction) (totalGasUsed *big.Int, err error) {
|
||||
/*
|
||||
Applies transactions to the given state and creates new
|
||||
state objects where needed.
|
||||
@ -129,9 +132,17 @@ func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transac
|
||||
assume there's a return value. The return value will be set to
|
||||
the script section of the state object.
|
||||
*/
|
||||
totalGasUsed := big.NewInt(0)
|
||||
var (
|
||||
addTotalGas = func(gas *big.Int) { totalGasUsed.Add(totalGasUsed, gas) }
|
||||
gas = new(big.Int)
|
||||
script []byte
|
||||
)
|
||||
totalGasUsed = big.NewInt(0)
|
||||
|
||||
// Apply the transaction to the current state
|
||||
err := sm.Ethereum.TxPool().ProcessTransaction(tx, state, false)
|
||||
gas, err = sm.Ethereum.TxPool().ProcessTransaction(tx, state, false)
|
||||
addTotalGas(gas)
|
||||
|
||||
if tx.CreatesContract() {
|
||||
if err == nil {
|
||||
// Create a new state object and the transaction
|
||||
@ -141,30 +152,32 @@ func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transac
|
||||
// Evaluate the initialization script
|
||||
// and use the return value as the
|
||||
// script section for the state object.
|
||||
script, err := sm.EvalScript(state, contract.Init(), contract, tx, block)
|
||||
script, gas, err = sm.EvalScript(state, contract.Init(), contract, tx, block)
|
||||
addTotalGas(gas)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[STATE] Error during init script run %v", err)
|
||||
err = fmt.Errorf("[STATE] Error during init script run %v", err)
|
||||
return
|
||||
}
|
||||
contract.script = script
|
||||
state.UpdateStateObject(contract)
|
||||
} else {
|
||||
return nil, fmt.Errorf("[STATE] Unable to create contract")
|
||||
err = fmt.Errorf("[STATE] Unable to create contract")
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("[STATE] contract creation tx:", err)
|
||||
err = fmt.Errorf("[STATE] contract creation tx: %v", err)
|
||||
}
|
||||
} else {
|
||||
// Find the state object at the "recipient" address. If
|
||||
// there's an object attempt to run the script.
|
||||
stateObject := state.GetStateObject(tx.Recipient)
|
||||
if err == nil && stateObject != nil && len(stateObject.Script()) > 0 {
|
||||
sm.EvalScript(state, stateObject.Script(), stateObject, tx, block)
|
||||
} else if err != nil {
|
||||
return nil, fmt.Errorf("[STATE] process:", err)
|
||||
_, gas, err = sm.EvalScript(state, stateObject.Script(), stateObject, tx, block)
|
||||
addTotalGas(gas)
|
||||
}
|
||||
}
|
||||
|
||||
return totalGasUsed, nil
|
||||
return
|
||||
}
|
||||
|
||||
func (sm *StateManager) Process(block *Block, dontReact bool) error {
|
||||
@ -349,7 +362,7 @@ func (sm *StateManager) Stop() {
|
||||
sm.bc.Stop()
|
||||
}
|
||||
|
||||
func (sm *StateManager) EvalScript(state *State, script []byte, object *StateObject, tx *Transaction, block *Block) (ret []byte, err error) {
|
||||
func (sm *StateManager) EvalScript(state *State, script []byte, object *StateObject, tx *Transaction, block *Block) (ret []byte, gas *big.Int, err error) {
|
||||
account := state.GetAccount(tx.Sender())
|
||||
|
||||
err = account.ConvertGas(tx.Gas, tx.GasPrice)
|
||||
@ -369,7 +382,7 @@ func (sm *StateManager) EvalScript(state *State, script []byte, object *StateObj
|
||||
Value: tx.Value,
|
||||
//Price: tx.GasPrice,
|
||||
})
|
||||
ret, err = closure.Call(vm, tx.Data, nil)
|
||||
ret, gas, err = closure.Call(vm, tx.Data, nil)
|
||||
|
||||
// Update the account (refunds)
|
||||
state.UpdateStateObject(account)
|
||||
|
@ -147,22 +147,6 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
|
||||
if len(tx.Recipient) == 0 {
|
||||
tx.contractCreation = true
|
||||
}
|
||||
|
||||
/*
|
||||
// If the list is of length 10 it's a contract creation tx
|
||||
if decoder.Len() == 10 {
|
||||
tx.contractCreation = true
|
||||
tx.Init = decoder.Get(6).Bytes()
|
||||
|
||||
tx.v = byte(decoder.Get(7).Uint())
|
||||
tx.r = decoder.Get(8).Bytes()
|
||||
tx.s = decoder.Get(9).Bytes()
|
||||
} else {
|
||||
tx.v = byte(decoder.Get(6).Uint())
|
||||
tx.r = decoder.Get(7).Bytes()
|
||||
tx.s = decoder.Get(8).Bytes()
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
func (tx *Transaction) String() string {
|
||||
@ -228,3 +212,15 @@ func (self *Receipt) String() string {
|
||||
self.PostState,
|
||||
self.CumulativeGasUsed)
|
||||
}
|
||||
|
||||
// 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] }
|
||||
|
||||
type TxByNonce struct{ Transactions }
|
||||
|
||||
func (s TxByNonce) Less(i, j int) bool {
|
||||
return s.Transactions[i].Nonce < s.Transactions[j].Nonce
|
||||
}
|
||||
|
@ -91,28 +91,37 @@ func (pool *TxPool) addTransaction(tx *Transaction) {
|
||||
|
||||
// Process transaction validates the Tx and processes funds from the
|
||||
// sender to the recipient.
|
||||
func (pool *TxPool) ProcessTransaction(tx *Transaction, state *State, toContract bool) (err error) {
|
||||
func (pool *TxPool) ProcessTransaction(tx *Transaction, state *State, toContract bool) (gas *big.Int, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ethutil.Config.Log.Infoln(r)
|
||||
err = fmt.Errorf("%v", r)
|
||||
}
|
||||
}()
|
||||
|
||||
gas = new(big.Int)
|
||||
addGas := func(g *big.Int) { gas.Add(gas, g) }
|
||||
|
||||
// Get the sender
|
||||
sender := state.GetAccount(tx.Sender())
|
||||
|
||||
if sender.Nonce != tx.Nonce {
|
||||
return fmt.Errorf("[TXPL] Invalid account nonce, state nonce is %d transaction nonce is %d instead", sender.Nonce, tx.Nonce)
|
||||
err = NonceError(tx.Nonce, sender.Nonce)
|
||||
return
|
||||
}
|
||||
|
||||
txTotalBytes := big.NewInt(int64(len(tx.Data)))
|
||||
txTotalBytes.Div(txTotalBytes, ethutil.Big32)
|
||||
addGas(new(big.Int).Mul(txTotalBytes, GasSStore))
|
||||
|
||||
// Make sure there's enough in the sender's account. Having insufficient
|
||||
// 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(tx.Gas, tx.GasPrice))
|
||||
if sender.Amount.Cmp(totAmount) < 0 {
|
||||
return fmt.Errorf("[TXPL] Insufficient amount in sender's (%x) account", tx.Sender())
|
||||
err = fmt.Errorf("[TXPL] Insufficient amount in sender's (%x) account", tx.Sender())
|
||||
return
|
||||
}
|
||||
//fmt.Println(tx)
|
||||
|
||||
// Get the receiver
|
||||
receiver := state.GetAccount(tx.Recipient)
|
||||
@ -120,6 +129,7 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, state *State, toContract
|
||||
|
||||
// Send Tx to self
|
||||
if bytes.Compare(tx.Recipient, tx.Sender()) == 0 {
|
||||
addGas(GasTx)
|
||||
// Subtract the fee
|
||||
sender.SubAmount(new(big.Int).Mul(GasTx, tx.GasPrice))
|
||||
} else {
|
||||
@ -225,7 +235,7 @@ func (pool *TxPool) RemoveInvalid(state *State) {
|
||||
tx := e.Value.(*Transaction)
|
||||
sender := state.GetAccount(tx.Sender())
|
||||
err := pool.ValidateTransaction(tx)
|
||||
if err != nil || sender.Nonce != tx.Nonce {
|
||||
if err != nil || sender.Nonce >= tx.Nonce {
|
||||
pool.pool.Remove(e)
|
||||
}
|
||||
}
|
||||
|
@ -5,206 +5,206 @@ type OpCode int
|
||||
// Op codes
|
||||
const (
|
||||
// 0x0 range - arithmetic ops
|
||||
oSTOP = 0x00
|
||||
oADD = 0x01
|
||||
oMUL = 0x02
|
||||
oSUB = 0x03
|
||||
oDIV = 0x04
|
||||
oSDIV = 0x05
|
||||
oMOD = 0x06
|
||||
oSMOD = 0x07
|
||||
oEXP = 0x08
|
||||
oNEG = 0x09
|
||||
oLT = 0x0a
|
||||
oGT = 0x0b
|
||||
oEQ = 0x0c
|
||||
oNOT = 0x0d
|
||||
STOP = 0x00
|
||||
ADD = 0x01
|
||||
MUL = 0x02
|
||||
SUB = 0x03
|
||||
DIV = 0x04
|
||||
SDIV = 0x05
|
||||
MOD = 0x06
|
||||
SMOD = 0x07
|
||||
EXP = 0x08
|
||||
NEG = 0x09
|
||||
LT = 0x0a
|
||||
GT = 0x0b
|
||||
EQ = 0x0c
|
||||
NOT = 0x0d
|
||||
|
||||
// 0x10 range - bit ops
|
||||
oAND = 0x10
|
||||
oOR = 0x11
|
||||
oXOR = 0x12
|
||||
oBYTE = 0x13
|
||||
AND = 0x10
|
||||
OR = 0x11
|
||||
XOR = 0x12
|
||||
BYTE = 0x13
|
||||
|
||||
// 0x20 range - crypto
|
||||
oSHA3 = 0x20
|
||||
SHA3 = 0x20
|
||||
|
||||
// 0x30 range - closure state
|
||||
oADDRESS = 0x30
|
||||
oBALANCE = 0x31
|
||||
oORIGIN = 0x32
|
||||
oCALLER = 0x33
|
||||
oCALLVALUE = 0x34
|
||||
oCALLDATALOAD = 0x35
|
||||
oCALLDATASIZE = 0x36
|
||||
oGASPRICE = 0x37
|
||||
ADDRESS = 0x30
|
||||
BALANCE = 0x31
|
||||
ORIGIN = 0x32
|
||||
CALLER = 0x33
|
||||
CALLVALUE = 0x34
|
||||
CALLDATALOAD = 0x35
|
||||
CALLDATASIZE = 0x36
|
||||
GASPRICE = 0x37
|
||||
|
||||
// 0x40 range - block operations
|
||||
oPREVHASH = 0x40
|
||||
oCOINBASE = 0x41
|
||||
oTIMESTAMP = 0x42
|
||||
oNUMBER = 0x43
|
||||
oDIFFICULTY = 0x44
|
||||
oGASLIMIT = 0x45
|
||||
PREVHASH = 0x40
|
||||
COINBASE = 0x41
|
||||
TIMESTAMP = 0x42
|
||||
NUMBER = 0x43
|
||||
DIFFICULTY = 0x44
|
||||
GASLIMIT = 0x45
|
||||
|
||||
// 0x50 range - 'storage' and execution
|
||||
oPOP = 0x51
|
||||
oDUP = 0x52
|
||||
oSWAP = 0x53
|
||||
oMLOAD = 0x54
|
||||
oMSTORE = 0x55
|
||||
oMSTORE8 = 0x56
|
||||
oSLOAD = 0x57
|
||||
oSSTORE = 0x58
|
||||
oJUMP = 0x59
|
||||
oJUMPI = 0x5a
|
||||
oPC = 0x5b
|
||||
oMSIZE = 0x5c
|
||||
POP = 0x51
|
||||
DUP = 0x52
|
||||
SWAP = 0x53
|
||||
MLOAD = 0x54
|
||||
MSTORE = 0x55
|
||||
MSTORE8 = 0x56
|
||||
SLOAD = 0x57
|
||||
SSTORE = 0x58
|
||||
JUMP = 0x59
|
||||
JUMPI = 0x5a
|
||||
PC = 0x5b
|
||||
MSIZE = 0x5c
|
||||
|
||||
// 0x60 range
|
||||
oPUSH1 = 0x60
|
||||
oPUSH2 = 0x61
|
||||
oPUSH3 = 0x62
|
||||
oPUSH4 = 0x63
|
||||
oPUSH5 = 0x64
|
||||
oPUSH6 = 0x65
|
||||
oPUSH7 = 0x66
|
||||
oPUSH8 = 0x67
|
||||
oPUSH9 = 0x68
|
||||
oPUSH10 = 0x69
|
||||
oPUSH11 = 0x6a
|
||||
oPUSH12 = 0x6b
|
||||
oPUSH13 = 0x6c
|
||||
oPUSH14 = 0x6d
|
||||
oPUSH15 = 0x6e
|
||||
oPUSH16 = 0x6f
|
||||
oPUSH17 = 0x70
|
||||
oPUSH18 = 0x71
|
||||
oPUSH19 = 0x72
|
||||
oPUSH20 = 0x73
|
||||
oPUSH21 = 0x74
|
||||
oPUSH22 = 0x75
|
||||
oPUSH23 = 0x76
|
||||
oPUSH24 = 0x77
|
||||
oPUSH25 = 0x78
|
||||
oPUSH26 = 0x79
|
||||
oPUSH27 = 0x7a
|
||||
oPUSH28 = 0x7b
|
||||
oPUSH29 = 0x7c
|
||||
oPUSH30 = 0x7d
|
||||
oPUSH31 = 0x7e
|
||||
oPUSH32 = 0x7f
|
||||
PUSH1 = 0x60
|
||||
PUSH2 = 0x61
|
||||
PUSH3 = 0x62
|
||||
PUSH4 = 0x63
|
||||
PUSH5 = 0x64
|
||||
PUSH6 = 0x65
|
||||
PUSH7 = 0x66
|
||||
PUSH8 = 0x67
|
||||
PUSH9 = 0x68
|
||||
PUSH10 = 0x69
|
||||
PUSH11 = 0x6a
|
||||
PUSH12 = 0x6b
|
||||
PUSH13 = 0x6c
|
||||
PUSH14 = 0x6d
|
||||
PUSH15 = 0x6e
|
||||
PUSH16 = 0x6f
|
||||
PUSH17 = 0x70
|
||||
PUSH18 = 0x71
|
||||
PUSH19 = 0x72
|
||||
PUSH20 = 0x73
|
||||
PUSH21 = 0x74
|
||||
PUSH22 = 0x75
|
||||
PUSH23 = 0x76
|
||||
PUSH24 = 0x77
|
||||
PUSH25 = 0x78
|
||||
PUSH26 = 0x79
|
||||
PUSH27 = 0x7a
|
||||
PUSH28 = 0x7b
|
||||
PUSH29 = 0x7c
|
||||
PUSH30 = 0x7d
|
||||
PUSH31 = 0x7e
|
||||
PUSH32 = 0x7f
|
||||
|
||||
// 0xf0 range - closures
|
||||
oCREATE = 0xf0
|
||||
oCALL = 0xf1
|
||||
oRETURN = 0xf2
|
||||
CREATE = 0xf0
|
||||
CALL = 0xf1
|
||||
RETURN = 0xf2
|
||||
|
||||
// 0x70 range - other
|
||||
oLOG = 0xfe // XXX Unofficial
|
||||
oSUICIDE = 0xff
|
||||
LOG = 0xfe // XXX Unofficial
|
||||
SUICIDE = 0xff
|
||||
)
|
||||
|
||||
// Since the opcodes aren't all in order we can't use a regular slice
|
||||
var opCodeToString = map[OpCode]string{
|
||||
// 0x0 range - arithmetic ops
|
||||
oSTOP: "STOP",
|
||||
oADD: "ADD",
|
||||
oMUL: "MUL",
|
||||
oSUB: "SUB",
|
||||
oDIV: "DIV",
|
||||
oSDIV: "SDIV",
|
||||
oMOD: "MOD",
|
||||
oSMOD: "SMOD",
|
||||
oEXP: "EXP",
|
||||
oNEG: "NEG",
|
||||
oLT: "LT",
|
||||
oGT: "GT",
|
||||
oEQ: "EQ",
|
||||
oNOT: "NOT",
|
||||
STOP: "STOP",
|
||||
ADD: "ADD",
|
||||
MUL: "MUL",
|
||||
SUB: "SUB",
|
||||
DIV: "DIV",
|
||||
SDIV: "SDIV",
|
||||
MOD: "MOD",
|
||||
SMOD: "SMOD",
|
||||
EXP: "EXP",
|
||||
NEG: "NEG",
|
||||
LT: "LT",
|
||||
GT: "GT",
|
||||
EQ: "EQ",
|
||||
NOT: "NOT",
|
||||
|
||||
// 0x10 range - bit ops
|
||||
oAND: "AND",
|
||||
oOR: "OR",
|
||||
oXOR: "XOR",
|
||||
oBYTE: "BYTE",
|
||||
AND: "AND",
|
||||
OR: "OR",
|
||||
XOR: "XOR",
|
||||
BYTE: "BYTE",
|
||||
|
||||
// 0x20 range - crypto
|
||||
oSHA3: "SHA3",
|
||||
SHA3: "SHA3",
|
||||
|
||||
// 0x30 range - closure state
|
||||
oADDRESS: "ADDRESS",
|
||||
oBALANCE: "BALANCE",
|
||||
oORIGIN: "ORIGIN",
|
||||
oCALLER: "CALLER",
|
||||
oCALLVALUE: "CALLVALUE",
|
||||
oCALLDATALOAD: "CALLDATALOAD",
|
||||
oCALLDATASIZE: "CALLDATASIZE",
|
||||
oGASPRICE: "TXGASPRICE",
|
||||
ADDRESS: "ADDRESS",
|
||||
BALANCE: "BALANCE",
|
||||
ORIGIN: "ORIGIN",
|
||||
CALLER: "CALLER",
|
||||
CALLVALUE: "CALLVALUE",
|
||||
CALLDATALOAD: "CALLDATALOAD",
|
||||
CALLDATASIZE: "CALLDATASIZE",
|
||||
GASPRICE: "TXGASPRICE",
|
||||
|
||||
// 0x40 range - block operations
|
||||
oPREVHASH: "PREVHASH",
|
||||
oCOINBASE: "COINBASE",
|
||||
oTIMESTAMP: "TIMESTAMP",
|
||||
oNUMBER: "NUMBER",
|
||||
oDIFFICULTY: "DIFFICULTY",
|
||||
oGASLIMIT: "GASLIMIT",
|
||||
PREVHASH: "PREVHASH",
|
||||
COINBASE: "COINBASE",
|
||||
TIMESTAMP: "TIMESTAMP",
|
||||
NUMBER: "NUMBER",
|
||||
DIFFICULTY: "DIFFICULTY",
|
||||
GASLIMIT: "GASLIMIT",
|
||||
|
||||
// 0x50 range - 'storage' and execution
|
||||
oDUP: "DUP",
|
||||
oSWAP: "SWAP",
|
||||
oMLOAD: "MLOAD",
|
||||
oMSTORE: "MSTORE",
|
||||
oMSTORE8: "MSTORE8",
|
||||
oSLOAD: "SLOAD",
|
||||
oSSTORE: "SSTORE",
|
||||
oJUMP: "JUMP",
|
||||
oJUMPI: "JUMPI",
|
||||
oPC: "PC",
|
||||
oMSIZE: "MSIZE",
|
||||
DUP: "DUP",
|
||||
SWAP: "SWAP",
|
||||
MLOAD: "MLOAD",
|
||||
MSTORE: "MSTORE",
|
||||
MSTORE8: "MSTORE8",
|
||||
SLOAD: "SLOAD",
|
||||
SSTORE: "SSTORE",
|
||||
JUMP: "JUMP",
|
||||
JUMPI: "JUMPI",
|
||||
PC: "PC",
|
||||
MSIZE: "MSIZE",
|
||||
|
||||
// 0x60 range - push
|
||||
oPUSH1: "PUSH1",
|
||||
oPUSH2: "PUSH2",
|
||||
oPUSH3: "PUSH3",
|
||||
oPUSH4: "PUSH4",
|
||||
oPUSH5: "PUSH5",
|
||||
oPUSH6: "PUSH6",
|
||||
oPUSH7: "PUSH7",
|
||||
oPUSH8: "PUSH8",
|
||||
oPUSH9: "PUSH9",
|
||||
oPUSH10: "PUSH10",
|
||||
oPUSH11: "PUSH11",
|
||||
oPUSH12: "PUSH12",
|
||||
oPUSH13: "PUSH13",
|
||||
oPUSH14: "PUSH14",
|
||||
oPUSH15: "PUSH15",
|
||||
oPUSH16: "PUSH16",
|
||||
oPUSH17: "PUSH17",
|
||||
oPUSH18: "PUSH18",
|
||||
oPUSH19: "PUSH19",
|
||||
oPUSH20: "PUSH20",
|
||||
oPUSH21: "PUSH21",
|
||||
oPUSH22: "PUSH22",
|
||||
oPUSH23: "PUSH23",
|
||||
oPUSH24: "PUSH24",
|
||||
oPUSH25: "PUSH25",
|
||||
oPUSH26: "PUSH26",
|
||||
oPUSH27: "PUSH27",
|
||||
oPUSH28: "PUSH28",
|
||||
oPUSH29: "PUSH29",
|
||||
oPUSH30: "PUSH30",
|
||||
oPUSH31: "PUSH31",
|
||||
oPUSH32: "PUSH32",
|
||||
PUSH1: "PUSH1",
|
||||
PUSH2: "PUSH2",
|
||||
PUSH3: "PUSH3",
|
||||
PUSH4: "PUSH4",
|
||||
PUSH5: "PUSH5",
|
||||
PUSH6: "PUSH6",
|
||||
PUSH7: "PUSH7",
|
||||
PUSH8: "PUSH8",
|
||||
PUSH9: "PUSH9",
|
||||
PUSH10: "PUSH10",
|
||||
PUSH11: "PUSH11",
|
||||
PUSH12: "PUSH12",
|
||||
PUSH13: "PUSH13",
|
||||
PUSH14: "PUSH14",
|
||||
PUSH15: "PUSH15",
|
||||
PUSH16: "PUSH16",
|
||||
PUSH17: "PUSH17",
|
||||
PUSH18: "PUSH18",
|
||||
PUSH19: "PUSH19",
|
||||
PUSH20: "PUSH20",
|
||||
PUSH21: "PUSH21",
|
||||
PUSH22: "PUSH22",
|
||||
PUSH23: "PUSH23",
|
||||
PUSH24: "PUSH24",
|
||||
PUSH25: "PUSH25",
|
||||
PUSH26: "PUSH26",
|
||||
PUSH27: "PUSH27",
|
||||
PUSH28: "PUSH28",
|
||||
PUSH29: "PUSH29",
|
||||
PUSH30: "PUSH30",
|
||||
PUSH31: "PUSH31",
|
||||
PUSH32: "PUSH32",
|
||||
|
||||
// 0xf0 range
|
||||
oCREATE: "CREATE",
|
||||
oCALL: "CALL",
|
||||
oRETURN: "RETURN",
|
||||
CREATE: "CREATE",
|
||||
CALL: "CALL",
|
||||
RETURN: "RETURN",
|
||||
|
||||
// 0x70 range - other
|
||||
oLOG: "LOG",
|
||||
oSUICIDE: "SUICIDE",
|
||||
LOG: "LOG",
|
||||
SUICIDE: "SUICIDE",
|
||||
}
|
||||
|
||||
func (o OpCode) String() string {
|
||||
@ -322,10 +322,3 @@ func IsOpCode(s string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func AppendScript(init, script []byte) []byte {
|
||||
s := append(init, byte(oRETURN))
|
||||
s = append(s, script...)
|
||||
|
||||
return s
|
||||
}
|
||||
|
164
ethchain/vm.go
164
ethchain/vm.go
@ -21,11 +21,10 @@ var (
|
||||
GasTx = big.NewInt(500)
|
||||
)
|
||||
|
||||
func CalculateTxGas(initSize, scriptSize *big.Int) *big.Int {
|
||||
func CalculateTxGas(initSize *big.Int) *big.Int {
|
||||
totalGas := new(big.Int)
|
||||
totalGas.Add(totalGas, GasCreate)
|
||||
|
||||
txTotalBytes := new(big.Int).Add(initSize, scriptSize)
|
||||
txTotalBytes := new(big.Int).Set(initSize)
|
||||
txTotalBytes.Div(txTotalBytes, ethutil.Big32)
|
||||
totalGas.Add(totalGas, new(big.Int).Mul(txTotalBytes, GasSStore))
|
||||
|
||||
@ -92,12 +91,14 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
pc := big.NewInt(0)
|
||||
// Current step count
|
||||
step := 0
|
||||
prevStep := 0
|
||||
|
||||
if ethutil.Config.Debug {
|
||||
ethutil.Config.Log.Debugf("# op\n")
|
||||
}
|
||||
|
||||
for {
|
||||
prevStep = step
|
||||
// The base for all big integer arithmetic
|
||||
base := new(big.Int)
|
||||
|
||||
@ -111,16 +112,16 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
}
|
||||
|
||||
gas := new(big.Int)
|
||||
useGas := func(amount *big.Int) {
|
||||
setStepGasUsage := func(amount *big.Int) {
|
||||
gas.Add(gas, amount)
|
||||
}
|
||||
|
||||
switch op {
|
||||
case oSHA3:
|
||||
useGas(GasSha)
|
||||
case oSLOAD:
|
||||
useGas(GasSLoad)
|
||||
case oSSTORE:
|
||||
case SHA3:
|
||||
setStepGasUsage(GasSha)
|
||||
case SLOAD:
|
||||
setStepGasUsage(GasSLoad)
|
||||
case SSTORE:
|
||||
var mult *big.Int
|
||||
y, x := stack.Peekn()
|
||||
val := closure.GetMem(x)
|
||||
@ -131,67 +132,64 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
} else {
|
||||
mult = ethutil.Big1
|
||||
}
|
||||
useGas(new(big.Int).Mul(mult, GasSStore))
|
||||
case oBALANCE:
|
||||
useGas(GasBalance)
|
||||
case oCREATE:
|
||||
setStepGasUsage(new(big.Int).Mul(mult, GasSStore))
|
||||
case BALANCE:
|
||||
setStepGasUsage(GasBalance)
|
||||
case CREATE:
|
||||
require(3)
|
||||
|
||||
args := stack.Get(big.NewInt(3))
|
||||
initSize := new(big.Int).Add(args[1], args[0])
|
||||
|
||||
useGas(CalculateTxGas(initSize, ethutil.Big0))
|
||||
case oCALL:
|
||||
useGas(GasCall)
|
||||
case oMLOAD, oMSIZE, oMSTORE8, oMSTORE:
|
||||
useGas(GasMemory)
|
||||
setStepGasUsage(CalculateTxGas(initSize))
|
||||
case CALL:
|
||||
setStepGasUsage(GasCall)
|
||||
case MLOAD, MSIZE, MSTORE8, MSTORE:
|
||||
setStepGasUsage(GasMemory)
|
||||
default:
|
||||
useGas(GasStep)
|
||||
setStepGasUsage(GasStep)
|
||||
}
|
||||
|
||||
if closure.Gas.Cmp(gas) < 0 {
|
||||
if !closure.UseGas(gas) {
|
||||
ethutil.Config.Log.Debugln("Insufficient gas", closure.Gas, gas)
|
||||
|
||||
return closure.Return(nil), fmt.Errorf("insufficient gas %v %v", closure.Gas, gas)
|
||||
}
|
||||
|
||||
// Sub the amount of gas from the remaining
|
||||
closure.Gas.Sub(closure.Gas, gas)
|
||||
|
||||
switch op {
|
||||
case oLOG:
|
||||
case LOG:
|
||||
stack.Print()
|
||||
mem.Print()
|
||||
// 0x20 range
|
||||
case oADD:
|
||||
case ADD:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
// (x + y) % 2 ** 256
|
||||
base.Add(x, y)
|
||||
// Pop result back on the stack
|
||||
stack.Push(base)
|
||||
case oSUB:
|
||||
case SUB:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
// (x - y) % 2 ** 256
|
||||
base.Sub(x, y)
|
||||
// Pop result back on the stack
|
||||
stack.Push(base)
|
||||
case oMUL:
|
||||
case MUL:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
// (x * y) % 2 ** 256
|
||||
base.Mul(x, y)
|
||||
// Pop result back on the stack
|
||||
stack.Push(base)
|
||||
case oDIV:
|
||||
case DIV:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
// floor(x / y)
|
||||
base.Div(x, y)
|
||||
// Pop result back on the stack
|
||||
stack.Push(base)
|
||||
case oSDIV:
|
||||
case SDIV:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
// n > 2**255
|
||||
@ -208,12 +206,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
}
|
||||
// Push result on to the stack
|
||||
stack.Push(z)
|
||||
case oMOD:
|
||||
case MOD:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
base.Mod(x, y)
|
||||
stack.Push(base)
|
||||
case oSMOD:
|
||||
case SMOD:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
// n > 2**255
|
||||
@ -230,17 +228,17 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
}
|
||||
// Push result on to the stack
|
||||
stack.Push(z)
|
||||
case oEXP:
|
||||
case EXP:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
base.Exp(x, y, Pow256)
|
||||
|
||||
stack.Push(base)
|
||||
case oNEG:
|
||||
case NEG:
|
||||
require(1)
|
||||
base.Sub(Pow256, stack.Pop())
|
||||
stack.Push(base)
|
||||
case oLT:
|
||||
case LT:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
// x < y
|
||||
@ -249,7 +247,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
} else {
|
||||
stack.Push(ethutil.BigFalse)
|
||||
}
|
||||
case oGT:
|
||||
case GT:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
// x > y
|
||||
@ -258,7 +256,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
} else {
|
||||
stack.Push(ethutil.BigFalse)
|
||||
}
|
||||
case oEQ:
|
||||
case EQ:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
// x == y
|
||||
@ -267,7 +265,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
} else {
|
||||
stack.Push(ethutil.BigFalse)
|
||||
}
|
||||
case oNOT:
|
||||
case NOT:
|
||||
require(1)
|
||||
x := stack.Pop()
|
||||
if x.Cmp(ethutil.BigFalse) == 0 {
|
||||
@ -277,7 +275,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
}
|
||||
|
||||
// 0x10 range
|
||||
case oAND:
|
||||
case AND:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
if (x.Cmp(ethutil.BigTrue) >= 0) && (y.Cmp(ethutil.BigTrue) >= 0) {
|
||||
@ -286,7 +284,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
stack.Push(ethutil.BigFalse)
|
||||
}
|
||||
|
||||
case oOR:
|
||||
case OR:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
if (x.Cmp(ethutil.BigInt0) >= 0) || (y.Cmp(ethutil.BigInt0) >= 0) {
|
||||
@ -294,11 +292,11 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
} else {
|
||||
stack.Push(ethutil.BigFalse)
|
||||
}
|
||||
case oXOR:
|
||||
case XOR:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
stack.Push(base.Xor(x, y))
|
||||
case oBYTE:
|
||||
case BYTE:
|
||||
require(2)
|
||||
val, th := stack.Popn()
|
||||
if th.Cmp(big.NewInt(32)) < 0 {
|
||||
@ -308,92 +306,92 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
}
|
||||
|
||||
// 0x20 range
|
||||
case oSHA3:
|
||||
case SHA3:
|
||||
require(2)
|
||||
size, offset := stack.Popn()
|
||||
data := mem.Get(offset.Int64(), size.Int64())
|
||||
|
||||
stack.Push(ethutil.BigD(data))
|
||||
// 0x30 range
|
||||
case oADDRESS:
|
||||
case ADDRESS:
|
||||
stack.Push(ethutil.BigD(closure.Object().Address()))
|
||||
case oBALANCE:
|
||||
case BALANCE:
|
||||
stack.Push(closure.object.Amount)
|
||||
case oORIGIN:
|
||||
case ORIGIN:
|
||||
stack.Push(ethutil.BigD(vm.vars.Origin))
|
||||
case oCALLER:
|
||||
case CALLER:
|
||||
stack.Push(ethutil.BigD(closure.Callee().Address()))
|
||||
case oCALLVALUE:
|
||||
case CALLVALUE:
|
||||
stack.Push(vm.vars.Value)
|
||||
case oCALLDATALOAD:
|
||||
case CALLDATALOAD:
|
||||
require(1)
|
||||
offset := stack.Pop().Int64()
|
||||
val := closure.Args[offset : offset+32]
|
||||
|
||||
stack.Push(ethutil.BigD(val))
|
||||
case oCALLDATASIZE:
|
||||
case CALLDATASIZE:
|
||||
stack.Push(big.NewInt(int64(len(closure.Args))))
|
||||
case oGASPRICE:
|
||||
case GASPRICE:
|
||||
stack.Push(closure.Price)
|
||||
|
||||
// 0x40 range
|
||||
case oPREVHASH:
|
||||
case PREVHASH:
|
||||
stack.Push(ethutil.BigD(vm.vars.PrevHash))
|
||||
case oCOINBASE:
|
||||
case COINBASE:
|
||||
stack.Push(ethutil.BigD(vm.vars.Coinbase))
|
||||
case oTIMESTAMP:
|
||||
case TIMESTAMP:
|
||||
stack.Push(big.NewInt(vm.vars.Time))
|
||||
case oNUMBER:
|
||||
case NUMBER:
|
||||
stack.Push(big.NewInt(int64(vm.vars.BlockNumber)))
|
||||
case oDIFFICULTY:
|
||||
case DIFFICULTY:
|
||||
stack.Push(vm.vars.Diff)
|
||||
case oGASLIMIT:
|
||||
case GASLIMIT:
|
||||
// TODO
|
||||
stack.Push(big.NewInt(0))
|
||||
|
||||
// 0x50 range
|
||||
case oPUSH1, oPUSH2, oPUSH3, oPUSH4, oPUSH5, oPUSH6, oPUSH7, oPUSH8, oPUSH9, oPUSH10, oPUSH11, oPUSH12, oPUSH13, oPUSH14, oPUSH15, oPUSH16, oPUSH17, oPUSH18, oPUSH19, oPUSH20, oPUSH21, oPUSH22, oPUSH23, oPUSH24, oPUSH25, oPUSH26, oPUSH27, oPUSH28, oPUSH29, oPUSH30, oPUSH31, oPUSH32:
|
||||
a := big.NewInt(int64(op) - int64(oPUSH1) + 1)
|
||||
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
|
||||
a := big.NewInt(int64(op) - int64(PUSH1) + 1)
|
||||
pc.Add(pc, ethutil.Big1)
|
||||
data := closure.Gets(pc, a)
|
||||
val := ethutil.BigD(data.Bytes())
|
||||
// Push value to stack
|
||||
stack.Push(val)
|
||||
pc.Add(pc, a.Sub(a, big.NewInt(1)))
|
||||
step++
|
||||
|
||||
case oPOP:
|
||||
step += int(op) - int(PUSH1) + 1
|
||||
case POP:
|
||||
require(1)
|
||||
stack.Pop()
|
||||
case oDUP:
|
||||
case DUP:
|
||||
require(1)
|
||||
stack.Push(stack.Peek())
|
||||
case oSWAP:
|
||||
case SWAP:
|
||||
require(2)
|
||||
x, y := stack.Popn()
|
||||
stack.Push(y)
|
||||
stack.Push(x)
|
||||
case oMLOAD:
|
||||
case MLOAD:
|
||||
require(1)
|
||||
offset := stack.Pop()
|
||||
stack.Push(ethutil.BigD(mem.Get(offset.Int64(), 32)))
|
||||
case oMSTORE: // Store the value at stack top-1 in to memory at location stack top
|
||||
case MSTORE: // Store the value at stack top-1 in to memory at location stack top
|
||||
require(2)
|
||||
// Pop value of the stack
|
||||
val, mStart := stack.Popn()
|
||||
mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(val, 256))
|
||||
case oMSTORE8:
|
||||
case MSTORE8:
|
||||
require(2)
|
||||
val, mStart := stack.Popn()
|
||||
base.And(val, new(big.Int).SetInt64(0xff))
|
||||
mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(base, 256))
|
||||
case oSLOAD:
|
||||
case SLOAD:
|
||||
require(1)
|
||||
loc := stack.Pop()
|
||||
val := closure.GetMem(loc)
|
||||
//fmt.Println("get", val.BigInt(), "@", loc)
|
||||
stack.Push(val.BigInt())
|
||||
case oSSTORE:
|
||||
case SSTORE:
|
||||
require(2)
|
||||
val, loc := stack.Popn()
|
||||
//fmt.Println("storing", val, "@", loc)
|
||||
@ -401,13 +399,13 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
|
||||
// Add the change to manifest
|
||||
vm.state.manifest.AddStorageChange(closure.Object(), loc.Bytes(), val)
|
||||
case oJUMP:
|
||||
case JUMP:
|
||||
require(1)
|
||||
pc = stack.Pop()
|
||||
// Reduce pc by one because of the increment that's at the end of this for loop
|
||||
//pc.Sub(pc, ethutil.Big1)
|
||||
continue
|
||||
case oJUMPI:
|
||||
case JUMPI:
|
||||
require(2)
|
||||
cond, pos := stack.Popn()
|
||||
if cond.Cmp(ethutil.BigTrue) == 0 {
|
||||
@ -415,12 +413,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
//pc.Sub(pc, ethutil.Big1)
|
||||
continue
|
||||
}
|
||||
case oPC:
|
||||
case PC:
|
||||
stack.Push(pc)
|
||||
case oMSIZE:
|
||||
case MSIZE:
|
||||
stack.Push(big.NewInt(int64(mem.Len())))
|
||||
// 0x60 range
|
||||
case oCREATE:
|
||||
case CREATE:
|
||||
require(3)
|
||||
|
||||
value := stack.Pop()
|
||||
@ -439,9 +437,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
// Transfer all remaining gas to the new
|
||||
// contract so it may run the init script
|
||||
gas := new(big.Int).Set(closure.Gas)
|
||||
closure.Gas.Sub(closure.Gas, gas)
|
||||
closure.UseGas(gas)
|
||||
|
||||
// Create the closure
|
||||
closure := NewClosure(closure.callee,
|
||||
c := NewClosure(closure.callee,
|
||||
closure.Object(),
|
||||
contract.initScript,
|
||||
vm.state,
|
||||
@ -449,7 +448,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
closure.Price)
|
||||
// Call the closure and set the return value as
|
||||
// main script.
|
||||
closure.Script, err = closure.Call(vm, nil, hook)
|
||||
c.Script, gas, err = c.Call(vm, nil, hook)
|
||||
|
||||
if err != nil {
|
||||
stack.Push(ethutil.BigFalse)
|
||||
|
||||
@ -460,7 +460,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
|
||||
vm.state.UpdateStateObject(contract)
|
||||
}
|
||||
case oCALL:
|
||||
case CALL:
|
||||
require(7)
|
||||
// Closure addr
|
||||
addr := stack.Pop()
|
||||
@ -492,7 +492,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
// Copy
|
||||
gas = new(big.Int).Set(closure.Gas)
|
||||
}
|
||||
closure.Gas.Sub(closure.Gas, gas)
|
||||
closure.UseGas(gas)
|
||||
|
||||
// Add the value to the state object
|
||||
contract.AddAmount(value)
|
||||
@ -500,7 +500,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
// Create a new callable closure
|
||||
closure := NewClosure(closure.Object(), contract, contract.script, vm.state, gas, closure.Price)
|
||||
// Executer the closure and get the return value (if any)
|
||||
ret, err := closure.Call(vm, args, hook)
|
||||
ret, _, err := closure.Call(vm, args, hook)
|
||||
if err != nil {
|
||||
stack.Push(ethutil.BigFalse)
|
||||
// Reset the changes applied this object
|
||||
@ -516,13 +516,13 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes())
|
||||
stack.Push(ethutil.BigFalse)
|
||||
}
|
||||
case oRETURN:
|
||||
case RETURN:
|
||||
require(2)
|
||||
size, offset := stack.Popn()
|
||||
ret := mem.Get(offset.Int64(), size.Int64())
|
||||
|
||||
return closure.Return(ret), nil
|
||||
case oSUICIDE:
|
||||
case SUICIDE:
|
||||
require(1)
|
||||
|
||||
receiver := vm.state.GetAccount(stack.Pop().Bytes())
|
||||
@ -532,7 +532,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
closure.object.state.Purge()
|
||||
|
||||
fallthrough
|
||||
case oSTOP: // Stop the closure
|
||||
case STOP: // Stop the closure
|
||||
return closure.Return(nil), nil
|
||||
default:
|
||||
ethutil.Config.Log.Debugf("Invalid opcode %x\n", op)
|
||||
@ -543,7 +543,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
||||
pc.Add(pc, ethutil.Big1)
|
||||
|
||||
if hook != nil {
|
||||
if !hook(step-1, op, mem, stack, closure.Object()) {
|
||||
if !hook(prevStep, op, mem, stack, closure.Object()) {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"github.com/ethereum/eth-go/ethchain"
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"github.com/ethereum/eth-go/ethwire"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type Miner struct {
|
||||
@ -12,7 +13,7 @@ type Miner struct {
|
||||
ethereum ethchain.EthManager
|
||||
coinbase []byte
|
||||
reactChan chan ethutil.React
|
||||
txs []*ethchain.Transaction
|
||||
txs ethchain.Transactions
|
||||
uncles []*ethchain.Block
|
||||
block *ethchain.Block
|
||||
powChan chan []byte
|
||||
@ -132,6 +133,8 @@ func (self *Miner) mineNewBlock() {
|
||||
self.block.SetUncles(self.uncles)
|
||||
}
|
||||
|
||||
// Sort the transactions by nonce in case of odd network propagation
|
||||
sort.Sort(ethchain.TxByNonce{self.txs})
|
||||
// Accumulate all valid transaction and apply them to the new state
|
||||
receipts, txs := stateManager.ApplyTransactions(self.block.State(), self.block, self.txs)
|
||||
self.txs = txs
|
||||
|
@ -63,19 +63,27 @@ type PTx struct {
|
||||
Hash string `json:"hash"`
|
||||
Address string `json:"address"`
|
||||
Sender string `json:"sender"`
|
||||
RawData string `json:"rawData"`
|
||||
Data string `json:"data"`
|
||||
Contract bool `json:"isContract"`
|
||||
CreatesContract bool `json:"createsContract"`
|
||||
}
|
||||
|
||||
func NewPTx(tx *ethchain.Transaction) *PTx {
|
||||
hash := hex.EncodeToString(tx.Hash())
|
||||
receiver := hex.EncodeToString(tx.Recipient)
|
||||
|
||||
if receiver == "" {
|
||||
receiver = hex.EncodeToString(tx.CreationAddress())
|
||||
}
|
||||
sender := hex.EncodeToString(tx.Sender())
|
||||
createsContract := tx.CreatesContract()
|
||||
|
||||
data := strings.Join(ethchain.Disassemble(tx.Data), "\n")
|
||||
|
||||
isContract := len(tx.Data) > 0
|
||||
|
||||
return &PTx{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: receiver, Contract: isContract, Gas: tx.Gas.String(), GasPrice: tx.GasPrice.String(), Data: data, Sender: sender}
|
||||
return &PTx{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: receiver, Contract: isContract, Gas: tx.Gas.String(), GasPrice: tx.GasPrice.String(), Data: data, Sender: sender, CreatesContract: createsContract, RawData: hex.EncodeToString(tx.Data)}
|
||||
}
|
||||
|
||||
func (self *PTx) ToString() string {
|
||||
|
@ -88,3 +88,13 @@ func IsHex(str string) bool {
|
||||
l := len(str)
|
||||
return l >= 4 && l%2 == 0 && str[0:2] == "0x"
|
||||
}
|
||||
|
||||
func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) {
|
||||
if len(str) > 1 && str[0:2] == "0x" {
|
||||
ret = FromHex(str[2:])
|
||||
} else {
|
||||
ret = cb(str)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func ReadConfig(base string, logTypes LoggerType, id string) *config {
|
||||
}
|
||||
}
|
||||
|
||||
Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC10"}
|
||||
Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC11"}
|
||||
Config.Identifier = id
|
||||
Config.Log = NewLogger(logTypes, LogLevelDebug)
|
||||
Config.SetClientString("/Ethereum(G)")
|
||||
|
Loading…
Reference in New Issue
Block a user