aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/geth/admin.go103
-rw-r--r--cmd/mist/bindings.go2
-rw-r--r--cmd/mist/ui_lib.go1
-rw-r--r--common/resolver/resolver.go4
-rw-r--r--core/transaction_pool.go2
-rw-r--r--rpc/api.go8
-rw-r--r--rpc/args.go10
-rw-r--r--xeth/xeth.go10
8 files changed, 133 insertions, 7 deletions
diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go
index 31f8d4400..e7cc96ddb 100644
--- a/cmd/geth/admin.go
+++ b/cmd/geth/admin.go
@@ -3,6 +3,7 @@ package main
import (
"errors"
"fmt"
+ "strconv"
"time"
"github.com/ethereum/go-ethereum/cmd/utils"
@@ -15,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/xeth"
"github.com/robertkrimen/otto"
+ "gopkg.in/fatih/set.v0"
)
/*
@@ -22,6 +24,11 @@ node admin bindings
*/
func (js *jsre) adminBindings() {
+ ethO, _ := js.re.Get("eth")
+ eth := ethO.Object()
+ eth.Set("pendingTransactions", js.pendingTransactions)
+ eth.Set("resend", js.resend)
+
js.re.Set("admin", struct{}{})
t, _ := js.re.Get("admin")
admin := t.Object()
@@ -74,6 +81,70 @@ func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
return nil, errors.New("requires block number or block hash as argument")
}
+func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value {
+ txs := js.ethereum.TxPool().GetTransactions()
+
+ // grab the accounts from the account manager. This will help with determening which
+ // transactions should be returned.
+ accounts, err := js.ethereum.AccountManager().Accounts()
+ if err != nil {
+ fmt.Println(err)
+ return otto.UndefinedValue()
+ }
+
+ // Add the accouns to a new set
+ accountSet := set.New()
+ for _, account := range accounts {
+ accountSet.Add(common.BytesToAddress(account.Address))
+ }
+
+ //ltxs := make([]*tx, len(txs))
+ var ltxs []*tx
+ for _, tx := range txs {
+ // no need to check err
+ if from, _ := tx.From(); accountSet.Has(from) {
+ ltxs = append(ltxs, newTx(tx))
+ }
+ }
+
+ return js.re.ToVal(ltxs)
+}
+
+func (js *jsre) resend(call otto.FunctionCall) otto.Value {
+ if len(call.ArgumentList) == 0 {
+ fmt.Println("first argument must be a transaction")
+ return otto.FalseValue()
+ }
+
+ v, err := call.Argument(0).Export()
+ if err != nil {
+ fmt.Println(err)
+ return otto.FalseValue()
+ }
+
+ if tx, ok := v.(*tx); ok {
+ gl, gp := tx.GasLimit, tx.GasPrice
+ if len(call.ArgumentList) > 1 {
+ gp = call.Argument(1).String()
+ }
+ if len(call.ArgumentList) > 2 {
+ gl = call.Argument(2).String()
+ }
+
+ ret, err := js.xeth.Transact(tx.From, tx.To, tx.Nonce, tx.Value, gl, gp, tx.Data)
+ if err != nil {
+ fmt.Println(err)
+ return otto.FalseValue()
+ }
+ js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx})
+
+ return js.re.ToVal(ret)
+ }
+
+ fmt.Println("first argument must be a transaction")
+ return otto.FalseValue()
+}
+
func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
block, err := js.getBlock(call)
if err != nil {
@@ -421,3 +492,35 @@ func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
return js.re.ToVal(dump)
}
+
+// internal transaction type which will allow us to resend transactions using `eth.resend`
+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.Amount.String(),
+ Nonce: strconv.Itoa(int(t.Nonce())),
+ Data: "0x" + common.Bytes2Hex(t.Data()),
+ GasLimit: t.GasLimit.String(),
+ GasPrice: t.GasPrice().String(),
+ }
+}
diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go
index e7ce50c35..7512421a1 100644
--- a/cmd/mist/bindings.go
+++ b/cmd/mist/bindings.go
@@ -40,7 +40,7 @@ type plugin struct {
func (gui *Gui) Transact(from, recipient, value, gas, gasPrice, d string) (string, error) {
d = common.Bytes2Hex(utils.FormatTransactionData(d))
- return gui.xeth.Transact(from, recipient, value, gas, gasPrice, d)
+ return gui.xeth.Transact(from, recipient, "", value, gas, gasPrice, d)
}
func (self *Gui) AddPlugin(pluginPath string) {
diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go
index 34ce56e77..2de71491c 100644
--- a/cmd/mist/ui_lib.go
+++ b/cmd/mist/ui_lib.go
@@ -119,6 +119,7 @@ func (self *UiLib) Transact(params map[string]interface{}) (string, error) {
return self.XEth.Transact(
object["from"],
object["to"],
+ "",
object["value"],
object["gas"],
object["gasPrice"],
diff --git a/common/resolver/resolver.go b/common/resolver/resolver.go
index 1e6d03ffb..42348a89c 100644
--- a/common/resolver/resolver.go
+++ b/common/resolver/resolver.go
@@ -24,11 +24,11 @@ var HashRegContractAddress string = "0000000000000000000000000000000000000000000
func CreateContracts(xeth *xe.XEth, addr string) {
var err error
- URLHintContractAddress, err = xeth.Transact(addr, "", "100000000000", "1000000", "100000", ContractCodeURLhint)
+ URLHintContractAddress, err = xeth.Transact(addr, "", "", "100000000000", "1000000", "100000", ContractCodeURLhint)
if err != nil {
panic(err)
}
- HashRegContractAddress, err = xeth.Transact(addr, "", "100000000000", "1000000", "100000", ContractCodeHashReg)
+ HashRegContractAddress, err = xeth.Transact(addr, "", "", "100000000000", "1000000", "100000", ContractCodeHashReg)
if err != nil {
panic(err)
}
diff --git a/core/transaction_pool.go b/core/transaction_pool.go
index 22a804e1d..bac6b7f0b 100644
--- a/core/transaction_pool.go
+++ b/core/transaction_pool.go
@@ -235,7 +235,7 @@ func (self *TxPool) RemoveTransactions(txs types.Transactions) {
defer self.mu.Unlock()
for _, tx := range txs {
- delete(self.txs, tx.Hash())
+ self.removeTx(tx.Hash())
}
}
diff --git a/rpc/api.go b/rpc/api.go
index 6d3a20bfa..b79a1306e 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -173,7 +173,13 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return fmt.Errorf("Transaction not confirmed")
}
- v, err := api.xeth().Transact(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
+ // nonce may be nil ("guess" mode)
+ var nonce string
+ if args.Nonce != nil {
+ nonce = args.Nonce.String()
+ }
+
+ v, err := api.xeth().Transact(args.From, args.To, nonce, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
if err != nil {
return err
}
diff --git a/rpc/args.go b/rpc/args.go
index 4bd48e6d6..e61f28c4f 100644
--- a/rpc/args.go
+++ b/rpc/args.go
@@ -157,6 +157,7 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
type NewTxArgs struct {
From string
To string
+ Nonce *big.Int
Value *big.Int
Gas *big.Int
GasPrice *big.Int
@@ -170,6 +171,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
var ext struct {
From string
To string
+ Nonce interface{}
Value interface{}
Gas interface{}
GasPrice interface{}
@@ -200,6 +202,14 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
args.Data = ext.Data
var num *big.Int
+ if ext.Nonce != nil {
+ num, err = numString(ext.Nonce)
+ if err != nil {
+ return err
+ }
+ }
+ args.Nonce = num
+
if ext.Value == nil {
num = big.NewInt(0)
} else {
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 692fb338c..ac59069d5 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -648,7 +648,7 @@ func (self *XEth) ConfirmTransaction(tx string) bool {
}
-func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
+func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
var (
from = common.HexToAddress(fromStr)
to = common.HexToAddress(toStr)
@@ -704,7 +704,13 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt
}
state := self.backend.ChainManager().TxState()
- nonce := state.NewNonce(from)
+
+ var nonce uint64
+ if len(nonceStr) != 0 {
+ nonce = common.Big(nonceStr).Uint64()
+ } else {
+ nonce = state.NewNonce(from)
+ }
tx.SetNonce(nonce)
if err := self.sign(tx, from, false); err != nil {