Skip to content

Commit 323216e

Browse files
committed
Merge pull request #861 from obscuren/transaction_pool_fixes
core: transaction pool fixes & resending transactions
2 parents 1f26a1b + 05ac120 commit 323216e

File tree

8 files changed

+133
-7
lines changed

8 files changed

+133
-7
lines changed

cmd/geth/admin.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"errors"
55
"fmt"
6+
"strconv"
67
"time"
78

89
"github.com/ethereum/go-ethereum/cmd/utils"
@@ -15,13 +16,19 @@ import (
1516
"github.com/ethereum/go-ethereum/rpc"
1617
"github.com/ethereum/go-ethereum/xeth"
1718
"github.com/robertkrimen/otto"
19+
"gopkg.in/fatih/set.v0"
1820
)
1921

2022
/*
2123
node admin bindings
2224
*/
2325

2426
func (js *jsre) adminBindings() {
27+
ethO, _ := js.re.Get("eth")
28+
eth := ethO.Object()
29+
eth.Set("pendingTransactions", js.pendingTransactions)
30+
eth.Set("resend", js.resend)
31+
2532
js.re.Set("admin", struct{}{})
2633
t, _ := js.re.Get("admin")
2734
admin := t.Object()
@@ -74,6 +81,70 @@ func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
7481
return nil, errors.New("requires block number or block hash as argument")
7582
}
7683

84+
func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value {
85+
txs := js.ethereum.TxPool().GetTransactions()
86+
87+
// grab the accounts from the account manager. This will help with determening which
88+
// transactions should be returned.
89+
accounts, err := js.ethereum.AccountManager().Accounts()
90+
if err != nil {
91+
fmt.Println(err)
92+
return otto.UndefinedValue()
93+
}
94+
95+
// Add the accouns to a new set
96+
accountSet := set.New()
97+
for _, account := range accounts {
98+
accountSet.Add(common.BytesToAddress(account.Address))
99+
}
100+
101+
//ltxs := make([]*tx, len(txs))
102+
var ltxs []*tx
103+
for _, tx := range txs {
104+
// no need to check err
105+
if from, _ := tx.From(); accountSet.Has(from) {
106+
ltxs = append(ltxs, newTx(tx))
107+
}
108+
}
109+
110+
return js.re.ToVal(ltxs)
111+
}
112+
113+
func (js *jsre) resend(call otto.FunctionCall) otto.Value {
114+
if len(call.ArgumentList) == 0 {
115+
fmt.Println("first argument must be a transaction")
116+
return otto.FalseValue()
117+
}
118+
119+
v, err := call.Argument(0).Export()
120+
if err != nil {
121+
fmt.Println(err)
122+
return otto.FalseValue()
123+
}
124+
125+
if tx, ok := v.(*tx); ok {
126+
gl, gp := tx.GasLimit, tx.GasPrice
127+
if len(call.ArgumentList) > 1 {
128+
gp = call.Argument(1).String()
129+
}
130+
if len(call.ArgumentList) > 2 {
131+
gl = call.Argument(2).String()
132+
}
133+
134+
ret, err := js.xeth.Transact(tx.From, tx.To, tx.Nonce, tx.Value, gl, gp, tx.Data)
135+
if err != nil {
136+
fmt.Println(err)
137+
return otto.FalseValue()
138+
}
139+
js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx})
140+
141+
return js.re.ToVal(ret)
142+
}
143+
144+
fmt.Println("first argument must be a transaction")
145+
return otto.FalseValue()
146+
}
147+
77148
func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
78149
block, err := js.getBlock(call)
79150
if err != nil {
@@ -421,3 +492,35 @@ func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
421492
return js.re.ToVal(dump)
422493

423494
}
495+
496+
// internal transaction type which will allow us to resend transactions using `eth.resend`
497+
type tx struct {
498+
tx *types.Transaction
499+
500+
To string
501+
From string
502+
Nonce string
503+
Value string
504+
Data string
505+
GasLimit string
506+
GasPrice string
507+
}
508+
509+
func newTx(t *types.Transaction) *tx {
510+
from, _ := t.From()
511+
var to string
512+
if t := t.To(); t != nil {
513+
to = t.Hex()
514+
}
515+
516+
return &tx{
517+
tx: t,
518+
To: to,
519+
From: from.Hex(),
520+
Value: t.Amount.String(),
521+
Nonce: strconv.Itoa(int(t.Nonce())),
522+
Data: "0x" + common.Bytes2Hex(t.Data()),
523+
GasLimit: t.GasLimit.String(),
524+
GasPrice: t.GasPrice().String(),
525+
}
526+
}

cmd/mist/bindings.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type plugin struct {
4040
func (gui *Gui) Transact(from, recipient, value, gas, gasPrice, d string) (string, error) {
4141
d = common.Bytes2Hex(utils.FormatTransactionData(d))
4242

43-
return gui.xeth.Transact(from, recipient, value, gas, gasPrice, d)
43+
return gui.xeth.Transact(from, recipient, "", value, gas, gasPrice, d)
4444
}
4545

4646
func (self *Gui) AddPlugin(pluginPath string) {

cmd/mist/ui_lib.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ func (self *UiLib) Transact(params map[string]interface{}) (string, error) {
119119
return self.XEth.Transact(
120120
object["from"],
121121
object["to"],
122+
"",
122123
object["value"],
123124
object["gas"],
124125
object["gasPrice"],

common/resolver/resolver.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ var HashRegContractAddress string = "0000000000000000000000000000000000000000000
2424

2525
func CreateContracts(xeth *xe.XEth, addr string) {
2626
var err error
27-
URLHintContractAddress, err = xeth.Transact(addr, "", "100000000000", "1000000", "100000", ContractCodeURLhint)
27+
URLHintContractAddress, err = xeth.Transact(addr, "", "", "100000000000", "1000000", "100000", ContractCodeURLhint)
2828
if err != nil {
2929
panic(err)
3030
}
31-
HashRegContractAddress, err = xeth.Transact(addr, "", "100000000000", "1000000", "100000", ContractCodeHashReg)
31+
HashRegContractAddress, err = xeth.Transact(addr, "", "", "100000000000", "1000000", "100000", ContractCodeHashReg)
3232
if err != nil {
3333
panic(err)
3434
}

core/transaction_pool.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ func (self *TxPool) RemoveTransactions(txs types.Transactions) {
235235
defer self.mu.Unlock()
236236

237237
for _, tx := range txs {
238-
delete(self.txs, tx.Hash())
238+
self.removeTx(tx.Hash())
239239
}
240240
}
241241

rpc/api.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,13 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
173173
return fmt.Errorf("Transaction not confirmed")
174174
}
175175

176-
v, err := api.xeth().Transact(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
176+
// nonce may be nil ("guess" mode)
177+
var nonce string
178+
if args.Nonce != nil {
179+
nonce = args.Nonce.String()
180+
}
181+
182+
v, err := api.xeth().Transact(args.From, args.To, nonce, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
177183
if err != nil {
178184
return err
179185
}

rpc/args.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
157157
type NewTxArgs struct {
158158
From string
159159
To string
160+
Nonce *big.Int
160161
Value *big.Int
161162
Gas *big.Int
162163
GasPrice *big.Int
@@ -170,6 +171,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
170171
var ext struct {
171172
From string
172173
To string
174+
Nonce interface{}
173175
Value interface{}
174176
Gas interface{}
175177
GasPrice interface{}
@@ -200,6 +202,14 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
200202
args.Data = ext.Data
201203

202204
var num *big.Int
205+
if ext.Nonce != nil {
206+
num, err = numString(ext.Nonce)
207+
if err != nil {
208+
return err
209+
}
210+
}
211+
args.Nonce = num
212+
203213
if ext.Value == nil {
204214
num = big.NewInt(0)
205215
} else {

xeth/xeth.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ func (self *XEth) ConfirmTransaction(tx string) bool {
648648

649649
}
650650

651-
func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
651+
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
652652
var (
653653
from = common.HexToAddress(fromStr)
654654
to = common.HexToAddress(toStr)
@@ -704,7 +704,13 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt
704704
}
705705

706706
state := self.backend.ChainManager().TxState()
707-
nonce := state.NewNonce(from)
707+
708+
var nonce uint64
709+
if len(nonceStr) != 0 {
710+
nonce = common.Big(nonceStr).Uint64()
711+
} else {
712+
nonce = state.NewNonce(from)
713+
}
708714
tx.SetNonce(nonce)
709715

710716
if err := self.sign(tx, from, false); err != nil {

0 commit comments

Comments
 (0)