|
|
|
@ -4,9 +4,12 @@ import ( |
|
|
|
|
"encoding/json" |
|
|
|
|
"fmt" |
|
|
|
|
"math/big" |
|
|
|
|
"strconv" |
|
|
|
|
"strings" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
|
"github.com/ethereum/go-ethereum/core/state" |
|
|
|
|
"github.com/ethereum/go-ethereum/core/types" |
|
|
|
|
"github.com/ethereum/go-ethereum/rpc/shared" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
@ -858,3 +861,178 @@ func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) { |
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type tx struct { |
|
|
|
|
tx *types.Transaction |
|
|
|
|
|
|
|
|
|
To string |
|
|
|
|
From string |
|
|
|
|
Nonce string |
|
|
|
|
Value string |
|
|
|
|
Data string |
|
|
|
|
GasLimit string |
|
|
|
|
GasPrice string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func newTx(t *types.Transaction) *tx { |
|
|
|
|
from, _ := t.From() |
|
|
|
|
var to string |
|
|
|
|
if t := t.To(); t != nil { |
|
|
|
|
to = t.Hex() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return &tx{ |
|
|
|
|
tx: t, |
|
|
|
|
To: to, |
|
|
|
|
From: from.Hex(), |
|
|
|
|
Value: t.Value().String(), |
|
|
|
|
Nonce: strconv.Itoa(int(t.Nonce())), |
|
|
|
|
Data: "0x" + common.Bytes2Hex(t.Data()), |
|
|
|
|
GasLimit: t.Gas().String(), |
|
|
|
|
GasPrice: t.GasPrice().String(), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type ResendArgs struct { |
|
|
|
|
Tx *tx |
|
|
|
|
GasPrice string |
|
|
|
|
GasLimit string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (tx *tx) UnmarshalJSON(b []byte) (err error) { |
|
|
|
|
var fields map[string]interface{} |
|
|
|
|
if err := json.Unmarshal(b, &fields); err != nil { |
|
|
|
|
return shared.NewDecodeParamError(err.Error()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
nonce uint64 |
|
|
|
|
to common.Address |
|
|
|
|
amount = new(big.Int).Set(common.Big0) |
|
|
|
|
gasLimit = new(big.Int).Set(common.Big0) |
|
|
|
|
gasPrice = new(big.Int).Set(common.Big0) |
|
|
|
|
data []byte |
|
|
|
|
contractCreation = true |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
if val, found := fields["To"]; found { |
|
|
|
|
if strVal, ok := val.(string); ok && len(strVal) > 0 { |
|
|
|
|
tx.To = strVal |
|
|
|
|
to = common.HexToAddress(strVal) |
|
|
|
|
contractCreation = false |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if val, found := fields["From"]; found { |
|
|
|
|
if strVal, ok := val.(string); ok { |
|
|
|
|
tx.From = strVal |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if val, found := fields["Nonce"]; found { |
|
|
|
|
if strVal, ok := val.(string); ok { |
|
|
|
|
tx.Nonce = strVal |
|
|
|
|
if nonce, err = strconv.ParseUint(strVal, 10, 64); err != nil { |
|
|
|
|
return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.Nonce - %v", err)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
return shared.NewDecodeParamError("tx.Nonce not found") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var parseOk bool |
|
|
|
|
if val, found := fields["Value"]; found { |
|
|
|
|
if strVal, ok := val.(string); ok { |
|
|
|
|
tx.Value = strVal |
|
|
|
|
if _, parseOk = amount.SetString(strVal, 0); !parseOk { |
|
|
|
|
return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.Amount - %v", err)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if val, found := fields["Data"]; found { |
|
|
|
|
if strVal, ok := val.(string); ok { |
|
|
|
|
tx.Data = strVal |
|
|
|
|
if strings.HasPrefix(strVal, "0x") { |
|
|
|
|
data = common.Hex2Bytes(strVal[2:]) |
|
|
|
|
} else { |
|
|
|
|
data = common.Hex2Bytes(strVal) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if val, found := fields["GasLimit"]; found { |
|
|
|
|
if strVal, ok := val.(string); ok { |
|
|
|
|
tx.GasLimit = strVal |
|
|
|
|
if _, parseOk = gasLimit.SetString(strVal, 0); !parseOk { |
|
|
|
|
return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.GasLimit - %v", err)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if val, found := fields["GasPrice"]; found { |
|
|
|
|
if strVal, ok := val.(string); ok { |
|
|
|
|
tx.GasPrice = strVal |
|
|
|
|
if _, parseOk = gasPrice.SetString(strVal, 0); !parseOk { |
|
|
|
|
return shared.NewDecodeParamError(fmt.Sprintf("Unable to decode tx.GasPrice - %v", err)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if contractCreation { |
|
|
|
|
tx.tx = types.NewContractCreation(nonce, amount, gasLimit, gasPrice, data) |
|
|
|
|
} else { |
|
|
|
|
tx.tx = types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (args *ResendArgs) UnmarshalJSON(b []byte) (err error) { |
|
|
|
|
var obj []interface{} |
|
|
|
|
if err = json.Unmarshal(b, &obj); err != nil { |
|
|
|
|
return shared.NewDecodeParamError(err.Error()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(obj) < 1 { |
|
|
|
|
return shared.NewInsufficientParamsError(len(obj), 1) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
data, err := json.Marshal(obj[0]) |
|
|
|
|
if err != nil { |
|
|
|
|
return shared.NewDecodeParamError("Unable to parse transaction object") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
trans := new(tx) |
|
|
|
|
err = json.Unmarshal(data, trans) |
|
|
|
|
if err != nil { |
|
|
|
|
return shared.NewDecodeParamError("Unable to parse transaction object") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if trans == nil || trans.tx == nil { |
|
|
|
|
return shared.NewDecodeParamError("Unable to parse transaction object") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gasLimit, gasPrice := trans.GasLimit, trans.GasPrice |
|
|
|
|
|
|
|
|
|
if len(obj) > 1 && obj[1] != nil { |
|
|
|
|
if gp, ok := obj[1].(string); ok { |
|
|
|
|
gasPrice = gp |
|
|
|
|
} else { |
|
|
|
|
return shared.NewInvalidTypeError("gasPrice", "not a string") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if len(obj) > 2 && obj[2] != nil { |
|
|
|
|
if gl, ok := obj[2].(string); ok { |
|
|
|
|
gasLimit = gl |
|
|
|
|
} else { |
|
|
|
|
return shared.NewInvalidTypeError("gasLimit", "not a string") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
args.Tx = trans |
|
|
|
|
args.GasPrice = gasPrice |
|
|
|
|
args.GasLimit = gasLimit |
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|