forked from cerc-io/plugeth
Added proper gas handling
This commit is contained in:
parent
c5729d7ecc
commit
a96c8c8af9
@ -27,14 +27,15 @@ type Closure struct {
|
|||||||
State *State
|
State *State
|
||||||
|
|
||||||
Gas *big.Int
|
Gas *big.Int
|
||||||
|
Price *big.Int
|
||||||
Value *big.Int
|
Value *big.Int
|
||||||
|
|
||||||
Args []byte
|
Args []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new closure for the given data items
|
// Create a new closure for the given data items
|
||||||
func NewClosure(callee Callee, object Reference, script []byte, state *State, gas, val *big.Int) *Closure {
|
func NewClosure(callee Callee, object Reference, script []byte, state *State, gas, price, val *big.Int) *Closure {
|
||||||
return &Closure{callee, object, script, state, gas, val, nil}
|
return &Closure{callee, object, script, state, gas, price, val, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retuns the x element in data slice
|
// Retuns the x element in data slice
|
||||||
|
@ -310,7 +310,7 @@ func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Trans
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
caller := sm.procState.GetAccount(tx.Sender())
|
caller := sm.procState.GetAccount(tx.Sender())
|
||||||
closure := NewClosure(caller, object, script, sm.procState, tx.Gas, tx.Value)
|
closure := NewClosure(caller, object, script, sm.procState, tx.Gas, tx.GasPrice, tx.Value)
|
||||||
vm := NewVm(sm.procState, RuntimeVars{
|
vm := NewVm(sm.procState, RuntimeVars{
|
||||||
Origin: caller.Address(),
|
Origin: caller.Address(),
|
||||||
BlockNumber: block.BlockInfo().Number,
|
BlockNumber: block.BlockInfo().Number,
|
||||||
@ -318,6 +318,7 @@ func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Trans
|
|||||||
Coinbase: block.Coinbase,
|
Coinbase: block.Coinbase,
|
||||||
Time: block.Time,
|
Time: block.Time,
|
||||||
Diff: block.Difficulty,
|
Diff: block.Difficulty,
|
||||||
|
//Price: tx.GasPrice,
|
||||||
})
|
})
|
||||||
closure.Call(vm, nil, nil)
|
closure.Call(vm, nil, nil)
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ type Transaction struct {
|
|||||||
Recipient []byte
|
Recipient []byte
|
||||||
Value *big.Int
|
Value *big.Int
|
||||||
Gas *big.Int
|
Gas *big.Int
|
||||||
Gasprice *big.Int
|
GasPrice *big.Int
|
||||||
Data []byte
|
Data []byte
|
||||||
Init []byte
|
Init []byte
|
||||||
v byte
|
v byte
|
||||||
@ -24,11 +24,11 @@ type Transaction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewContractCreationTx(value, gasprice *big.Int, script []byte, init []byte) *Transaction {
|
func NewContractCreationTx(value, gasprice *big.Int, script []byte, init []byte) *Transaction {
|
||||||
return &Transaction{Value: value, Gasprice: gasprice, Data: script, Init: init, contractCreation: true}
|
return &Transaction{Value: value, 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, gasprice, gas *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,7 +46,7 @@ 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, string(tx.Data)}
|
||||||
if tx.contractCreation {
|
if tx.contractCreation {
|
||||||
data = append(data, string(tx.Init))
|
data = append(data, string(tx.Init))
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ func (tx *Transaction) Sign(privk []byte) error {
|
|||||||
// [ NONCE, VALUE, GASPRICE, GAS, TO, DATA, V, R, S ]
|
// [ NONCE, VALUE, GASPRICE, GAS, TO, DATA, V, R, S ]
|
||||||
// [ NONCE, VALUE, GASPRICE, GAS, 0, CODE, INIT, V, R, S ]
|
// [ NONCE, VALUE, GASPRICE, GAS, 0, CODE, INIT, V, R, S ]
|
||||||
func (tx *Transaction) RlpData() interface{} {
|
func (tx *Transaction) RlpData() interface{} {
|
||||||
data := []interface{}{tx.Nonce, tx.Value, tx.Gasprice, tx.Gas, tx.Recipient, 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, tx.Init)
|
data = append(data, tx.Init)
|
||||||
@ -132,7 +132,7 @@ func (tx *Transaction) RlpDecode(data []byte) {
|
|||||||
func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
|
func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
|
||||||
tx.Nonce = decoder.Get(0).Uint()
|
tx.Nonce = decoder.Get(0).Uint()
|
||||||
tx.Value = decoder.Get(1).BigInt()
|
tx.Value = decoder.Get(1).BigInt()
|
||||||
tx.Gasprice = decoder.Get(2).BigInt()
|
tx.GasPrice = decoder.Get(2).BigInt()
|
||||||
tx.Gas = decoder.Get(3).BigInt()
|
tx.Gas = decoder.Get(3).BigInt()
|
||||||
tx.Recipient = decoder.Get(4).Bytes()
|
tx.Recipient = decoder.Get(4).Bytes()
|
||||||
tx.Data = decoder.Get(5).Bytes()
|
tx.Data = decoder.Get(5).Bytes()
|
||||||
|
@ -71,7 +71,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
|||||||
// New stack (should this be shared?)
|
// New stack (should this be shared?)
|
||||||
stack := NewStack()
|
stack := NewStack()
|
||||||
require := func(m int) {
|
require := func(m int) {
|
||||||
if stack.Len()-1 > m {
|
if stack.Len() < m {
|
||||||
isRequireError = true
|
isRequireError = true
|
||||||
panic(fmt.Sprintf("stack = %d, req = %d", stack.Len(), m))
|
panic(fmt.Sprintf("stack = %d, req = %d", stack.Len(), m))
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
|||||||
// TODO Get each instruction cost properly
|
// TODO Get each instruction cost properly
|
||||||
gas := new(big.Int)
|
gas := new(big.Int)
|
||||||
useGas := func(amount *big.Int) {
|
useGas := func(amount *big.Int) {
|
||||||
gas.Add(gas, amount)
|
gas.Add(gas, new(big.Int).Mul(amount, closure.Price))
|
||||||
}
|
}
|
||||||
|
|
||||||
switch op {
|
switch op {
|
||||||
@ -142,6 +142,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
|||||||
|
|
||||||
return closure.Return(nil), fmt.Errorf("insufficient gas %v %v", closure.Gas, gas)
|
return closure.Return(nil), fmt.Errorf("insufficient gas %v %v", closure.Gas, gas)
|
||||||
}
|
}
|
||||||
|
closure.Gas.Sub(closure.Gas, gas)
|
||||||
|
|
||||||
switch op {
|
switch op {
|
||||||
case oLOG:
|
case oLOG:
|
||||||
@ -411,7 +412,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
|||||||
// 0x60 range
|
// 0x60 range
|
||||||
case oCREATE:
|
case oCREATE:
|
||||||
case oCALL:
|
case oCALL:
|
||||||
require(8)
|
require(7)
|
||||||
// Closure addr
|
// Closure addr
|
||||||
addr := stack.Pop()
|
addr := stack.Pop()
|
||||||
// Pop gas and value of the stack.
|
// Pop gas and value of the stack.
|
||||||
@ -425,7 +426,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
|
|||||||
// Fetch the contract which will serve as the closure body
|
// Fetch the contract which will serve as the closure body
|
||||||
contract := vm.state.GetContract(addr.Bytes())
|
contract := vm.state.GetContract(addr.Bytes())
|
||||||
// Create a new callable closure
|
// Create a new callable closure
|
||||||
closure := NewClosure(closure, contract, contract.script, vm.state, gas, value)
|
closure := NewClosure(closure, contract, contract.script, vm.state, gas, closure.Price, value)
|
||||||
// Executer the closure and get the return value (if any)
|
// 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 {
|
if err != nil {
|
||||||
|
@ -91,10 +91,10 @@ func TestRun4(t *testing.T) {
|
|||||||
exit()
|
exit()
|
||||||
`), false)
|
`), false)
|
||||||
script := ethutil.Assemble(asm...)
|
script := ethutil.Assemble(asm...)
|
||||||
tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), script)
|
tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), script, nil)
|
||||||
addr := tx.Hash()[12:]
|
addr := tx.Hash()[12:]
|
||||||
contract := MakeContract(tx, state)
|
contract := MakeContract(tx, state)
|
||||||
state.UpdateContract(contract)
|
state.UpdateStateObject(contract)
|
||||||
fmt.Printf("%x\n", addr)
|
fmt.Printf("%x\n", addr)
|
||||||
|
|
||||||
asm, err = mutan.Compile(strings.NewReader(`
|
asm, err = mutan.Compile(strings.NewReader(`
|
||||||
@ -122,12 +122,13 @@ func TestRun4(t *testing.T) {
|
|||||||
fmt.Println(asm)
|
fmt.Println(asm)
|
||||||
|
|
||||||
callerScript := ethutil.Assemble(asm...)
|
callerScript := ethutil.Assemble(asm...)
|
||||||
callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), callerScript)
|
callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), callerScript, nil)
|
||||||
|
|
||||||
// Contract addr as test address
|
// Contract addr as test address
|
||||||
account := NewAccount(ContractAddr, big.NewInt(10000000))
|
account := NewAccount(ContractAddr, big.NewInt(10000000))
|
||||||
|
fmt.Println(account)
|
||||||
c := MakeContract(callerTx, state)
|
c := MakeContract(callerTx, state)
|
||||||
callerClosure := NewClosure(account, c, c.script, state, big.NewInt(1000000000), new(big.Int))
|
callerClosure := NewClosure(account, c, c.script, state, big.NewInt(1000000000), big.NewInt(10), big.NewInt(0))
|
||||||
|
|
||||||
vm := NewVm(state, RuntimeVars{
|
vm := NewVm(state, RuntimeVars{
|
||||||
Origin: account.Address(),
|
Origin: account.Address(),
|
||||||
@ -136,10 +137,12 @@ func TestRun4(t *testing.T) {
|
|||||||
Coinbase: ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
|
Coinbase: ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
|
||||||
Time: 1,
|
Time: 1,
|
||||||
Diff: big.NewInt(256),
|
Diff: big.NewInt(256),
|
||||||
// XXX Tx data? Could be just an argument to the closure instead
|
|
||||||
TxData: nil,
|
|
||||||
})
|
})
|
||||||
callerClosure.Call(vm, nil, nil)
|
_, e := callerClosure.Call(vm, nil, nil)
|
||||||
|
if e != nil {
|
||||||
|
fmt.Println("error", e)
|
||||||
|
}
|
||||||
|
fmt.Println(account)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRun5(t *testing.T) {
|
func TestRun5(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user