Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
654564e1
Commit
654564e1
authored
Jun 11, 2015
by
Felix Lange
Committed by
Jeffrey Wilcke
Jun 29, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core/types: make transactions immutable
parent
9d8b512b
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
215 additions
and
275 deletions
+215
-275
transaction_pool.go
core/transaction_pool.go
+8
-11
transaction_pool_test.go
core/transaction_pool_test.go
+26
-65
block_test.go
core/types/block_test.go
+4
-15
transaction.go
core/types/transaction.go
+127
-119
transaction_test.go
core/types/transaction_test.go
+12
-20
protocol_test.go
eth/protocol_test.go
+2
-2
transaction_test_util.go
tests/transaction_test_util.go
+22
-23
xeth.go
xeth/xeth.go
+14
-20
No files found.
core/transaction_pool.go
View file @
654564e1
...
@@ -162,27 +162,25 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
...
@@ -162,27 +162,25 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
// Check the transaction doesn't exceed the current
// Check the transaction doesn't exceed the current
// block limit gas.
// block limit gas.
if
pool
.
gasLimit
()
.
Cmp
(
tx
.
Gas
Limit
)
<
0
{
if
pool
.
gasLimit
()
.
Cmp
(
tx
.
Gas
()
)
<
0
{
return
ErrGasLimit
return
ErrGasLimit
}
}
// Transactions can't be negative. This may never happen
// Transactions can't be negative. This may never happen
// using RLP decoded transactions but may occur if you create
// using RLP decoded transactions but may occur if you create
// a transaction using the RPC for example.
// a transaction using the RPC for example.
if
tx
.
Amount
.
Cmp
(
common
.
Big0
)
<
0
{
if
tx
.
Value
()
.
Cmp
(
common
.
Big0
)
<
0
{
return
ErrNegativeValue
return
ErrNegativeValue
}
}
// Transactor should have enough funds to cover the costs
// Transactor should have enough funds to cover the costs
// cost == V + GP * GL
// cost == V + GP * GL
total
:=
new
(
big
.
Int
)
.
Mul
(
tx
.
Price
,
tx
.
GasLimit
)
if
pool
.
currentState
()
.
GetBalance
(
from
)
.
Cmp
(
tx
.
Cost
())
<
0
{
total
.
Add
(
total
,
tx
.
Value
())
if
pool
.
currentState
()
.
GetBalance
(
from
)
.
Cmp
(
total
)
<
0
{
return
ErrInsufficientFunds
return
ErrInsufficientFunds
}
}
// Should supply enough intrinsic gas
// Should supply enough intrinsic gas
if
tx
.
Gas
Limit
.
Cmp
(
IntrinsicGas
(
tx
))
<
0
{
if
tx
.
Gas
()
.
Cmp
(
IntrinsicGas
(
tx
))
<
0
{
return
ErrIntrinsicGas
return
ErrIntrinsicGas
}
}
...
@@ -238,7 +236,7 @@ func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Trans
...
@@ -238,7 +236,7 @@ func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Trans
// Increment the nonce on the pending state. This can only happen if
// Increment the nonce on the pending state. This can only happen if
// the nonce is +1 to the previous one.
// the nonce is +1 to the previous one.
pool
.
pendingState
.
SetNonce
(
addr
,
tx
.
AccountNonce
+
1
)
pool
.
pendingState
.
SetNonce
(
addr
,
tx
.
Nonce
()
+
1
)
// Notify the subscribers. This event is posted in a goroutine
// Notify the subscribers. This event is posted in a goroutine
// because it's possible that somewhere during the post "Remove transaction"
// because it's possible that somewhere during the post "Remove transaction"
// gets called which will then wait for the global tx pool lock and deadlock.
// gets called which will then wait for the global tx pool lock and deadlock.
...
@@ -341,7 +339,7 @@ func (pool *TxPool) checkQueue() {
...
@@ -341,7 +339,7 @@ func (pool *TxPool) checkQueue() {
trueNonce
:=
pool
.
currentState
()
.
GetNonce
(
address
)
trueNonce
:=
pool
.
currentState
()
.
GetNonce
(
address
)
addq
:=
addq
[
:
0
]
addq
:=
addq
[
:
0
]
for
hash
,
tx
:=
range
txs
{
for
hash
,
tx
:=
range
txs
{
if
tx
.
AccountNonce
<
trueNonce
{
if
tx
.
Nonce
()
<
trueNonce
{
// Drop queued transactions whose nonce is lower than
// Drop queued transactions whose nonce is lower than
// the account nonce because they have been processed.
// the account nonce because they have been processed.
delete
(
txs
,
hash
)
delete
(
txs
,
hash
)
...
@@ -362,8 +360,7 @@ func (pool *TxPool) checkQueue() {
...
@@ -362,8 +360,7 @@ func (pool *TxPool) checkQueue() {
delete
(
pool
.
queue
[
address
],
e
.
hash
)
delete
(
pool
.
queue
[
address
],
e
.
hash
)
continue
continue
}
}
if
e
.
Nonce
()
>
guessedNonce
{
if
e
.
AccountNonce
>
guessedNonce
{
break
break
}
}
delete
(
txs
,
e
.
hash
)
delete
(
txs
,
e
.
hash
)
...
@@ -418,4 +415,4 @@ type txQueueEntry struct {
...
@@ -418,4 +415,4 @@ type txQueueEntry struct {
func
(
q
txQueue
)
Len
()
int
{
return
len
(
q
)
}
func
(
q
txQueue
)
Len
()
int
{
return
len
(
q
)
}
func
(
q
txQueue
)
Swap
(
i
,
j
int
)
{
q
[
i
],
q
[
j
]
=
q
[
j
],
q
[
i
]
}
func
(
q
txQueue
)
Swap
(
i
,
j
int
)
{
q
[
i
],
q
[
j
]
=
q
[
j
],
q
[
i
]
}
func
(
q
txQueue
)
Less
(
i
,
j
int
)
bool
{
return
q
[
i
]
.
AccountNonce
<
q
[
j
]
.
AccountNonce
}
func
(
q
txQueue
)
Less
(
i
,
j
int
)
bool
{
return
q
[
i
]
.
Nonce
()
<
q
[
j
]
.
Nonce
()
}
core/transaction_pool_test.go
View file @
654564e1
...
@@ -13,8 +13,9 @@ import (
...
@@ -13,8 +13,9 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event"
)
)
func
transaction
()
*
types
.
Transaction
{
func
transaction
(
nonce
uint64
,
gaslimit
*
big
.
Int
,
key
*
ecdsa
.
PrivateKey
)
*
types
.
Transaction
{
return
types
.
NewTransactionMessage
(
common
.
Address
{},
big
.
NewInt
(
100
),
big
.
NewInt
(
100
),
big
.
NewInt
(
100
),
nil
)
tx
,
_
:=
types
.
NewTransaction
(
nonce
,
common
.
Address
{},
big
.
NewInt
(
100
),
gaslimit
,
big
.
NewInt
(
1
),
nil
)
.
SignECDSA
(
key
)
return
tx
}
}
func
setupTxPool
()
(
*
TxPool
,
*
ecdsa
.
PrivateKey
)
{
func
setupTxPool
()
(
*
TxPool
,
*
ecdsa
.
PrivateKey
)
{
...
@@ -29,43 +30,34 @@ func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
...
@@ -29,43 +30,34 @@ func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
func
TestInvalidTransactions
(
t
*
testing
.
T
)
{
func
TestInvalidTransactions
(
t
*
testing
.
T
)
{
pool
,
key
:=
setupTxPool
()
pool
,
key
:=
setupTxPool
()
tx
:=
transaction
()
tx
:=
transaction
(
0
,
big
.
NewInt
(
100
),
key
)
tx
.
SignECDSA
(
key
)
if
err
:=
pool
.
Add
(
tx
);
err
!=
ErrNonExistentAccount
{
err
:=
pool
.
Add
(
tx
)
if
err
!=
ErrNonExistentAccount
{
t
.
Error
(
"expected"
,
ErrNonExistentAccount
)
t
.
Error
(
"expected"
,
ErrNonExistentAccount
)
}
}
from
,
_
:=
tx
.
From
()
from
,
_
:=
tx
.
From
()
pool
.
currentState
()
.
AddBalance
(
from
,
big
.
NewInt
(
1
))
pool
.
currentState
()
.
AddBalance
(
from
,
big
.
NewInt
(
1
))
err
=
pool
.
Add
(
tx
)
if
err
:=
pool
.
Add
(
tx
);
err
!=
ErrInsufficientFunds
{
if
err
!=
ErrInsufficientFunds
{
t
.
Error
(
"expected"
,
ErrInsufficientFunds
)
t
.
Error
(
"expected"
,
ErrInsufficientFunds
)
}
}
balance
:=
new
(
big
.
Int
)
.
Add
(
tx
.
Value
(),
new
(
big
.
Int
)
.
Mul
(
tx
.
Gas
(),
tx
.
GasPrice
()))
balance
:=
new
(
big
.
Int
)
.
Add
(
tx
.
Value
(),
new
(
big
.
Int
)
.
Mul
(
tx
.
Gas
(),
tx
.
GasPrice
()))
pool
.
currentState
()
.
AddBalance
(
from
,
balance
)
pool
.
currentState
()
.
AddBalance
(
from
,
balance
)
err
=
pool
.
Add
(
tx
)
if
err
:=
pool
.
Add
(
tx
);
err
!=
ErrIntrinsicGas
{
if
err
!=
ErrIntrinsicGas
{
t
.
Error
(
"expected"
,
ErrIntrinsicGas
,
"got"
,
err
)
t
.
Error
(
"expected"
,
ErrIntrinsicGas
,
"got"
,
err
)
}
}
pool
.
currentState
()
.
SetNonce
(
from
,
1
)
pool
.
currentState
()
.
SetNonce
(
from
,
1
)
pool
.
currentState
()
.
AddBalance
(
from
,
big
.
NewInt
(
0xffffffffffffff
))
pool
.
currentState
()
.
AddBalance
(
from
,
big
.
NewInt
(
0xffffffffffffff
))
tx
.
GasLimit
=
big
.
NewInt
(
100000
)
tx
=
transaction
(
0
,
big
.
NewInt
(
100000
),
key
)
tx
.
Price
=
big
.
NewInt
(
1
)
if
err
:=
pool
.
Add
(
tx
);
err
!=
ErrNonce
{
tx
.
SignECDSA
(
key
)
err
=
pool
.
Add
(
tx
)
if
err
!=
ErrNonce
{
t
.
Error
(
"expected"
,
ErrNonce
)
t
.
Error
(
"expected"
,
ErrNonce
)
}
}
}
}
func
TestTransactionQueue
(
t
*
testing
.
T
)
{
func
TestTransactionQueue
(
t
*
testing
.
T
)
{
pool
,
key
:=
setupTxPool
()
pool
,
key
:=
setupTxPool
()
tx
:=
transaction
()
tx
:=
transaction
(
0
,
big
.
NewInt
(
100
),
key
)
tx
.
SignECDSA
(
key
)
from
,
_
:=
tx
.
From
()
from
,
_
:=
tx
.
From
()
pool
.
currentState
()
.
AddBalance
(
from
,
big
.
NewInt
(
1
))
pool
.
currentState
()
.
AddBalance
(
from
,
big
.
NewInt
(
1
))
pool
.
queueTx
(
tx
.
Hash
(),
tx
)
pool
.
queueTx
(
tx
.
Hash
(),
tx
)
...
@@ -75,9 +67,7 @@ func TestTransactionQueue(t *testing.T) {
...
@@ -75,9 +67,7 @@ func TestTransactionQueue(t *testing.T) {
t
.
Error
(
"expected valid txs to be 1 is"
,
len
(
pool
.
pending
))
t
.
Error
(
"expected valid txs to be 1 is"
,
len
(
pool
.
pending
))
}
}
tx
=
transaction
()
tx
=
transaction
(
1
,
big
.
NewInt
(
100
),
key
)
tx
.
SetNonce
(
1
)
tx
.
SignECDSA
(
key
)
from
,
_
=
tx
.
From
()
from
,
_
=
tx
.
From
()
pool
.
currentState
()
.
SetNonce
(
from
,
2
)
pool
.
currentState
()
.
SetNonce
(
from
,
2
)
pool
.
queueTx
(
tx
.
Hash
(),
tx
)
pool
.
queueTx
(
tx
.
Hash
(),
tx
)
...
@@ -91,12 +81,9 @@ func TestTransactionQueue(t *testing.T) {
...
@@ -91,12 +81,9 @@ func TestTransactionQueue(t *testing.T) {
}
}
pool
,
key
=
setupTxPool
()
pool
,
key
=
setupTxPool
()
tx1
,
tx2
,
tx3
:=
transaction
(),
transaction
(),
transaction
()
tx1
:=
transaction
(
0
,
big
.
NewInt
(
100
),
key
)
tx2
.
SetNonce
(
10
)
tx2
:=
transaction
(
10
,
big
.
NewInt
(
100
),
key
)
tx3
.
SetNonce
(
11
)
tx3
:=
transaction
(
11
,
big
.
NewInt
(
100
),
key
)
tx1
.
SignECDSA
(
key
)
tx2
.
SignECDSA
(
key
)
tx3
.
SignECDSA
(
key
)
pool
.
queueTx
(
tx1
.
Hash
(),
tx1
)
pool
.
queueTx
(
tx1
.
Hash
(),
tx1
)
pool
.
queueTx
(
tx2
.
Hash
(),
tx2
)
pool
.
queueTx
(
tx2
.
Hash
(),
tx2
)
pool
.
queueTx
(
tx3
.
Hash
(),
tx3
)
pool
.
queueTx
(
tx3
.
Hash
(),
tx3
)
...
@@ -114,8 +101,7 @@ func TestTransactionQueue(t *testing.T) {
...
@@ -114,8 +101,7 @@ func TestTransactionQueue(t *testing.T) {
func
TestRemoveTx
(
t
*
testing
.
T
)
{
func
TestRemoveTx
(
t
*
testing
.
T
)
{
pool
,
key
:=
setupTxPool
()
pool
,
key
:=
setupTxPool
()
tx
:=
transaction
()
tx
:=
transaction
(
0
,
big
.
NewInt
(
100
),
key
)
tx
.
SignECDSA
(
key
)
from
,
_
:=
tx
.
From
()
from
,
_
:=
tx
.
From
()
pool
.
currentState
()
.
AddBalance
(
from
,
big
.
NewInt
(
1
))
pool
.
currentState
()
.
AddBalance
(
from
,
big
.
NewInt
(
1
))
pool
.
queueTx
(
tx
.
Hash
(),
tx
)
pool
.
queueTx
(
tx
.
Hash
(),
tx
)
...
@@ -142,13 +128,10 @@ func TestRemoveTx(t *testing.T) {
...
@@ -142,13 +128,10 @@ func TestRemoveTx(t *testing.T) {
func
TestNegativeValue
(
t
*
testing
.
T
)
{
func
TestNegativeValue
(
t
*
testing
.
T
)
{
pool
,
key
:=
setupTxPool
()
pool
,
key
:=
setupTxPool
()
tx
:=
transaction
()
tx
,
_
:=
types
.
NewTransaction
(
0
,
common
.
Address
{},
big
.
NewInt
(
-
1
),
big
.
NewInt
(
100
),
big
.
NewInt
(
1
),
nil
)
.
SignECDSA
(
key
)
tx
.
Value
()
.
Set
(
big
.
NewInt
(
-
1
))
tx
.
SignECDSA
(
key
)
from
,
_
:=
tx
.
From
()
from
,
_
:=
tx
.
From
()
pool
.
currentState
()
.
AddBalance
(
from
,
big
.
NewInt
(
1
))
pool
.
currentState
()
.
AddBalance
(
from
,
big
.
NewInt
(
1
))
err
:=
pool
.
Add
(
tx
)
if
err
:=
pool
.
Add
(
tx
);
err
!=
ErrNegativeValue
{
if
err
!=
ErrNegativeValue
{
t
.
Error
(
"expected"
,
ErrNegativeValue
,
"got"
,
err
)
t
.
Error
(
"expected"
,
ErrNegativeValue
,
"got"
,
err
)
}
}
}
}
...
@@ -165,20 +148,15 @@ func TestTransactionChainFork(t *testing.T) {
...
@@ -165,20 +148,15 @@ func TestTransactionChainFork(t *testing.T) {
}
}
resetState
()
resetState
()
tx
:=
transaction
()
tx
:=
transaction
(
0
,
big
.
NewInt
(
100000
),
key
)
tx
.
GasLimit
=
big
.
NewInt
(
100000
)
if
err
:=
pool
.
add
(
tx
);
err
!=
nil
{
tx
.
SignECDSA
(
key
)
err
:=
pool
.
add
(
tx
)
if
err
!=
nil
{
t
.
Error
(
"didn't expect error"
,
err
)
t
.
Error
(
"didn't expect error"
,
err
)
}
}
pool
.
RemoveTransactions
([]
*
types
.
Transaction
{
tx
})
pool
.
RemoveTransactions
([]
*
types
.
Transaction
{
tx
})
// reset the pool's internal state
// reset the pool's internal state
resetState
()
resetState
()
err
=
pool
.
add
(
tx
)
if
err
:=
pool
.
add
(
tx
);
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
(
"didn't expect error"
,
err
)
t
.
Error
(
"didn't expect error"
,
err
)
}
}
}
}
...
@@ -195,24 +173,14 @@ func TestTransactionDoubleNonce(t *testing.T) {
...
@@ -195,24 +173,14 @@ func TestTransactionDoubleNonce(t *testing.T) {
}
}
resetState
()
resetState
()
tx
:=
transaction
()
tx
:=
transaction
(
0
,
big
.
NewInt
(
100000
),
key
)
tx
.
GasLimit
=
big
.
NewInt
(
100000
)
tx2
:=
transaction
(
0
,
big
.
NewInt
(
1000000
),
key
)
tx
.
SignECDSA
(
key
)
if
err
:=
pool
.
add
(
tx
);
err
!=
nil
{
err
:=
pool
.
add
(
tx
)
if
err
!=
nil
{
t
.
Error
(
"didn't expect error"
,
err
)
t
.
Error
(
"didn't expect error"
,
err
)
}
}
if
err
:=
pool
.
add
(
tx2
);
err
!=
nil
{
tx2
:=
transaction
()
tx2
.
GasLimit
=
big
.
NewInt
(
1000000
)
tx2
.
SignECDSA
(
key
)
err
=
pool
.
add
(
tx2
)
if
err
!=
nil
{
t
.
Error
(
"didn't expect error"
,
err
)
t
.
Error
(
"didn't expect error"
,
err
)
}
}
if
len
(
pool
.
pending
)
!=
2
{
if
len
(
pool
.
pending
)
!=
2
{
t
.
Error
(
"expected 2 pending txs. Got"
,
len
(
pool
.
pending
))
t
.
Error
(
"expected 2 pending txs. Got"
,
len
(
pool
.
pending
))
}
}
...
@@ -222,20 +190,13 @@ func TestMissingNonce(t *testing.T) {
...
@@ -222,20 +190,13 @@ func TestMissingNonce(t *testing.T) {
pool
,
key
:=
setupTxPool
()
pool
,
key
:=
setupTxPool
()
addr
:=
crypto
.
PubkeyToAddress
(
key
.
PublicKey
)
addr
:=
crypto
.
PubkeyToAddress
(
key
.
PublicKey
)
pool
.
currentState
()
.
AddBalance
(
addr
,
big
.
NewInt
(
100000000000000
))
pool
.
currentState
()
.
AddBalance
(
addr
,
big
.
NewInt
(
100000000000000
))
tx
:=
transaction
()
tx
:=
transaction
(
1
,
big
.
NewInt
(
100000
),
key
)
tx
.
AccountNonce
=
1
if
err
:=
pool
.
add
(
tx
);
err
!=
nil
{
tx
.
GasLimit
=
big
.
NewInt
(
100000
)
tx
.
SignECDSA
(
key
)
err
:=
pool
.
add
(
tx
)
if
err
!=
nil
{
t
.
Error
(
"didn't expect error"
,
err
)
t
.
Error
(
"didn't expect error"
,
err
)
}
}
if
len
(
pool
.
pending
)
!=
0
{
if
len
(
pool
.
pending
)
!=
0
{
t
.
Error
(
"expected 0 pending transactions, got"
,
len
(
pool
.
pending
))
t
.
Error
(
"expected 0 pending transactions, got"
,
len
(
pool
.
pending
))
}
}
if
len
(
pool
.
queue
[
addr
])
!=
1
{
if
len
(
pool
.
queue
[
addr
])
!=
1
{
t
.
Error
(
"expected 1 queued transaction, got"
,
len
(
pool
.
queue
[
addr
]))
t
.
Error
(
"expected 1 queued transaction, got"
,
len
(
pool
.
queue
[
addr
]))
}
}
...
...
core/types/block_test.go
View file @
654564e1
...
@@ -13,7 +13,6 @@ import (
...
@@ -13,7 +13,6 @@ import (
// from bcValidBlockTest.json, "SimpleTx"
// from bcValidBlockTest.json, "SimpleTx"
func
TestBlockEncoding
(
t
*
testing
.
T
)
{
func
TestBlockEncoding
(
t
*
testing
.
T
)
{
blockEnc
:=
common
.
FromHex
(
"f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0"
)
blockEnc
:=
common
.
FromHex
(
"f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0"
)
var
block
Block
var
block
Block
if
err
:=
rlp
.
DecodeBytes
(
blockEnc
,
&
block
);
err
!=
nil
{
if
err
:=
rlp
.
DecodeBytes
(
blockEnc
,
&
block
);
err
!=
nil
{
t
.
Fatal
(
"decode error: "
,
err
)
t
.
Fatal
(
"decode error: "
,
err
)
...
@@ -35,20 +34,10 @@ func TestBlockEncoding(t *testing.T) {
...
@@ -35,20 +34,10 @@ func TestBlockEncoding(t *testing.T) {
check
(
"Time"
,
block
.
Time
(),
int64
(
1426516743
))
check
(
"Time"
,
block
.
Time
(),
int64
(
1426516743
))
check
(
"Size"
,
block
.
Size
(),
common
.
StorageSize
(
len
(
blockEnc
)))
check
(
"Size"
,
block
.
Size
(),
common
.
StorageSize
(
len
(
blockEnc
)))
to
:=
common
.
HexToAddress
(
"095e7baea6a6c7c4c2dfeb977efac326af552d87"
)
tx1
:=
NewTransaction
(
0
,
common
.
HexToAddress
(
"095e7baea6a6c7c4c2dfeb977efac326af552d87"
),
big
.
NewInt
(
10
),
big
.
NewInt
(
50000
),
big
.
NewInt
(
10
),
nil
)
check
(
"Transactions"
,
block
.
Transactions
(),
Transactions
{
tx1
,
_
=
tx1
.
WithSignature
(
common
.
Hex2Bytes
(
"9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100"
))
{
check
(
"len(Transactions)"
,
len
(
block
.
Transactions
()),
1
)
Payload
:
[]
byte
{},
check
(
"Transactions[0].Hash"
,
block
.
Transactions
()[
0
]
.
Hash
(),
tx1
.
Hash
())
Amount
:
big
.
NewInt
(
10
),
Price
:
big
.
NewInt
(
10
),
GasLimit
:
big
.
NewInt
(
50000
),
AccountNonce
:
0
,
V
:
27
,
R
:
common
.
String2Big
(
"0x9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f"
),
S
:
common
.
String2Big
(
"0x8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1"
),
Recipient
:
&
to
,
},
})
ourBlockEnc
,
err
:=
rlp
.
EncodeToBytes
(
&
block
)
ourBlockEnc
,
err
:=
rlp
.
EncodeToBytes
(
&
block
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
core/types/transaction.go
View file @
654564e1
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"crypto/ecdsa"
"crypto/ecdsa"
"errors"
"errors"
"fmt"
"fmt"
"io"
"math/big"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
...
@@ -18,38 +19,59 @@ func IsContractAddr(addr []byte) bool {
...
@@ -18,38 +19,59 @@ func IsContractAddr(addr []byte) bool {
}
}
type
Transaction
struct
{
type
Transaction
struct
{
AccountNonce
uint64
data
txdata
Price
*
big
.
Int
}
GasLimit
*
big
.
Int
Recipient
*
common
.
Address
`rlp:"nil"`
// nil means contract creation
type
txdata
struct
{
Amount
*
big
.
Int
AccountNonce
uint64
Payload
[]
byte
Price
,
GasLimit
*
big
.
Int
V
byte
Recipient
*
common
.
Address
`rlp:"nil"`
// nil means contract creation
R
,
S
*
big
.
Int
Amount
*
big
.
Int
}
Payload
[]
byte
V
byte
// signature
func
NewContractCreationTx
(
amount
,
gasLimit
,
gasPrice
*
big
.
Int
,
data
[]
byte
)
*
Transaction
{
R
,
S
*
big
.
Int
// signature
return
&
Transaction
{
Recipient
:
nil
,
Amount
:
amount
,
GasLimit
:
gasLimit
,
Price
:
gasPrice
,
Payload
:
data
,
R
:
new
(
big
.
Int
),
S
:
new
(
big
.
Int
),
}
}
}
func
NewTransactionMessage
(
to
common
.
Address
,
amount
,
gasAmount
,
gasPrice
*
big
.
Int
,
data
[]
byte
)
*
Transaction
{
func
NewContractCreation
(
nonce
uint64
,
amount
,
gasLimit
,
gasPrice
*
big
.
Int
,
data
[]
byte
)
*
Transaction
{
return
&
Transaction
{
if
len
(
data
)
>
0
{
Recipient
:
&
to
,
data
=
common
.
CopyBytes
(
data
)
Amount
:
amount
,
}
GasLimit
:
gasAmount
,
return
&
Transaction
{
data
:
txdata
{
Price
:
gasPrice
,
AccountNonce
:
nonce
,
Payload
:
data
,
Recipient
:
nil
,
R
:
new
(
big
.
Int
),
Amount
:
new
(
big
.
Int
)
.
Set
(
amount
),
S
:
new
(
big
.
Int
),
GasLimit
:
new
(
big
.
Int
)
.
Set
(
gasLimit
),
Price
:
new
(
big
.
Int
)
.
Set
(
gasPrice
),
Payload
:
data
,
R
:
new
(
big
.
Int
),
S
:
new
(
big
.
Int
),
}}
}
func
NewTransaction
(
nonce
uint64
,
to
common
.
Address
,
amount
,
gasLimit
,
gasPrice
*
big
.
Int
,
data
[]
byte
)
*
Transaction
{
if
len
(
data
)
>
0
{
data
=
common
.
CopyBytes
(
data
)
}
d
:=
txdata
{
AccountNonce
:
nonce
,
Recipient
:
&
to
,
Payload
:
data
,
Amount
:
new
(
big
.
Int
),
GasLimit
:
new
(
big
.
Int
),
Price
:
new
(
big
.
Int
),
R
:
new
(
big
.
Int
),
S
:
new
(
big
.
Int
),
}
}
if
amount
!=
nil
{
d
.
Amount
.
Set
(
amount
)
}
if
gasLimit
!=
nil
{
d
.
GasLimit
.
Set
(
gasLimit
)
}
if
gasPrice
!=
nil
{
d
.
Price
.
Set
(
gasPrice
)
}
return
&
Transaction
{
data
:
d
}
}
}
func
NewTransactionFromBytes
(
data
[]
byte
)
*
Transaction
{
func
NewTransactionFromBytes
(
data
[]
byte
)
*
Transaction
{
...
@@ -61,112 +83,110 @@ func NewTransactionFromBytes(data []byte) *Transaction {
...
@@ -61,112 +83,110 @@ func NewTransactionFromBytes(data []byte) *Transaction {
return
tx
return
tx
}
}
func
(
tx
*
Transaction
)
Hash
()
common
.
Hash
{
func
(
tx
*
Transaction
)
EncodeRLP
(
w
io
.
Writer
)
error
{
return
rlpHash
([]
interface
{}{
return
rlp
.
Encode
(
w
,
&
tx
.
data
)
tx
.
AccountNonce
,
tx
.
Price
,
tx
.
GasLimit
,
tx
.
Recipient
,
tx
.
Amount
,
tx
.
Payload
,
})
}
// Size returns the encoded RLP size of tx.
func
(
self
*
Transaction
)
Size
()
common
.
StorageSize
{
c
:=
writeCounter
(
0
)
rlp
.
Encode
(
&
c
,
self
)
return
common
.
StorageSize
(
c
)
}
func
(
self
*
Transaction
)
Data
()
[]
byte
{
return
self
.
Payload
}
}
func
(
self
*
Transaction
)
Gas
()
*
big
.
Int
{
func
(
tx
*
Transaction
)
DecodeRLP
(
s
*
rlp
.
Stream
)
error
{
return
s
elf
.
GasLimit
return
s
.
Decode
(
&
tx
.
data
)
}
}
func
(
self
*
Transaction
)
GasPrice
()
*
big
.
Int
{
func
(
tx
*
Transaction
)
Data
()
[]
byte
{
return
common
.
CopyBytes
(
tx
.
data
.
Payload
)
}
return
self
.
Price
func
(
tx
*
Transaction
)
Gas
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
tx
.
data
.
GasLimit
)
}
}
func
(
tx
*
Transaction
)
GasPrice
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
tx
.
data
.
Price
)
}
func
(
tx
*
Transaction
)
Value
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Set
(
tx
.
data
.
Amount
)
}
func
(
tx
*
Transaction
)
Nonce
()
uint64
{
return
tx
.
data
.
AccountNonce
}
func
(
self
*
Transaction
)
Value
()
*
big
.
Int
{
func
(
tx
*
Transaction
)
To
()
*
common
.
Address
{
return
self
.
Amount
if
tx
.
data
.
Recipient
==
nil
{
return
nil
}
else
{
to
:=
*
tx
.
data
.
Recipient
return
&
to
}
}
}
func
(
self
*
Transaction
)
Nonce
()
uint64
{
func
(
tx
*
Transaction
)
Hash
()
common
.
Hash
{
return
self
.
AccountNonce
v
:=
rlpHash
([]
interface
{}{
tx
.
data
.
AccountNonce
,
tx
.
data
.
Price
,
tx
.
data
.
GasLimit
,
tx
.
data
.
Recipient
,
tx
.
data
.
Amount
,
tx
.
data
.
Payload
,
})
return
v
}
}
func
(
self
*
Transaction
)
SetNonce
(
AccountNonce
uint64
)
{
func
(
tx
*
Transaction
)
Size
()
common
.
StorageSize
{
self
.
AccountNonce
=
AccountNonce
v
,
_
,
_
:=
rlp
.
EncodeToReader
(
&
tx
.
data
)
return
common
.
StorageSize
(
v
)
}
}
func
(
self
*
Transaction
)
From
()
(
common
.
Address
,
error
)
{
func
(
tx
*
Transaction
)
From
()
(
common
.
Address
,
error
)
{
pubkey
,
err
:=
self
.
PublicKey
()
pubkey
,
err
:=
tx
.
PublicKey
()
if
err
!=
nil
{
if
err
!=
nil
{
return
common
.
Address
{},
err
return
common
.
Address
{},
err
}
}
var
addr
common
.
Address
var
addr
common
.
Address
copy
(
addr
[
:
],
crypto
.
Sha3
(
pubkey
[
1
:
])[
12
:
])
copy
(
addr
[
:
],
crypto
.
Sha3
(
pubkey
[
1
:
])[
12
:
])
return
addr
,
nil
return
addr
,
nil
}
}
//
To returns the recipient of the transaction
.
//
Cost returns amount + gasprice * gaslimit
.
// If transaction is a contract creation (with no recipient address)
func
(
tx
*
Transaction
)
Cost
()
*
big
.
Int
{
// To returns nil.
total
:=
new
(
big
.
Int
)
.
Mul
(
tx
.
data
.
Price
,
tx
.
data
.
GasLimit
)
func
(
tx
*
Transaction
)
To
()
*
common
.
Address
{
total
.
Add
(
total
,
tx
.
data
.
Amount
)
return
t
x
.
Recipient
return
t
otal
}
}
func
(
tx
*
Transaction
)
GetSignatureValues
()
(
v
byte
,
r
[]
byte
,
s
[]
byte
)
{
func
(
tx
*
Transaction
)
SignatureValues
()
(
v
byte
,
r
*
big
.
Int
,
s
*
big
.
Int
)
{
v
=
byte
(
tx
.
V
)
return
tx
.
data
.
V
,
new
(
big
.
Int
)
.
Set
(
tx
.
data
.
R
),
new
(
big
.
Int
)
.
Set
(
tx
.
data
.
S
)
r
=
common
.
LeftPadBytes
(
tx
.
R
.
Bytes
(),
32
)
s
=
common
.
LeftPadBytes
(
tx
.
S
.
Bytes
(),
32
)
return
}
}
func
(
tx
*
Transaction
)
PublicKey
()
([]
byte
,
error
)
{
func
(
tx
*
Transaction
)
PublicKey
()
([]
byte
,
error
)
{
if
!
crypto
.
ValidateSignatureValues
(
tx
.
V
,
tx
.
R
,
tx
.
S
)
{
if
!
crypto
.
ValidateSignatureValues
(
tx
.
data
.
V
,
tx
.
data
.
R
,
tx
.
data
.
S
)
{
return
nil
,
errors
.
New
(
"invalid v, r, s values"
)
return
nil
,
errors
.
New
(
"invalid v, r, s values"
)
}
}
hash
:=
tx
.
Hash
()
// encode the signature in uncompressed format
v
,
r
,
s
:=
tx
.
GetSignatureValues
()
r
,
s
:=
tx
.
data
.
R
.
Bytes
(),
tx
.
data
.
S
.
Bytes
()
sig
:=
append
(
r
,
s
...
)
sig
:=
make
([]
byte
,
65
)
sig
=
append
(
sig
,
v
-
27
)
copy
(
sig
[
32
-
len
(
r
)
:
32
],
r
)
copy
(
sig
[
64
-
len
(
s
)
:
64
],
s
)
sig
[
64
]
=
tx
.
data
.
V
-
27
p
,
err
:=
crypto
.
SigToPub
(
hash
[
:
],
sig
)
// recover the public key from the signature
hash
:=
tx
.
Hash
()
pub
,
err
:=
crypto
.
Ecrecover
(
hash
[
:
],
sig
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Could not get pubkey from signature: "
,
err
)
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Could not get pubkey from signature: "
,
err
)
return
nil
,
err
return
nil
,
err
}
}
if
len
(
pub
)
==
0
||
pub
[
0
]
!=
4
{
pubkey
:=
crypto
.
FromECDSAPub
(
p
)
if
len
(
pubkey
)
==
0
||
pubkey
[
0
]
!=
4
{
return
nil
,
errors
.
New
(
"invalid public key"
)
return
nil
,
errors
.
New
(
"invalid public key"
)
}
}
return
pub
key
,
nil
return
pub
,
nil
}
}
func
(
tx
*
Transaction
)
SetSignatureValues
(
sig
[]
byte
)
error
{
func
(
tx
*
Transaction
)
WithSignature
(
sig
[]
byte
)
(
*
Transaction
,
error
)
{
tx
.
R
=
common
.
Bytes2Big
(
sig
[
:
32
])
if
len
(
sig
)
!=
65
{
tx
.
S
=
common
.
Bytes2Big
(
sig
[
32
:
64
])
panic
(
fmt
.
Sprintf
(
"wrong size for signature: got %d, want 65"
,
len
(
sig
)))
tx
.
V
=
sig
[
64
]
+
27
}
return
nil
cpy
:=
&
Transaction
{
data
:
tx
.
data
}
cpy
.
data
.
R
=
new
(
big
.
Int
)
.
SetBytes
(
sig
[
:
32
])
cpy
.
data
.
S
=
new
(
big
.
Int
)
.
SetBytes
(
sig
[
32
:
64
])
cpy
.
data
.
V
=
sig
[
64
]
+
27
return
cpy
,
nil
}
}
func
(
tx
*
Transaction
)
SignECDSA
(
prv
*
ecdsa
.
PrivateKey
)
error
{
func
(
tx
*
Transaction
)
SignECDSA
(
prv
*
ecdsa
.
PrivateKey
)
(
*
Transaction
,
error
)
{
h
:=
tx
.
Hash
()
h
:=
tx
.
Hash
()
sig
,
err
:=
crypto
.
Sign
(
h
[
:
],
prv
)
sig
,
err
:=
crypto
.
Sign
(
h
[
:
],
prv
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
nil
,
err
}
}
tx
.
SetSignatureValues
(
sig
)
return
tx
.
WithSignature
(
sig
)
return
nil
}
// TODO: remove
func
(
tx
*
Transaction
)
RlpData
()
interface
{}
{
data
:=
[]
interface
{}{
tx
.
AccountNonce
,
tx
.
Price
,
tx
.
GasLimit
,
tx
.
Recipient
,
tx
.
Amount
,
tx
.
Payload
}
return
append
(
data
,
tx
.
V
,
tx
.
R
.
Bytes
(),
tx
.
S
.
Bytes
())
}
}
func
(
tx
*
Transaction
)
String
()
string
{
func
(
tx
*
Transaction
)
String
()
string
{
...
@@ -176,12 +196,12 @@ func (tx *Transaction) String() string {
...
@@ -176,12 +196,12 @@ func (tx *Transaction) String() string {
}
else
{
}
else
{
from
=
fmt
.
Sprintf
(
"%x"
,
f
[
:
])
from
=
fmt
.
Sprintf
(
"%x"
,
f
[
:
])
}
}
if
t
:=
tx
.
To
();
t
==
nil
{
if
t
x
.
data
.
Recipien
t
==
nil
{
to
=
"[contract creation]"
to
=
"[contract creation]"
}
else
{
}
else
{
to
=
fmt
.
Sprintf
(
"%x"
,
t
[
:
])
to
=
fmt
.
Sprintf
(
"%x"
,
t
x
.
data
.
Recipient
[
:
])
}
}
enc
,
_
:=
rlp
.
EncodeToBytes
(
tx
)
enc
,
_
:=
rlp
.
EncodeToBytes
(
&
tx
.
data
)
return
fmt
.
Sprintf
(
`
return
fmt
.
Sprintf
(
`
TX(%x)
TX(%x)
Contract: %v
Contract: %v
...
@@ -198,36 +218,24 @@ func (tx *Transaction) String() string {
...
@@ -198,36 +218,24 @@ func (tx *Transaction) String() string {
Hex: %x
Hex: %x
`
,
`
,
tx
.
Hash
(),
tx
.
Hash
(),
len
(
tx
.
Recipient
)
==
0
,
len
(
tx
.
data
.
Recipient
)
==
0
,
from
,
from
,
to
,
to
,
tx
.
AccountNonce
,
tx
.
data
.
AccountNonce
,
tx
.
Price
,
tx
.
data
.
Price
,
tx
.
GasLimit
,
tx
.
data
.
GasLimit
,
tx
.
Amount
,
tx
.
data
.
Amount
,
tx
.
Payload
,
tx
.
data
.
Payload
,
tx
.
V
,
tx
.
data
.
V
,
tx
.
R
,
tx
.
data
.
R
,
tx
.
S
,
tx
.
data
.
S
,
enc
,
enc
,
)
)
}
}
// Transaction slice type for basic sorting
// Transaction slice type for basic sorting
.
type
Transactions
[]
*
Transaction
type
Transactions
[]
*
Transaction
// TODO: remove
func
(
self
Transactions
)
RlpData
()
interface
{}
{
// Marshal the transactions of this block
enc
:=
make
([]
interface
{},
len
(
self
))
for
i
,
tx
:=
range
self
{
// Cast it to a string (safe)
enc
[
i
]
=
tx
.
RlpData
()
}
return
enc
}
func
(
s
Transactions
)
Len
()
int
{
return
len
(
s
)
}
func
(
s
Transactions
)
Len
()
int
{
return
len
(
s
)
}
func
(
s
Transactions
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
func
(
s
Transactions
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
...
@@ -239,5 +247,5 @@ func (s Transactions) GetRlp(i int) []byte {
...
@@ -239,5 +247,5 @@ func (s Transactions) GetRlp(i int) []byte {
type
TxByNonce
struct
{
Transactions
}
type
TxByNonce
struct
{
Transactions
}
func
(
s
TxByNonce
)
Less
(
i
,
j
int
)
bool
{
func
(
s
TxByNonce
)
Less
(
i
,
j
int
)
bool
{
return
s
.
Transactions
[
i
]
.
AccountNonce
<
s
.
Transactions
[
j
]
.
AccountNonce
return
s
.
Transactions
[
i
]
.
data
.
AccountNonce
<
s
.
Transactions
[
j
]
.
data
.
AccountNonce
}
}
core/types/transaction_test.go
View file @
654564e1
...
@@ -15,40 +15,35 @@ import (
...
@@ -15,40 +15,35 @@ import (
// at github.com/ethereum/tests.
// at github.com/ethereum/tests.
var
(
var
(
emptyTx
=
NewTransactionMessage
(
emptyTx
=
NewTransaction
(
0
,
common
.
HexToAddress
(
"095e7baea6a6c7c4c2dfeb977efac326af552d87"
),
common
.
HexToAddress
(
"095e7baea6a6c7c4c2dfeb977efac326af552d87"
),
big
.
NewInt
(
0
),
big
.
NewInt
(
0
),
big
.
NewInt
(
0
),
big
.
NewInt
(
0
),
big
.
NewInt
(
0
),
big
.
NewInt
(
0
),
nil
,
nil
,
)
)
rightvrsRecipient
=
common
.
HexToAddress
(
"b94f5374fce5edbc8e2a8697c15331677e6ebf0b"
)
rightvrsTx
,
_
=
NewTransaction
(
rightvrsTx
=
&
Transaction
{
3
,
Recipient
:
&
rightvrsRecipient
,
common
.
HexToAddress
(
"b94f5374fce5edbc8e2a8697c15331677e6ebf0b"
),
AccountNonce
:
3
,
big
.
NewInt
(
10
),
Price
:
big
.
NewInt
(
1
),
big
.
NewInt
(
2000
),
GasLimit
:
big
.
NewInt
(
2000
),
big
.
NewInt
(
1
),
Amount
:
big
.
NewInt
(
10
),
common
.
FromHex
(
"5544"
),
Payload
:
common
.
FromHex
(
"5544"
),
)
.
WithSignature
(
V
:
28
,
common
.
Hex2Bytes
(
"98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a301"
),
R
:
common
.
String2Big
(
"0x98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a"
),
)
S
:
common
.
String2Big
(
"0x8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3"
),
}
)
)
func
TestTransactionHash
(
t
*
testing
.
T
)
{
func
TestTransactionHash
(
t
*
testing
.
T
)
{
// "EmptyTransaction"
if
emptyTx
.
Hash
()
!=
common
.
HexToHash
(
"c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386"
)
{
if
emptyTx
.
Hash
()
!=
common
.
HexToHash
(
"c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386"
)
{
t
.
Errorf
(
"empty transaction hash mismatch, got %x"
,
emptyTx
.
Hash
())
t
.
Errorf
(
"empty transaction hash mismatch, got %x"
,
emptyTx
.
Hash
())
}
}
// "RightVRSTest"
if
rightvrsTx
.
Hash
()
!=
common
.
HexToHash
(
"fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a"
)
{
if
rightvrsTx
.
Hash
()
!=
common
.
HexToHash
(
"fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a"
)
{
t
.
Errorf
(
"RightVRS transaction hash mismatch, got %x"
,
rightvrsTx
.
Hash
())
t
.
Errorf
(
"RightVRS transaction hash mismatch, got %x"
,
rightvrsTx
.
Hash
())
}
}
}
}
func
TestTransactionEncode
(
t
*
testing
.
T
)
{
func
TestTransactionEncode
(
t
*
testing
.
T
)
{
// "RightVRSTest"
txb
,
err
:=
rlp
.
EncodeToBytes
(
rightvrsTx
)
txb
,
err
:=
rlp
.
EncodeToBytes
(
rightvrsTx
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"encode error: %v"
,
err
)
t
.
Fatalf
(
"encode error: %v"
,
err
)
...
@@ -72,19 +67,16 @@ func defaultTestKey() (*ecdsa.PrivateKey, common.Address) {
...
@@ -72,19 +67,16 @@ func defaultTestKey() (*ecdsa.PrivateKey, common.Address) {
func
TestRecipientEmpty
(
t
*
testing
.
T
)
{
func
TestRecipientEmpty
(
t
*
testing
.
T
)
{
_
,
addr
:=
defaultTestKey
()
_
,
addr
:=
defaultTestKey
()
tx
,
err
:=
decodeTx
(
common
.
Hex2Bytes
(
"f8498080808080011ca09b16de9d5bdee2cf56c28d16275a4da68cd30273e2525f3959f5d62557489921a0372ebd8fb3345f7db7b5a86d42e24d36e983e259b0664ceb8c227ec9af572f3d"
))
tx
,
err
:=
decodeTx
(
common
.
Hex2Bytes
(
"f8498080808080011ca09b16de9d5bdee2cf56c28d16275a4da68cd30273e2525f3959f5d62557489921a0372ebd8fb3345f7db7b5a86d42e24d36e983e259b0664ceb8c227ec9af572f3d"
))
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
(
err
)
t
.
Error
(
err
)
t
.
FailNow
()
t
.
FailNow
()
}
}
from
,
err
:=
tx
.
From
()
from
,
err
:=
tx
.
From
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
(
err
)
t
.
Error
(
err
)
t
.
FailNow
()
t
.
FailNow
()
}
}
if
addr
!=
from
{
if
addr
!=
from
{
t
.
Error
(
"derived address doesn't match"
)
t
.
Error
(
"derived address doesn't match"
)
}
}
...
...
eth/protocol_test.go
View file @
654564e1
...
@@ -234,7 +234,7 @@ func (pool *fakeTxPool) GetTransactions() types.Transactions {
...
@@ -234,7 +234,7 @@ func (pool *fakeTxPool) GetTransactions() types.Transactions {
func
newtx
(
from
*
crypto
.
Key
,
nonce
uint64
,
datasize
int
)
*
types
.
Transaction
{
func
newtx
(
from
*
crypto
.
Key
,
nonce
uint64
,
datasize
int
)
*
types
.
Transaction
{
data
:=
make
([]
byte
,
datasize
)
data
:=
make
([]
byte
,
datasize
)
tx
:=
types
.
NewTransaction
Message
(
common
.
Address
{},
big
.
NewInt
(
0
),
big
.
NewInt
(
100000
),
big
.
NewInt
(
0
),
data
)
tx
:=
types
.
NewTransaction
(
nonce
,
common
.
Address
{},
big
.
NewInt
(
0
),
big
.
NewInt
(
100000
),
big
.
NewInt
(
0
),
data
)
tx
.
SetNonce
(
nonce
)
tx
,
_
=
tx
.
SignECDSA
(
from
.
PrivateKey
)
return
tx
return
tx
}
}
tests/transaction_test_util.go
View file @
654564e1
...
@@ -152,54 +152,53 @@ func verifyTxFields(txTest TransactionTest, decodedTx *types.Transaction) (err e
...
@@ -152,54 +152,53 @@ func verifyTxFields(txTest TransactionTest, decodedTx *types.Transaction) (err e
}
}
expectedData
:=
mustConvertBytes
(
txTest
.
Transaction
.
Data
)
expectedData
:=
mustConvertBytes
(
txTest
.
Transaction
.
Data
)
if
!
bytes
.
Equal
(
expectedData
,
decodedTx
.
Payload
)
{
if
!
bytes
.
Equal
(
expectedData
,
decodedTx
.
Data
()
)
{
return
fmt
.
Errorf
(
"Tx input data mismatch: %#v %#v"
,
expectedData
,
decodedTx
.
Payload
)
return
fmt
.
Errorf
(
"Tx input data mismatch: %#v %#v"
,
expectedData
,
decodedTx
.
Data
()
)
}
}
expectedGasLimit
:=
mustConvertBigInt
(
txTest
.
Transaction
.
GasLimit
,
16
)
expectedGasLimit
:=
mustConvertBigInt
(
txTest
.
Transaction
.
GasLimit
,
16
)
if
expectedGasLimit
.
Cmp
(
decodedTx
.
Gas
Limit
)
!=
0
{
if
expectedGasLimit
.
Cmp
(
decodedTx
.
Gas
()
)
!=
0
{
return
fmt
.
Errorf
(
"GasLimit mismatch: %v %v"
,
expectedGasLimit
,
decodedTx
.
Gas
Limit
)
return
fmt
.
Errorf
(
"GasLimit mismatch: %v %v"
,
expectedGasLimit
,
decodedTx
.
Gas
()
)
}
}
expectedGasPrice
:=
mustConvertBigInt
(
txTest
.
Transaction
.
GasPrice
,
16
)
expectedGasPrice
:=
mustConvertBigInt
(
txTest
.
Transaction
.
GasPrice
,
16
)
if
expectedGasPrice
.
Cmp
(
decodedTx
.
Price
)
!=
0
{
if
expectedGasPrice
.
Cmp
(
decodedTx
.
GasPrice
()
)
!=
0
{
return
fmt
.
Errorf
(
"GasPrice mismatch: %v %v"
,
expectedGasPrice
,
decodedTx
.
Price
)
return
fmt
.
Errorf
(
"GasPrice mismatch: %v %v"
,
expectedGasPrice
,
decodedTx
.
GasPrice
()
)
}
}
expectedNonce
:=
mustConvertUint
(
txTest
.
Transaction
.
Nonce
,
16
)
expectedNonce
:=
mustConvertUint
(
txTest
.
Transaction
.
Nonce
,
16
)
if
expectedNonce
!=
decodedTx
.
AccountNonce
{
if
expectedNonce
!=
decodedTx
.
Nonce
()
{
return
fmt
.
Errorf
(
"Nonce mismatch: %v %v"
,
expectedNonce
,
decodedTx
.
AccountNonce
)
return
fmt
.
Errorf
(
"Nonce mismatch: %v %v"
,
expectedNonce
,
decodedTx
.
Nonce
()
)
}
}
expectedR
:=
common
.
Bytes2Big
(
mustConvertBytes
(
txTest
.
Transaction
.
R
))
v
,
r
,
s
:=
decodedTx
.
SignatureValues
()
if
expectedR
.
Cmp
(
decodedTx
.
R
)
!=
0
{
expectedR
:=
mustConvertBigInt
(
txTest
.
Transaction
.
R
,
16
)
return
fmt
.
Errorf
(
"R mismatch: %v %v"
,
expectedR
,
decodedTx
.
R
)
if
r
.
Cmp
(
expectedR
)
!=
0
{
return
fmt
.
Errorf
(
"R mismatch: %v %v"
,
expectedR
,
r
)
}
}
expectedS
:=
mustConvertBigInt
(
txTest
.
Transaction
.
S
,
16
)
expectedS
:=
common
.
Bytes2Big
(
mustConvertBytes
(
txTest
.
Transaction
.
S
))
if
s
.
Cmp
(
expectedS
)
!=
0
{
if
expectedS
.
Cmp
(
decodedTx
.
S
)
!=
0
{
return
fmt
.
Errorf
(
"S mismatch: %v %v"
,
expectedS
,
s
)
return
fmt
.
Errorf
(
"S mismatch: %v %v"
,
expectedS
,
decodedTx
.
S
)
}
}
expectedV
:=
mustConvertUint
(
txTest
.
Transaction
.
V
,
16
)
expectedV
:=
mustConvertUint
(
txTest
.
Transaction
.
V
,
16
)
if
expectedV
!=
uint64
(
decodedTx
.
V
)
{
if
uint64
(
v
)
!=
expectedV
{
return
fmt
.
Errorf
(
"V mismatch: %v %v"
,
expectedV
,
uint64
(
decodedTx
.
V
)
)
return
fmt
.
Errorf
(
"V mismatch: %v %v"
,
expectedV
,
v
)
}
}
expectedTo
:=
mustConvertAddress
(
txTest
.
Transaction
.
To
)
expectedTo
:=
mustConvertAddress
(
txTest
.
Transaction
.
To
)
if
decodedTx
.
Recipient
==
nil
{
if
decodedTx
.
To
()
==
nil
{
if
expectedTo
!=
common
.
BytesToAddress
([]
byte
{})
{
// "empty" or "zero" address
if
expectedTo
!=
common
.
BytesToAddress
([]
byte
{})
{
// "empty" or "zero" address
return
fmt
.
Errorf
(
"To mismatch when recipient is nil (contract creation): %v"
,
expectedTo
)
return
fmt
.
Errorf
(
"To mismatch when recipient is nil (contract creation): %v"
,
expectedTo
)
}
}
}
else
{
}
else
{
if
expectedTo
!=
*
decodedTx
.
Recipient
{
if
expectedTo
!=
*
decodedTx
.
To
()
{
return
fmt
.
Errorf
(
"To mismatch: %v %v"
,
expectedTo
,
*
decodedTx
.
Recipient
)
return
fmt
.
Errorf
(
"To mismatch: %v %v"
,
expectedTo
,
*
decodedTx
.
To
()
)
}
}
}
}
expectedValue
:=
mustConvertBigInt
(
txTest
.
Transaction
.
Value
,
16
)
expectedValue
:=
mustConvertBigInt
(
txTest
.
Transaction
.
Value
,
16
)
if
expectedValue
.
Cmp
(
decodedTx
.
Amount
)
!=
0
{
if
expectedValue
.
Cmp
(
decodedTx
.
Value
()
)
!=
0
{
return
fmt
.
Errorf
(
"Value mismatch: %v %v"
,
expectedValue
,
decodedTx
.
Amount
)
return
fmt
.
Errorf
(
"Value mismatch: %v %v"
,
expectedValue
,
decodedTx
.
Value
()
)
}
}
return
nil
return
nil
...
...
xeth/xeth.go
View file @
654564e1
...
@@ -946,51 +946,45 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS
...
@@ -946,51 +946,45 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS
// TODO: align default values to have the same type, e.g. not depend on
// TODO: align default values to have the same type, e.g. not depend on
// common.Value conversions later on
// common.Value conversions later on
var
tx
*
types
.
Transaction
if
contractCreation
{
tx
=
types
.
NewContractCreationTx
(
value
,
gas
,
price
,
data
)
}
else
{
tx
=
types
.
NewTransactionMessage
(
to
,
value
,
gas
,
price
,
data
)
}
state
:=
self
.
backend
.
TxPool
()
.
State
()
var
nonce
uint64
var
nonce
uint64
if
len
(
nonceStr
)
!=
0
{
if
len
(
nonceStr
)
!=
0
{
nonce
=
common
.
Big
(
nonceStr
)
.
Uint64
()
nonce
=
common
.
Big
(
nonceStr
)
.
Uint64
()
}
else
{
}
else
{
state
:=
self
.
backend
.
TxPool
()
.
State
()
nonce
=
state
.
GetNonce
(
from
)
nonce
=
state
.
GetNonce
(
from
)
}
}
tx
.
SetNonce
(
nonce
)
var
tx
*
types
.
Transaction
if
contractCreation
{
tx
=
types
.
NewContractCreation
(
nonce
,
value
,
gas
,
price
,
data
)
}
else
{
tx
=
types
.
NewTransaction
(
nonce
,
to
,
value
,
gas
,
price
,
data
)
}
if
err
:=
self
.
sign
(
tx
,
from
,
false
);
err
!=
nil
{
signed
,
err
:=
self
.
sign
(
tx
,
from
,
false
)
if
err
!=
nil
{
return
""
,
err
return
""
,
err
}
}
if
err
:=
self
.
backend
.
TxPool
()
.
Add
(
tx
);
err
!=
nil
{
if
err
=
self
.
backend
.
TxPool
()
.
Add
(
signed
);
err
!=
nil
{
return
""
,
err
return
""
,
err
}
}
//state.SetNonce(from, nonce+1)
if
contractCreation
{
if
contractCreation
{
addr
:=
core
.
AddressFromMessage
(
tx
)
addr
:=
core
.
AddressFromMessage
(
tx
)
glog
.
V
(
logger
.
Info
)
.
Infof
(
"Tx(%x) created: %x
\n
"
,
tx
.
Hash
(),
addr
)
glog
.
V
(
logger
.
Info
)
.
Infof
(
"Tx(%x) created: %x
\n
"
,
tx
.
Hash
(),
addr
)
return
addr
.
Hex
(),
nil
return
core
.
AddressFromMessage
(
tx
)
.
Hex
(),
nil
}
else
{
}
else
{
glog
.
V
(
logger
.
Info
)
.
Infof
(
"Tx(%x) to: %x
\n
"
,
tx
.
Hash
(),
tx
.
To
())
glog
.
V
(
logger
.
Info
)
.
Infof
(
"Tx(%x) to: %x
\n
"
,
tx
.
Hash
(),
tx
.
To
())
}
}
return
tx
.
Hash
()
.
Hex
(),
nil
return
tx
.
Hash
()
.
Hex
(),
nil
}
}
func
(
self
*
XEth
)
sign
(
tx
*
types
.
Transaction
,
from
common
.
Address
,
didUnlock
bool
)
error
{
func
(
self
*
XEth
)
sign
(
tx
*
types
.
Transaction
,
from
common
.
Address
,
didUnlock
bool
)
(
*
types
.
Transaction
,
error
)
{
hash
:=
tx
.
Hash
()
hash
:=
tx
.
Hash
()
sig
,
err
:=
self
.
doSign
(
from
,
hash
,
didUnlock
)
sig
,
err
:=
self
.
doSign
(
from
,
hash
,
didUnlock
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
tx
,
err
}
}
tx
.
SetSignatureValues
(
sig
)
return
tx
.
WithSignature
(
sig
)
return
nil
}
}
// callmsg is the message type used for call transations.
// callmsg is the message type used for call transations.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment