forked from cerc-io/plugeth
More dapp samples
* Info DApp, coin DApp * Additional rpc methods
This commit is contained in:
+38
-5
@@ -69,10 +69,28 @@ func (a *PushTxArgs) requirementsPushTx() error {
|
||||
|
||||
type GetStorageArgs struct {
|
||||
Address string
|
||||
Key string
|
||||
}
|
||||
|
||||
func (obj *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
|
||||
if err = json.Unmarshal(b, &obj.Address); err != nil {
|
||||
return NewErrorResponse(ErrorDecodeArgs)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *GetStorageArgs) requirements() error {
|
||||
if len(a.Address) == 0 {
|
||||
return NewErrorResponse("GetStorageAt requires an 'address' value as argument")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetStateArgs struct {
|
||||
Address string
|
||||
Key string
|
||||
}
|
||||
|
||||
func (obj *GetStateArgs) UnmarshalJSON(b []byte) (err error) {
|
||||
arg0 := ""
|
||||
if err = json.Unmarshal(b, arg0); err == nil {
|
||||
obj.Address = arg0
|
||||
@@ -81,7 +99,7 @@ func (obj *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
|
||||
return NewErrorResponse(ErrorDecodeArgs)
|
||||
}
|
||||
|
||||
func (a *GetStorageArgs) requirements() error {
|
||||
func (a *GetStateArgs) requirements() error {
|
||||
if a.Address == "" {
|
||||
return NewErrorResponse("GetStorageAt requires an 'address' value as argument")
|
||||
}
|
||||
@@ -92,9 +110,8 @@ func (a *GetStorageArgs) requirements() error {
|
||||
}
|
||||
|
||||
type GetStorageAtRes struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Address string `json:"address"`
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type GetTxCountArgs struct {
|
||||
@@ -218,3 +235,19 @@ func toFilterOptions(options *FilterOptions) core.FilterOptions {
|
||||
type FilterChangedArgs struct {
|
||||
n int
|
||||
}
|
||||
|
||||
type DbArgs struct {
|
||||
Database string
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
|
||||
func (a *DbArgs) requirements() error {
|
||||
if len(a.Database) == 0 {
|
||||
return NewErrorResponse("DbPutArgs requires an 'Database' value as argument")
|
||||
}
|
||||
if len(a.Key) == 0 {
|
||||
return NewErrorResponse("DbPutArgs requires an 'Key' value as argument")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+59
-3
@@ -126,13 +126,28 @@ func (req *RpcRequest) ToPushTxArgs() (*PushTxArgs, error) {
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (req *RpcRequest) ToGetStorageArgs() (*GetStorageArgs, error) {
|
||||
if len(req.Params) < 2 {
|
||||
func (req *RpcRequest) ToGetStateArgs() (*GetStateArgs, error) {
|
||||
if len(req.Params) < 1 {
|
||||
return nil, NewErrorResponse(ErrorArguments)
|
||||
}
|
||||
|
||||
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, NewErrorResponse(ErrorDecodeArgs)
|
||||
}
|
||||
rpclogger.DebugDetailf("%T %v", args, args)
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (req *RpcRequest) ToStorageAtArgs() (*GetStorageArgs, error) {
|
||||
if len(req.Params) < 1 {
|
||||
return nil, NewErrorResponse(ErrorArguments)
|
||||
}
|
||||
|
||||
args := new(GetStorageArgs)
|
||||
// TODO need to pass both arguments
|
||||
r := bytes.NewReader(req.Params[0])
|
||||
err := json.NewDecoder(r).Decode(args)
|
||||
if err != nil {
|
||||
@@ -239,3 +254,44 @@ func toLogs(logs state.Logs) (ls []Log) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (req *RpcRequest) ToDbPutArgs() (*DbArgs, error) {
|
||||
if len(req.Params) < 3 {
|
||||
return nil, NewErrorResponse(ErrorArguments)
|
||||
}
|
||||
|
||||
var args DbArgs
|
||||
err := json.Unmarshal(req.Params[0], &args.Database)
|
||||
if err != nil {
|
||||
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
|
||||
}
|
||||
err = json.Unmarshal(req.Params[1], &args.Key)
|
||||
if err != nil {
|
||||
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
|
||||
}
|
||||
err = json.Unmarshal(req.Params[2], &args.Value)
|
||||
if err != nil {
|
||||
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
|
||||
}
|
||||
rpclogger.DebugDetailf("%T %v", args, args)
|
||||
return &args, nil
|
||||
}
|
||||
|
||||
func (req *RpcRequest) ToDbGetArgs() (*DbArgs, error) {
|
||||
if len(req.Params) < 2 {
|
||||
return nil, NewErrorResponse(ErrorArguments)
|
||||
}
|
||||
|
||||
var args DbArgs
|
||||
err := json.Unmarshal(req.Params[0], &args.Database)
|
||||
if err != nil {
|
||||
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(req.Params[1], &args.Key)
|
||||
if err != nil {
|
||||
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
|
||||
}
|
||||
rpclogger.DebugDetailf("%T %v", args, args)
|
||||
return &args, nil
|
||||
}
|
||||
|
||||
+77
-28
@@ -33,6 +33,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/ethutil"
|
||||
"github.com/ethereum/go-ethereum/event/filter"
|
||||
"github.com/ethereum/go-ethereum/state"
|
||||
@@ -63,13 +64,17 @@ type EthereumApi struct {
|
||||
|
||||
mut sync.RWMutex
|
||||
logs map[int]state.Logs
|
||||
|
||||
db ethutil.Database
|
||||
}
|
||||
|
||||
func NewEthereumApi(xeth *xeth.XEth) *EthereumApi {
|
||||
db, _ := ethdb.NewLDBDatabase("dapps")
|
||||
api := &EthereumApi{
|
||||
xeth: xeth,
|
||||
filterManager: filter.NewFilterManager(xeth.Backend().EventMux()),
|
||||
logs: make(map[int]state.Logs),
|
||||
db: db,
|
||||
}
|
||||
go api.filterManager.Start()
|
||||
|
||||
@@ -91,29 +96,6 @@ func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
type Log struct {
|
||||
Address string `json:"address"`
|
||||
Topics []string `json:"topics"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
func toLogs(logs state.Logs) (ls []Log) {
|
||||
ls = make([]Log, len(logs))
|
||||
|
||||
for i, log := range logs {
|
||||
var l Log
|
||||
l.Topics = make([]string, len(log.Topics()))
|
||||
l.Address = toHex(log.Address())
|
||||
l.Data = toHex(log.Data())
|
||||
for j, topic := range log.Topics() {
|
||||
l.Topics[j] = toHex(topic)
|
||||
}
|
||||
ls[i] = l
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (self *EthereumApi) FilterChanged(id int, reply *interface{}) error {
|
||||
self.mut.RLock()
|
||||
defer self.mut.RUnlock()
|
||||
@@ -176,7 +158,7 @@ func (p *EthereumApi) PushTx(args *PushTxArgs, reply *interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *interface{}) error {
|
||||
func (p *EthereumApi) GetStateAt(args *GetStateArgs, reply *interface{}) error {
|
||||
err := args.requirements()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -184,6 +166,7 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *interface{}) err
|
||||
|
||||
state := p.xeth.State().SafeGet(args.Address)
|
||||
|
||||
value := state.StorageString(args.Key)
|
||||
var hx string
|
||||
if strings.Index(args.Key, "0x") == 0 {
|
||||
hx = string([]byte(args.Key)[2:])
|
||||
@@ -192,9 +175,18 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *interface{}) err
|
||||
i, _ := new(big.Int).SetString(args.Key, 10)
|
||||
hx = ethutil.Bytes2Hex(i.Bytes())
|
||||
}
|
||||
rpclogger.Debugf("GetStorageAt(%s, %s)\n", args.Address, hx)
|
||||
value := state.Storage(ethutil.Hex2Bytes(hx))
|
||||
*reply = GetStorageAtRes{Address: args.Address, Key: args.Key, Value: value.Str()}
|
||||
rpclogger.Debugf("GetStateAt(%s, %s)\n", args.Address, hx)
|
||||
*reply = map[string]string{args.Key: value.Str()}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *interface{}) error {
|
||||
err := args.requirements()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*reply = p.xeth.State().SafeGet(args.Address).Storage()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -213,11 +205,21 @@ func (p *EthereumApi) GetCoinbase(reply *interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *EthereumApi) Accounts(reply *interface{}) error {
|
||||
*reply = p.xeth.Accounts()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *EthereumApi) GetIsMining(reply *interface{}) error {
|
||||
*reply = p.xeth.IsMining()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *EthereumApi) BlockNumber(reply *interface{}) error {
|
||||
*reply = p.xeth.Backend().ChainManager().CurrentBlock().Number()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *EthereumApi) GetTxCountAt(args *GetTxCountArgs, reply *interface{}) error {
|
||||
err := args.requirements()
|
||||
if err != nil {
|
||||
@@ -251,6 +253,28 @@ func (p *EthereumApi) Sha3(args *Sha3Args, reply *interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *EthereumApi) DbPut(args *DbArgs, reply *interface{}) error {
|
||||
err := args.requirements()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.db.Put([]byte(args.Database+args.Key), []byte(args.Value))
|
||||
*reply = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *EthereumApi) DbGet(args *DbArgs, reply *interface{}) error {
|
||||
err := args.requirements()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, _ := p.db.Get([]byte(args.Database + args.Key))
|
||||
*reply = string(res)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error {
|
||||
// Spec at https://github.com/ethereum/wiki/wiki/Generic-ON-RPC
|
||||
rpclogger.DebugDetailf("%T %s", req.Params, req.Params)
|
||||
@@ -263,6 +287,10 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
|
||||
return p.GetIsMining(reply)
|
||||
case "eth_peerCount":
|
||||
return p.GetPeerCount(reply)
|
||||
case "eth_number":
|
||||
return p.BlockNumber(reply)
|
||||
case "eth_accounts":
|
||||
return p.Accounts(reply)
|
||||
case "eth_countAt":
|
||||
args, err := req.ToGetTxCountArgs()
|
||||
if err != nil {
|
||||
@@ -282,7 +310,13 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
|
||||
}
|
||||
return p.GetBalanceAt(args, reply)
|
||||
case "eth_stateAt":
|
||||
args, err := req.ToGetStorageArgs()
|
||||
args, err := req.ToGetStateArgs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.GetStateAt(args, reply)
|
||||
case "eth_storageAt":
|
||||
args, err := req.ToStorageAtArgs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -317,12 +351,27 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
|
||||
return err
|
||||
}
|
||||
return p.FilterChanged(args, reply)
|
||||
case "eth_gasPrice":
|
||||
*reply = "1000000000000000"
|
||||
return nil
|
||||
case "web3_sha3":
|
||||
args, err := req.ToSha3Args()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.Sha3(args, reply)
|
||||
case "db_put":
|
||||
args, err := req.ToDbPutArgs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.DbPut(args, reply)
|
||||
case "db_get":
|
||||
args, err := req.ToDbGetArgs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.DbGet(args, reply)
|
||||
default:
|
||||
return NewErrorResponse(fmt.Sprintf("%v %s", ErrorNotImplemented, req.Method))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user