Value Transfer in Private Transactions (#538)

Fix #528
This commit is contained in:
Nguyen Kien Trung 2018-10-01 14:37:05 -04:00 committed by Samer Falah
parent 8c9ed51fa0
commit 40f7d2b8b4
3 changed files with 79 additions and 24 deletions

View File

@ -585,8 +585,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
return ErrNonceTooLow
}
// Ether value is not currently supported on private transactions
if tx.IsPrivate() && (tx.Value().Sign() != 0) {
return ErrEtherValueUnsupported;
if tx.IsPrivate() && (len(tx.Data()) == 0 || tx.Value().Sign() != 0) {
return ErrEtherValueUnsupported
}
// Transactor should have enough funds to cover the costs
// cost == V + GP * GL

View File

@ -19,8 +19,14 @@ package core
import (
"crypto/ecdsa"
"fmt"
"io/ioutil"
"math/big"
"math/rand"
"os"
"reflect"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
@ -28,11 +34,6 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"math/rand"
"time"
"io/ioutil"
"os"
"reflect"
)
// testTxPoolConfig is a transaction pool configuration without stateful disk
@ -281,6 +282,54 @@ func TestQuorumInvalidTransactions(t *testing.T) {
}
func TestValidateTx_whenValueZeroTransferForPrivateTransaction(t *testing.T) {
pool, key := setupQuorumTxPool()
defer pool.Stop()
zeroValue := common.Big0
zeroGasPrice := common.Big0
defaultTxPoolGasLimit := big.NewInt(1000000)
arbitraryTx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, zeroValue, defaultTxPoolGasLimit, zeroGasPrice, nil), types.HomesteadSigner{}, key)
arbitraryTx.SetPrivate()
if err := pool.AddRemote(arbitraryTx); err != ErrEtherValueUnsupported {
t.Error("expected:", ErrEtherValueUnsupported, "; got:", err)
}
}
func TestValidateTx_whenValueNonZeroTransferForPrivateTransaction(t *testing.T) {
pool, key := setupQuorumTxPool()
defer pool.Stop()
arbitraryValue := common.Big3
arbitraryTx, balance, from := newPrivateTransaction(arbitraryValue, nil, key)
pool.currentState.AddBalance(from, balance)
if err := pool.AddRemote(arbitraryTx); err != ErrEtherValueUnsupported {
t.Error("expected: ", ErrEtherValueUnsupported, "; got:", err)
}
}
func newPrivateTransaction(value *big.Int, data []byte, key *ecdsa.PrivateKey) (*types.Transaction, *big.Int, common.Address) {
zeroGasPrice := common.Big0
defaultTxPoolGasLimit := big.NewInt(1000000)
arbitraryTx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, value, defaultTxPoolGasLimit, zeroGasPrice, data), types.HomesteadSigner{}, key)
arbitraryTx.SetPrivate()
balance := new(big.Int).Add(arbitraryTx.Value(), new(big.Int).Mul(arbitraryTx.Gas(), arbitraryTx.GasPrice()))
from, _ := deriveSender(arbitraryTx)
return arbitraryTx, balance, from
}
func TestValidateTx_whenValueNonZeroWithSmartContractForPrivateTransaction(t *testing.T) {
pool, key := setupQuorumTxPool()
defer pool.Stop()
arbitraryValue := common.Big3
arbitraryTx, balance, from := newPrivateTransaction(arbitraryValue, []byte("arbitrary bytecode"), key)
pool.currentState.AddBalance(from, balance)
if err := pool.AddRemote(arbitraryTx); err != ErrEtherValueUnsupported {
t.Error("expected: ", ErrEtherValueUnsupported, "; got:", err)
}
}
func TestTransactionQueue(t *testing.T) {
pool, key := setupTxPool()
defer pool.Stop()
@ -1527,9 +1576,9 @@ func benchmarkPoolBatchInsert(b *testing.B, size int) {
//Checks that the EIP155 signer is assigned to the TxPool no matter the configuration, even invalid config
func TestEIP155SignerOnTxPool(t *testing.T) {
var flagtests = []struct {
name string
homesteadBlock *big.Int
eip155Block *big.Int
name string
homesteadBlock *big.Int
eip155Block *big.Int
}{
{"hsnileip155nil", nil, nil},
{"hsnileip1550", nil, big.NewInt(0)},
@ -1567,4 +1616,3 @@ func TestEIP155SignerOnTxPool(t *testing.T) {
}
}

View File

@ -362,12 +362,14 @@ func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs
data := []byte(args.Data)
isPrivate := args.PrivateFor != nil
if isPrivate {
log.Info("sending private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", args.PrivateFor)
data, err = private.P.Send(data, args.PrivateFrom, args.PrivateFor)
log.Info("sent private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", args.PrivateFor)
if err != nil {
return common.Hash{}, err
}
if len(data) > 0 {
log.Info("sending private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", args.PrivateFor)
data, err = private.P.Send(data, args.PrivateFrom, args.PrivateFor)
log.Info("sent private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", args.PrivateFor)
if err != nil {
return common.Hash{}, err
}
} // else tx_pool.go#validateTx will capture and throw error
args.Data = data
}
@ -1152,13 +1154,15 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
isPrivate := args.PrivateFor != nil
if isPrivate {
//Send private transaction to local Constellation node
log.Info("sending private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", args.PrivateFor)
data, err = private.P.Send(data, args.PrivateFrom, args.PrivateFor)
log.Info("sent private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", args.PrivateFor)
if err != nil {
return common.Hash{}, err
}
if len(data) > 0 {
//Send private transaction to local Constellation node
log.Info("sending private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", args.PrivateFor)
data, err = private.P.Send(data, args.PrivateFrom, args.PrivateFor)
log.Info("sent private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", args.PrivateFor)
if err != nil {
return common.Hash{}, err
}
} // else tx_pool.go#validateTx will capture and throw error
args.Data = data
}
@ -1239,6 +1243,9 @@ func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args Sen
if err != nil {
return nil, err
}
if args.PrivateFor != nil {
tx.SetPrivate()
}
data, err := rlp.EncodeToBytes(tx)
if err != nil {
return nil, err