Commit 239e17de authored by obscuren's avatar obscuren

Merge branch 'rpcfrontier' into develop

parents 61bf29be c01d4c2f
...@@ -26,6 +26,7 @@ import ( ...@@ -26,6 +26,7 @@ import (
"os" "os"
"runtime" "runtime"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
...@@ -112,6 +113,7 @@ runtime will execute the file and exit. ...@@ -112,6 +113,7 @@ runtime will execute the file and exit.
}, },
} }
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
utils.UnlockedAccountFlag,
utils.BootnodesFlag, utils.BootnodesFlag,
utils.DataDirFlag, utils.DataDirFlag,
utils.ListenPortFlag, utils.ListenPortFlag,
...@@ -191,6 +193,21 @@ Please run 'ethereum account new' to create a new account.`) ...@@ -191,6 +193,21 @@ Please run 'ethereum account new' to create a new account.`)
func startEth(ctx *cli.Context, eth *eth.Ethereum) { func startEth(ctx *cli.Context, eth *eth.Ethereum) {
utils.StartEthereum(eth) utils.StartEthereum(eth)
// Load startup keys. XXX we are going to need a different format
account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
if len(account) > 0 {
split := strings.Split(account, ":")
if len(split) != 2 {
utils.Fatalf("Illegal 'unlock' format (address:password)")
}
am := eth.AccountManager()
// Attempt to unlock the account
err := am.Unlock(ethutil.Hex2Bytes(split[0]), split[1])
if err != nil {
utils.Fatalf("Unlock account failed '%v'", err)
}
}
// Start auxiliary services if enabled. // Start auxiliary services if enabled.
if ctx.GlobalBool(utils.RPCEnabledFlag.Name) { if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
utils.StartRPC(eth, ctx) utils.StartRPC(eth, ctx)
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
var web3 = require('web3'); var web3 = require('web3');
var eth = web3.eth; var eth = web3.eth;
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545')); web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
var desc = [{ var desc = [{
"name": "balance(address)", "name": "balance(address)",
"type": "function", "type": "function",
...@@ -72,12 +72,13 @@ ...@@ -72,12 +72,13 @@
// deploy if not exist // deploy if not exist
if (address == null) { if (address == null) {
var code = "0x60056013565b61014f8061003a6000396000f35b620f42406000600033600160a060020a0316815260200190815260200160002081905550560060e060020a600035048063d0679d3414610020578063e3d670d71461003457005b61002e600435602435610049565b60006000f35b61003f600435610129565b8060005260206000f35b806000600033600160a060020a03168152602001908152602001600020541061007157610076565b610125565b806000600033600160a060020a03168152602001908152602001600020908154039081905550806000600084600160a060020a031681526020019081526020016000209081540190819055508033600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a38082600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a35b5050565b60006000600083600160a060020a0316815260200190815260200160002054905091905056"; var code = "0x60056013565b61014f8061003a6000396000f35b620f42406000600033600160a060020a0316815260200190815260200160002081905550560060e060020a600035048063d0679d3414610020578063e3d670d71461003457005b61002e600435602435610049565b60006000f35b61003f600435610129565b8060005260206000f35b806000600033600160a060020a03168152602001908152602001600020541061007157610076565b610125565b806000600033600160a060020a03168152602001908152602001600020908154039081905550806000600084600160a060020a031681526020019081526020016000209081540190819055508033600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a38082600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a35b5050565b60006000600083600160a060020a0316815260200190815260200160002054905091905056";
address = web3.eth.transact({data: code}); address = web3.eth.transact({from: eth.coinbase, data: code});
localStorage.setItem("address", address); localStorage.setItem("address", address);
} }
document.querySelector("#contract_addr").innerHTML = address; document.querySelector("#contract_addr").innerHTML = address;
var contract = web3.eth.contract(address, desc); var Contract = web3.eth.contract(desc);
contract = new Contract(address);
contract.Changed({from: eth.coinbase}).changed(function() { contract.Changed({from: eth.coinbase}).changed(function() {
refresh(); refresh();
}); });
...@@ -88,7 +89,7 @@ ...@@ -88,7 +89,7 @@
var table = document.querySelector("#table_body"); var table = document.querySelector("#table_body");
table.innerHTML = ""; // clear table.innerHTML = ""; // clear
var storage = eth.storageAt(address); var storage = eth.getStorage(address);
table.innerHTML = ""; table.innerHTML = "";
for( var item in storage ) { for( var item in storage ) {
table.innerHTML += "<tr><td>"+item+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>"; table.innerHTML += "<tr><td>"+item+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>";
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -77,6 +77,10 @@ var ( ...@@ -77,6 +77,10 @@ var (
Usage: "Virtual Machine type: 0 is standard VM, 1 is debug VM", Usage: "Virtual Machine type: 0 is standard VM, 1 is debug VM",
} }
*/ */
UnlockedAccountFlag = cli.StringFlag{
Name: "unlock",
Usage: "Unlock a given account untill this programs exits (address:password)",
}
VMDebugFlag = cli.BoolFlag{ VMDebugFlag = cli.BoolFlag{
Name: "vmdebug", Name: "vmdebug",
Usage: "Virtual Machine debug output", Usage: "Virtual Machine debug output",
...@@ -221,7 +225,8 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database, ethutil.D ...@@ -221,7 +225,8 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database, ethutil.D
func GetAccountManager(ctx *cli.Context) *accounts.Manager { func GetAccountManager(ctx *cli.Context) *accounts.Manager {
dataDir := ctx.GlobalString(DataDirFlag.Name) dataDir := ctx.GlobalString(DataDirFlag.Name)
ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys")) ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
return accounts.NewManager(ks) km := accounts.NewManager(ks)
return km
} }
func StartRPC(eth *eth.Ethereum, ctx *cli.Context) { func StartRPC(eth *eth.Ethereum, ctx *cli.Context) {
......
...@@ -80,7 +80,7 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated ...@@ -80,7 +80,7 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
cb := statedb.GetStateObject(coinbase.Address()) cb := statedb.GetStateObject(coinbase.Address())
st := NewStateTransition(NewEnv(statedb, self.bc, tx, block), tx, cb) st := NewStateTransition(NewEnv(statedb, self.bc, tx, block), tx, cb)
_, err := st.TransitionState() _, err := st.TransitionState()
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err)) { if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
return nil, nil, err return nil, nil, err
} }
...@@ -120,17 +120,12 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state ...@@ -120,17 +120,12 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
for _, tx := range txs { for _, tx := range txs {
receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, block, tx, totalUsedGas, transientProcess) receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, block, tx, totalUsedGas, transientProcess)
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
return nil, nil, nil, nil, err
}
if err != nil { if err != nil {
switch { statelogger.Infoln("TX err:", err)
case IsNonceErr(err):
return nil, nil, nil, nil, err
case state.IsGasLimitErr(err):
return nil, nil, nil, nil, err
default:
statelogger.Infoln(err)
erroneous = append(erroneous, tx)
err = nil
}
} }
receipts = append(receipts, receipt) receipts = append(receipts, receipt)
handled = append(handled, tx) handled = append(handled, tx)
......
...@@ -440,12 +440,14 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { ...@@ -440,12 +440,14 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
self.setTotalDifficulty(td) self.setTotalDifficulty(td)
self.insert(block) self.insert(block)
/* XXX crashes
jsonlogger.LogJson(&logger.EthChainNewHead{ jsonlogger.LogJson(&logger.EthChainNewHead{
BlockHash: ethutil.Bytes2Hex(block.Hash()), BlockHash: ethutil.Bytes2Hex(block.Hash()),
BlockNumber: block.Number(), BlockNumber: block.Number(),
ChainHeadHash: ethutil.Bytes2Hex(cblock.Hash()), ChainHeadHash: ethutil.Bytes2Hex(cblock.Hash()),
BlockPrevHash: ethutil.Bytes2Hex(block.ParentHash()), BlockPrevHash: ethutil.Bytes2Hex(block.ParentHash()),
}) })
*/
self.setTransState(state.New(block.Root(), self.stateDb)) self.setTransState(state.New(block.Root(), self.stateDb))
queue[i] = ChainEvent{block} queue[i] = ChainEvent{block}
......
...@@ -184,6 +184,7 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) { ...@@ -184,6 +184,7 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
} }
} }
if err = self.UseGas(big.NewInt(dgas)); err != nil { if err = self.UseGas(big.NewInt(dgas)); err != nil {
println("2")
return nil, InvalidTxError(err) return nil, InvalidTxError(err)
} }
...@@ -198,48 +199,18 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) { ...@@ -198,48 +199,18 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
dataGas.Mul(dataGas, vm.GasCreateByte) dataGas.Mul(dataGas, vm.GasCreateByte)
if err := self.UseGas(dataGas); err == nil { if err := self.UseGas(dataGas); err == nil {
ref.SetCode(ret) ref.SetCode(ret)
} else {
statelogger.Infoln("Insufficient gas for creating code. Require", dataGas, "and have", self.gas)
} }
} }
/*
if vmenv, ok := vmenv.(*VMEnv); ok && tryJit {
statelogger.Infof("CREATE: re-running using JIT (PH=%x)\n", stateCopy.Root()[:4])
// re-run using the JIT (validation for the JIT)
goodState := vmenv.State().Copy()
vmenv.state = stateCopy
vmenv.SetVmType(vm.JitVmTy)
vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value)
statelogger.Infof("DONE PH=%x STD_H=%x JIT_H=%x\n", stateCopy.Root()[:4], goodState.Root()[:4], vmenv.State().Root()[:4])
self.state.Set(goodState)
}
*/
} else { } else {
ret, err = vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) ret, err = vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value)
/*
if vmenv, ok := vmenv.(*VMEnv); ok && tryJit {
statelogger.Infof("CALL: re-running using JIT (PH=%x)\n", stateCopy.Root()[:4])
// re-run using the JIT (validation for the JIT)
goodState := vmenv.State().Copy()
vmenv.state = stateCopy
vmenv.SetVmType(vm.JitVmTy)
vmenv.Call(self.From(), self.To().Address(), self.msg.Data(), self.gas, self.gasPrice, self.value)
statelogger.Infof("DONE PH=%x STD_H=%x JIT_H=%x\n", stateCopy.Root()[:4], goodState.Root()[:4], vmenv.State().Root()[:4])
self.state.Set(goodState)
}
*/
} }
if err != nil && IsValueTransferErr(err) { if err != nil && IsValueTransferErr(err) {
return nil, InvalidTxError(err) return nil, InvalidTxError(err)
} }
/*
if err != nil {
self.UseGas(self.gas)
}
*/
return return
} }
......
...@@ -58,7 +58,7 @@ type JSEthereum struct { ...@@ -58,7 +58,7 @@ type JSEthereum struct {
func (self *JSEthereum) Block(v interface{}) otto.Value { func (self *JSEthereum) Block(v interface{}) otto.Value {
if number, ok := v.(int64); ok { if number, ok := v.(int64); ok {
return self.toVal(&JSBlock{self.XEth.BlockByNumber(int32(number)), self}) return self.toVal(&JSBlock{self.XEth.BlockByNumber(number), self})
} else if hash, ok := v.(string); ok { } else if hash, ok := v.(string); ok {
return self.toVal(&JSBlock{self.XEth.BlockByHash(hash), self}) return self.toVal(&JSBlock{self.XEth.BlockByHash(hash), self})
} }
......
...@@ -209,6 +209,8 @@ gasLimit: ...@@ -209,6 +209,8 @@ gasLimit:
err := self.commitTransaction(tx) err := self.commitTransaction(tx)
switch { switch {
case core.IsNonceErr(err): case core.IsNonceErr(err):
fallthrough
case core.IsInvalidTxErr(err):
// Remove invalid transactions // Remove invalid transactions
remove = append(remove, tx) remove = append(remove, tx)
case state.IsGasLimitErr(err): case state.IsGasLimitErr(err):
...@@ -222,7 +224,7 @@ gasLimit: ...@@ -222,7 +224,7 @@ gasLimit:
} }
self.eth.TxPool().RemoveSet(remove) self.eth.TxPool().RemoveSet(remove)
self.current.coinbase.AddBalance(core.BlockReward) self.current.state.AddBalance(self.coinbase, core.BlockReward)
self.current.state.Update(ethutil.Big0) self.current.state.Update(ethutil.Big0)
self.push() self.push()
...@@ -258,9 +260,11 @@ func (self *worker) commitUncle(uncle *types.Header) error { ...@@ -258,9 +260,11 @@ func (self *worker) commitUncle(uncle *types.Header) error {
} }
func (self *worker) commitTransaction(tx *types.Transaction) error { func (self *worker) commitTransaction(tx *types.Transaction) error {
snap := self.current.state.Copy()
//fmt.Printf("proc %x %v\n", tx.Hash()[:3], tx.Nonce()) //fmt.Printf("proc %x %v\n", tx.Hash()[:3], tx.Nonce())
receipt, _, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true) receipt, _, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true)
if err != nil && (core.IsNonceErr(err) || state.IsGasLimitErr(err)) { if err != nil && (core.IsNonceErr(err) || state.IsGasLimitErr(err) || core.IsInvalidTxErr(err)) {
self.current.state.Set(snap)
return err return err
} }
......
This diff is collapsed.
package rpc package rpc
import ( import (
"encoding/json"
"sync" "sync"
"testing" "testing"
"time" "time"
) )
func TestWeb3Sha3(t *testing.T) {
jsonstr := `{"jsonrpc":"2.0","method":"web3_sha3","params":["0x68656c6c6f20776f726c64"],"id":64}`
expected := "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"
api := &EthereumApi{}
var req RpcRequest
json.Unmarshal([]byte(jsonstr), &req)
var response interface{}
_ = api.GetRequestReply(&req, &response)
if response.(string) != expected {
t.Errorf("Expected %s got %s", expected, response)
}
}
func TestFilterClose(t *testing.T) { func TestFilterClose(t *testing.T) {
t.Skip() t.Skip()
api := &EthereumApi{ api := &EthereumApi{
......
This diff is collapsed.
This diff is collapsed.
...@@ -17,12 +17,9 @@ ...@@ -17,12 +17,9 @@
package rpc package rpc
import ( import (
"bytes"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/xeth"
) )
var ( var (
...@@ -33,10 +30,10 @@ var ( ...@@ -33,10 +30,10 @@ var (
) )
type RpcRequest struct { type RpcRequest struct {
ID interface{} `json:"id"` ID interface{} `json:"id"`
JsonRpc string `json:"jsonrpc"` JsonRpc string `json:"jsonrpc"`
Method string `json:"method"` Method string `json:"method"`
Params []json.RawMessage `json:"params"` Params json.RawMessage `json:"params"`
} }
type RpcSuccessResponse struct { type RpcSuccessResponse struct {
...@@ -61,359 +58,30 @@ func NewErrorWithMessage(err error, msg string) error { ...@@ -61,359 +58,30 @@ func NewErrorWithMessage(err error, msg string) error {
return fmt.Errorf("%s: %s", err.Error(), msg) return fmt.Errorf("%s: %s", err.Error(), msg)
} }
func (req *RpcRequest) ToSha3Args() (*Sha3Args, error) { // func (req *RpcRequest) ToRegisterArgs() (string, error) {
if len(req.Params) < 1 { // if len(req.Params) < 1 {
return nil, errArguments // return "", errArguments
} // }
args := new(Sha3Args)
r := bytes.NewReader(req.Params[0])
if err := json.NewDecoder(r).Decode(args); err != nil {
return nil, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToGetBlockArgs() (*GetBlockArgs, error) {
if len(req.Params) < 1 {
return nil, errArguments
}
args := new(GetBlockArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToNewTxArgs() (*NewTxArgs, error) {
if len(req.Params) < 1 {
return nil, errArguments
}
args := new(NewTxArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
return args, nil
}
func (req *RpcRequest) ToPushTxArgs() (*PushTxArgs, error) {
if len(req.Params) < 1 {
return nil, errArguments
}
args := new(PushTxArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToGetStateArgs() (*GetStateArgs, error) {
if len(req.Params) < 1 {
return nil, errArguments
}
args := new(GetStateArgs)
// TODO need to pass both arguments
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToStorageAtArgs() (*GetStorageArgs, error) {
if len(req.Params) < 1 {
return nil, errArguments
}
args := new(GetStorageArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToGetTxCountArgs() (*GetTxCountArgs, error) {
if len(req.Params) < 1 {
return nil, errArguments
}
args := new(GetTxCountArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToGetBalanceArgs() (*GetBalanceArgs, error) {
if len(req.Params) < 1 {
return nil, errArguments
}
args := new(GetBalanceArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToGetCodeAtArgs() (*GetCodeAtArgs, error) {
if len(req.Params) < 1 {
return nil, errArguments
}
args := new(GetCodeAtArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToBoolArgs() (bool, error) {
if len(req.Params) < 1 {
return false, errArguments
}
var args bool
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
return false, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToIntArgs() (int, error) {
if len(req.Params) < 1 {
return 0, errArguments
}
var args int
if err := json.Unmarshal(req.Params[0], &args); err != nil {
return 0, errArguments
}
return args, nil
}
func (req *RpcRequest) ToCompileArgs() (string, error) {
if len(req.Params) < 1 {
return "", errArguments
}
var args string
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
return "", errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToFilterArgs() (*FilterOptions, error) {
if len(req.Params) < 1 {
return nil, errArguments
}
args := new(FilterOptions)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
return nil, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToFilterStringArgs() (string, error) {
if len(req.Params) < 1 {
return "", errArguments
}
var args string
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
return "", errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToUninstallFilterArgs() (int, error) {
if len(req.Params) < 1 {
return 0, errArguments
}
var args int
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
return 0, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToFilterChangedArgs() (int, error) {
if len(req.Params) < 1 {
return 0, errArguments
}
var id int
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(&id)
if err != nil {
return 0, errDecodeArgs
}
return id, nil
}
func (req *RpcRequest) ToDbPutArgs() (*DbArgs, error) {
if len(req.Params) < 3 {
return nil, errArguments
}
var args DbArgs
err := json.Unmarshal(req.Params[0], &args.Database)
if err != nil {
return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
err = json.Unmarshal(req.Params[1], &args.Key)
if err != nil {
return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
err = json.Unmarshal(req.Params[2], &args.Value)
if err != nil {
return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
return &args, nil
}
func (req *RpcRequest) ToDbGetArgs() (*DbArgs, error) {
if len(req.Params) < 2 {
return nil, errArguments
}
var args DbArgs // var args string
err := json.Unmarshal(req.Params[0], &args.Database) // err := json.Unmarshal(req.Params, &args)
if err != nil { // if err != nil {
return nil, NewErrorWithMessage(errDecodeArgs, err.Error()) // return "", err
} // }
err = json.Unmarshal(req.Params[1], &args.Key) // return args, nil
if err != nil { // }
return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
return &args, nil // func (req *RpcRequest) ToWatchTxArgs() (string, error) {
} // if len(req.Params) < 1 {
// return "", errArguments
func (req *RpcRequest) ToWhisperFilterArgs() (*xeth.Options, error) { // }
if len(req.Params) < 1 {
return nil, errArguments
}
var args xeth.Options
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
return &args, nil
}
func (req *RpcRequest) ToIdArgs() (int, error) {
if len(req.Params) < 1 {
return 0, errArguments
}
var id int // var args string
err := json.Unmarshal(req.Params[0], &id) // err := json.Unmarshal(req.Params, &args)
if err != nil { // if err != nil {
return 0, errDecodeArgs // return "", err
} // }
return id, nil
}
func (req *RpcRequest) ToWhisperPostArgs() (*WhisperMessageArgs, error) {
if len(req.Params) < 1 {
return nil, errArguments
}
var args WhisperMessageArgs
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
return nil, err
}
return &args, nil
}
func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) { // return args, nil
if len(req.Params) < 1 { // }
return "", errArguments
}
var args string
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
return "", err
}
return args, nil
}
func (req *RpcRequest) ToRegisterArgs() (string, error) {
if len(req.Params) < 1 {
return "", errArguments
}
var args string
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
return "", err
}
return args, nil
}
func (req *RpcRequest) ToWatchTxArgs() (string, error) {
if len(req.Params) < 1 {
return "", errArguments
}
var args string
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
return "", err
}
return args, nil
}
package rpc
import (
"encoding/json"
// "fmt"
"math/big"
"github.com/ethereum/go-ethereum/core/types"
)
type BlockRes struct {
fullTx bool
BlockNumber int64 `json:"number"`
BlockHash []byte `json:"hash"`
ParentHash []byte `json:"parentHash"`
Nonce []byte `json:"nonce"`
Sha3Uncles []byte `json:"sha3Uncles"`
LogsBloom []byte `json:"logsBloom"`
TransactionRoot []byte `json:"transactionRoot"`
StateRoot []byte `json:"stateRoot"`
Miner []byte `json:"miner"`
Difficulty int64 `json:"difficulty"`
TotalDifficulty int64 `json:"totalDifficulty"`
Size int64 `json:"size"`
ExtraData []byte `json:"extraData"`
GasLimit int64 `json:"gasLimit"`
MinGasPrice int64 `json:"minGasPrice"`
GasUsed int64 `json:"gasUsed"`
UnixTimestamp int64 `json:"timestamp"`
Transactions []*TransactionRes `json:"transactions"`
Uncles [][]byte `json:"uncles"`
}
func (b *BlockRes) MarshalJSON() ([]byte, error) {
var ext struct {
BlockNumber string `json:"number"`
BlockHash string `json:"hash"`
ParentHash string `json:"parentHash"`
Nonce string `json:"nonce"`
Sha3Uncles string `json:"sha3Uncles"`
LogsBloom string `json:"logsBloom"`
TransactionRoot string `json:"transactionRoot"`
StateRoot string `json:"stateRoot"`
Miner string `json:"miner"`
Difficulty string `json:"difficulty"`
TotalDifficulty string `json:"totalDifficulty"`
Size string `json:"size"`
ExtraData string `json:"extraData"`
GasLimit string `json:"gasLimit"`
MinGasPrice string `json:"minGasPrice"`
GasUsed string `json:"gasUsed"`
UnixTimestamp string `json:"timestamp"`
Transactions []interface{} `json:"transactions"`
Uncles []string `json:"uncles"`
}
// convert strict types to hexified strings
ext.BlockNumber = toHex(big.NewInt(b.BlockNumber).Bytes())
ext.BlockHash = toHex(b.BlockHash)
ext.ParentHash = toHex(b.ParentHash)
ext.Nonce = toHex(b.Nonce)
ext.Sha3Uncles = toHex(b.Sha3Uncles)
ext.LogsBloom = toHex(b.LogsBloom)
ext.TransactionRoot = toHex(b.TransactionRoot)
ext.StateRoot = toHex(b.StateRoot)
ext.Miner = toHex(b.Miner)
ext.Difficulty = toHex(big.NewInt(b.Difficulty).Bytes())
ext.TotalDifficulty = toHex(big.NewInt(b.TotalDifficulty).Bytes())
ext.Size = toHex(big.NewInt(b.Size).Bytes())
// ext.ExtraData = toHex(b.ExtraData)
ext.GasLimit = toHex(big.NewInt(b.GasLimit).Bytes())
// ext.MinGasPrice = toHex(big.NewInt(b.MinGasPrice).Bytes())
ext.GasUsed = toHex(big.NewInt(b.GasUsed).Bytes())
ext.UnixTimestamp = toHex(big.NewInt(b.UnixTimestamp).Bytes())
ext.Transactions = make([]interface{}, len(b.Transactions))
if b.fullTx {
for i, tx := range b.Transactions {
ext.Transactions[i] = tx
}
} else {
for i, tx := range b.Transactions {
ext.Transactions[i] = toHex(tx.Hash)
}
}
ext.Uncles = make([]string, len(b.Uncles))
for i, v := range b.Uncles {
ext.Uncles[i] = toHex(v)
}
return json.Marshal(ext)
}
func NewBlockRes(block *types.Block) *BlockRes {
if block == nil {
return &BlockRes{}
}
res := new(BlockRes)
res.BlockNumber = block.Number().Int64()
res.BlockHash = block.Hash()
res.ParentHash = block.ParentHash()
res.Nonce = block.Header().Nonce
res.Sha3Uncles = block.Header().UncleHash
res.LogsBloom = block.Bloom()
res.TransactionRoot = block.Header().TxHash
res.StateRoot = block.Root()
res.Miner = block.Header().Coinbase
res.Difficulty = block.Difficulty().Int64()
if block.Td != nil {
res.TotalDifficulty = block.Td.Int64()
}
res.Size = int64(block.Size())
// res.ExtraData =
res.GasLimit = block.GasLimit().Int64()
// res.MinGasPrice =
res.GasUsed = block.GasUsed().Int64()
res.UnixTimestamp = block.Time()
res.Transactions = make([]*TransactionRes, len(block.Transactions()))
for i, tx := range block.Transactions() {
v := NewTransactionRes(tx)
v.BlockHash = block.Hash()
v.BlockNumber = block.Number().Int64()
v.TxIndex = int64(i)
res.Transactions[i] = v
}
res.Uncles = make([][]byte, len(block.Uncles()))
for i, uncle := range block.Uncles() {
res.Uncles[i] = uncle.Hash()
}
return res
}
type TransactionRes struct {
Hash []byte `json:"hash"`
Nonce int64 `json:"nonce"`
BlockHash []byte `json:"blockHash,omitempty"`
BlockNumber int64 `json:"blockNumber,omitempty"`
TxIndex int64 `json:"transactionIndex,omitempty"`
From []byte `json:"from"`
To []byte `json:"to"`
Value int64 `json:"value"`
Gas int64 `json:"gas"`
GasPrice int64 `json:"gasPrice"`
Input []byte `json:"input"`
}
func (t *TransactionRes) MarshalJSON() ([]byte, error) {
var ext struct {
Hash string `json:"hash"`
Nonce string `json:"nonce"`
BlockHash string `json:"blockHash,omitempty"`
BlockNumber string `json:"blockNumber,omitempty"`
TxIndex string `json:"transactionIndex,omitempty"`
From string `json:"from"`
To string `json:"to"`
Value string `json:"value"`
Gas string `json:"gas"`
GasPrice string `json:"gasPrice"`
Input string `json:"input"`
}
ext.Hash = toHex(t.Hash)
ext.Nonce = toHex(big.NewInt(t.Nonce).Bytes())
ext.BlockHash = toHex(t.BlockHash)
ext.BlockNumber = toHex(big.NewInt(t.BlockNumber).Bytes())
ext.TxIndex = toHex(big.NewInt(t.TxIndex).Bytes())
ext.From = toHex(t.From)
ext.To = toHex(t.To)
ext.Value = toHex(big.NewInt(t.Value).Bytes())
ext.Gas = toHex(big.NewInt(t.Gas).Bytes())
ext.GasPrice = toHex(big.NewInt(t.GasPrice).Bytes())
ext.Input = toHex(t.Input)
return json.Marshal(ext)
}
func NewTransactionRes(tx *types.Transaction) *TransactionRes {
var v = new(TransactionRes)
v.Hash = tx.Hash()
v.Nonce = int64(tx.Nonce())
v.From = tx.From()
v.To = tx.To()
v.Value = tx.Value().Int64()
v.Gas = tx.Gas().Int64()
v.GasPrice = tx.GasPrice().Int64()
v.Input = tx.Data()
return v
}
type FilterLogRes struct {
Hash string `json:"hash"`
Address string `json:"address"`
Data string `json:"data"`
BlockNumber string `json:"blockNumber"`
TransactionHash string `json:"transactionHash"`
BlockHash string `json:"blockHash"`
TransactionIndex string `json:"transactionIndex"`
LogIndex string `json:"logIndex"`
}
type FilterWhisperRes struct {
Hash string `json:"hash"`
From string `json:"from"`
To string `json:"to"`
Expiry string `json:"expiry"`
Sent string `json:"sent"`
Ttl string `json:"ttl"`
Topics string `json:"topics"`
Payload string `json:"payload"`
WorkProved string `json:"workProved"`
}
...@@ -18,8 +18,11 @@ package rpc ...@@ -18,8 +18,11 @@ package rpc
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"math/big"
"net/http" "net/http"
"reflect"
"time" "time"
"github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/ethutil"
...@@ -32,9 +35,63 @@ var rpclogger = logger.NewLogger("RPC") ...@@ -32,9 +35,63 @@ var rpclogger = logger.NewLogger("RPC")
type JsonWrapper struct{} type JsonWrapper struct{}
// Unmarshal state is a helper method which has the ability to decode messsages
// that use the `defaultBlock` (https://github.com/ethereum/wiki/wiki/JSON-RPC#the-default-block-parameter)
// For example a `call`: [{to: "0x....", data:"0x..."}, "latest"]. The first argument is the transaction
// message and the second one refers to the block height (or state) to which to apply this `call`.
func UnmarshalRawMessages(b []byte, iface interface{}, number *int64) (err error) {
var data []json.RawMessage
if err = json.Unmarshal(b, &data); err != nil && len(data) == 0 {
return errDecodeArgs
}
// Number index determines the index in the array for a possible block number
numberIndex := 0
value := reflect.ValueOf(iface)
rvalue := reflect.Indirect(value)
switch rvalue.Kind() {
case reflect.Slice:
// This is a bit of a cheat, but `data` is expected to be larger than 2 if iface is a slice
if number != nil {
numberIndex = len(data) - 1
} else {
numberIndex = len(data)
}
slice := reflect.MakeSlice(rvalue.Type(), numberIndex, numberIndex)
for i, raw := range data[0:numberIndex] {
v := slice.Index(i).Interface()
if err = json.Unmarshal(raw, &v); err != nil {
fmt.Println(err, v)
return err
}
slice.Index(i).Set(reflect.ValueOf(v))
}
reflect.Indirect(rvalue).Set(slice) //value.Set(slice)
case reflect.Struct:
fallthrough
default:
if err = json.Unmarshal(data[0], iface); err != nil {
return errDecodeArgs
}
numberIndex = 1
}
// <0 index means out of bound for block number
if numberIndex >= 0 && len(data) > numberIndex {
if err = blockNumber(data[numberIndex], number); err != nil {
return errDecodeArgs
}
}
return nil
}
func (self JsonWrapper) Send(writer io.Writer, v interface{}) (n int, err error) { func (self JsonWrapper) Send(writer io.Writer, v interface{}) (n int, err error) {
var payload []byte var payload []byte
payload, err = json.Marshal(v) payload, err = json.MarshalIndent(v, "", "\t")
if err != nil { if err != nil {
rpclogger.Fatalln("Error marshalling JSON", err) rpclogger.Fatalln("Error marshalling JSON", err)
return 0, err return 0, err
...@@ -63,18 +120,31 @@ func (self JsonWrapper) ParseRequestBody(req *http.Request) (RpcRequest, error) ...@@ -63,18 +120,31 @@ func (self JsonWrapper) ParseRequestBody(req *http.Request) (RpcRequest, error)
} }
func toHex(b []byte) string { func toHex(b []byte) string {
return "0x" + ethutil.Bytes2Hex(b) hex := ethutil.Bytes2Hex(b)
// Prefer output of "0x0" instead of "0x"
if len(hex) == 0 {
hex = "0"
}
return "0x" + hex
} }
func fromHex(s string) []byte { func fromHex(s string) []byte {
if len(s) > 1 { if len(s) > 1 {
if s[0:2] == "0x" { if s[0:2] == "0x" {
s = s[2:] s = s[2:]
} }
if len(s)%2 == 1 {
s = "0" + s
}
return ethutil.Hex2Bytes(s) return ethutil.Hex2Bytes(s)
} }
return nil return nil
} }
func i2hex(n int) string {
return toHex(big.NewInt(int64(n)).Bytes())
}
type RpcServer interface { type RpcServer interface {
Start() Start()
Stop() Stop()
......
package rpc
import (
"bytes"
"testing"
)
//fromHex
func TestFromHex(t *testing.T) {
input := "0x01"
expected := []byte{1}
result := fromHex(input)
if bytes.Compare(expected, result) != 0 {
t.Errorf("Expected % x got % x", expected, result)
}
}
func TestFromHexOddLength(t *testing.T) {
input := "0x1"
expected := []byte{1}
result := fromHex(input)
if bytes.Compare(expected, result) != 0 {
t.Errorf("Expected % x got % x", expected, result)
}
}
...@@ -37,7 +37,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I ...@@ -37,7 +37,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
context := NewContext(caller, me, code, gas, price) context := NewContext(caller, me, code, gas, price)
vmlogger.Debugf("(%d) (%x) %x (code=%d) gas: %v (d) %x\n", self.env.Depth(), caller.Address()[:4], context.Address(), len(code), context.Gas, callData) self.Printf("(%d) (%x) %x (code=%d) gas: %v (d) %x", self.env.Depth(), caller.Address()[:4], context.Address(), len(code), context.Gas, callData).Endl()
if self.Recoverable { if self.Recoverable {
// Recover from any require exception // Recover from any require exception
...@@ -696,7 +696,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I ...@@ -696,7 +696,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
if err != nil { if err != nil {
stack.push(ethutil.BigFalse) stack.push(ethutil.BigFalse)
vmlogger.Debugln(err) self.Printf("%v").Endl()
} else { } else {
stack.push(ethutil.BigTrue) stack.push(ethutil.BigTrue)
...@@ -726,7 +726,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I ...@@ -726,7 +726,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
return context.Return(nil), nil return context.Return(nil), nil
default: default:
vmlogger.Debugf("(pc) %-3v Invalid opcode %x\n", pc, op) self.Printf("(pc) %-3v Invalid opcode %x\n", pc, op).Endl()
panic(fmt.Errorf("Invalid opcode %x", op)) panic(fmt.Errorf("Invalid opcode %x", op))
} }
...@@ -894,7 +894,7 @@ func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine { ...@@ -894,7 +894,7 @@ func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine {
func (self *Vm) Endl() VirtualMachine { func (self *Vm) Endl() VirtualMachine {
if self.debug { if self.debug {
if self.logTy == LogTyPretty { if self.logTy == LogTyPretty {
vmlogger.Debugln(self.logStr) vmlogger.Infoln(self.logStr)
self.logStr = "" self.logStr = ""
} }
} }
......
...@@ -98,7 +98,7 @@ func New(eth Backend, frontend Frontend) *XEth { ...@@ -98,7 +98,7 @@ func New(eth Backend, frontend Frontend) *XEth {
} }
func (self *XEth) Backend() Backend { return self.eth } func (self *XEth) Backend() Backend { return self.eth }
func (self *XEth) UseState(statedb *state.StateDB) *XEth { func (self *XEth) WithState(statedb *state.StateDB) *XEth {
xeth := &XEth{ xeth := &XEth{
eth: self.eth, eth: self.eth,
blockProcessor: self.blockProcessor, blockProcessor: self.blockProcessor,
...@@ -122,7 +122,14 @@ func (self *XEth) BlockByHash(strHash string) *Block { ...@@ -122,7 +122,14 @@ func (self *XEth) BlockByHash(strHash string) *Block {
return NewBlock(block) return NewBlock(block)
} }
func (self *XEth) BlockByNumber(num int32) *Block { func (self *XEth) EthBlockByHash(strHash string) *types.Block {
hash := fromHex(strHash)
block := self.chainManager.GetBlock(hash)
return block
}
func (self *XEth) BlockByNumber(num int64) *Block {
if num == -1 { if num == -1 {
return NewBlock(self.chainManager.CurrentBlock()) return NewBlock(self.chainManager.CurrentBlock())
} }
...@@ -130,13 +137,21 @@ func (self *XEth) BlockByNumber(num int32) *Block { ...@@ -130,13 +137,21 @@ func (self *XEth) BlockByNumber(num int32) *Block {
return NewBlock(self.chainManager.GetBlockByNumber(uint64(num))) return NewBlock(self.chainManager.GetBlockByNumber(uint64(num)))
} }
func (self *XEth) EthBlockByNumber(num int64) *types.Block {
if num == -1 {
return self.chainManager.CurrentBlock()
}
return self.chainManager.GetBlockByNumber(uint64(num))
}
func (self *XEth) Block(v interface{}) *Block { func (self *XEth) Block(v interface{}) *Block {
if n, ok := v.(int32); ok { if n, ok := v.(int32); ok {
return self.BlockByNumber(n) return self.BlockByNumber(int64(n))
} else if str, ok := v.(string); ok { } else if str, ok := v.(string); ok {
return self.BlockByHash(str) return self.BlockByHash(str)
} else if f, ok := v.(float64); ok { // Don't ask ... } else if f, ok := v.(float64); ok { // Don't ask ...
return self.BlockByNumber(int32(f)) return self.BlockByNumber(int64(f))
} }
return nil return nil
...@@ -278,14 +293,12 @@ func (self *XEth) PushTx(encodedTx string) (string, error) { ...@@ -278,14 +293,12 @@ func (self *XEth) PushTx(encodedTx string) (string, error) {
return toHex(tx.Hash()), nil return toHex(tx.Hash()), nil
} }
func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, error) { var (
if len(gasStr) == 0 { defaultGasPrice = big.NewInt(10000000000000)
gasStr = "100000" defaultGas = big.NewInt(90000)
} )
if len(gasPriceStr) == 0 {
gasPriceStr = "1"
}
func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, error) {
statedb := self.State().State() //self.chainManager.TransState() statedb := self.State().State() //self.chainManager.TransState()
msg := callmsg{ msg := callmsg{
from: statedb.GetOrNewStateObject(fromHex(fromStr)), from: statedb.GetOrNewStateObject(fromHex(fromStr)),
...@@ -295,6 +308,14 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st ...@@ -295,6 +308,14 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
value: ethutil.Big(valueStr), value: ethutil.Big(valueStr),
data: fromHex(dataStr), data: fromHex(dataStr),
} }
if msg.gas.Cmp(big.NewInt(0)) == 0 {
msg.gas = defaultGas
}
if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
msg.gasPrice = defaultGasPrice
}
block := self.chainManager.CurrentBlock() block := self.chainManager.CurrentBlock()
vmenv := core.NewEnv(statedb, self.chainManager, msg, block) vmenv := core.NewEnv(statedb, self.chainManager, msg, block)
...@@ -327,7 +348,7 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt ...@@ -327,7 +348,7 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt
tx = types.NewTransactionMessage(to, value.BigInt(), gas.BigInt(), price.BigInt(), data) tx = types.NewTransactionMessage(to, value.BigInt(), gas.BigInt(), price.BigInt(), data)
} }
state := self.chainManager.TransState() state := self.chainManager.TxState()
nonce := state.GetNonce(from) nonce := state.GetNonce(from)
tx.SetNonce(nonce) tx.SetNonce(nonce)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment