From 7b9ddc978f1da98bb5f379e0f0be40b11fc5e474 Mon Sep 17 00:00:00 2001 From: rodion Date: Fri, 25 Aug 2023 10:24:35 +0000 Subject: [PATCH] Fix abigen not supporting enhanced privacy for go --- accounts/abi/bind/base.go | 12 ++++++--- accounts/abi/bind/bind_quorum_test.go | 39 ++++++++++++++++++++++++++- ethclient/ethclient.go | 12 ++++++++- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go index 5d32806a0e..ea7aaa596e 100644 --- a/accounts/abi/bind/base.go +++ b/accounts/abi/bind/base.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/private/engine" ) // SignerFn is a signer function callback when a contract requires a method to @@ -39,7 +40,10 @@ type SignerFn func(common.Address, *types.Transaction) (*types.Transaction, erro // // Additional arguments in order to support transaction privacy type PrivateTxArgs struct { - PrivateFor []string `json:"privateFor"` + PrivateFrom string `json:"privateFrom"` + PrivateFor []string `json:"privateFor"` + PrivacyFlag engine.PrivacyFlagType `json:"privacyFlag"` + MandatoryRecipients []string `json:"mandatoryFor"` } // CallOpts is the collection of options to fine tune a contract call request. @@ -68,6 +72,8 @@ type TransactOpts struct { // Quorum PrivateFrom string // The public key of the Tessera/Constellation identity to send this tx from. PrivateFor []string // The public keys of the Tessera/Constellation identities this tx is intended for. + PrivacyFlag engine.PrivacyFlagType + MandatoryRecipients []string IsUsingPrivacyPrecompile bool } @@ -282,7 +288,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i rawTx = c.createPrivateTransaction(rawTx, payload) if opts.IsUsingPrivacyPrecompile { - rawTx, _ = c.createMarkerTx(opts, rawTx, PrivateTxArgs{PrivateFor: opts.PrivateFor}) + rawTx, _ = c.createMarkerTx(opts, rawTx, PrivateTxArgs{PrivateFrom: opts.PrivateFrom, PrivateFor: opts.PrivateFor, PrivacyFlag: opts.PrivacyFlag, MandatoryRecipients: opts.MandatoryRecipients}) opts.PrivateFor = nil } } @@ -298,7 +304,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i if opts.NoSend { return signedTx, nil } - if err := c.transactor.SendTransaction(ensureContext(opts.Context), signedTx, PrivateTxArgs{PrivateFor: opts.PrivateFor}); err != nil { + if err := c.transactor.SendTransaction(ensureContext(opts.Context), signedTx, PrivateTxArgs{PrivateFrom: opts.PrivateFrom, PrivateFor: opts.PrivateFor, PrivacyFlag: opts.PrivacyFlag, MandatoryRecipients: opts.MandatoryRecipients}); err != nil { return nil, err } return signedTx, nil diff --git a/accounts/abi/bind/bind_quorum_test.go b/accounts/abi/bind/bind_quorum_test.go index eafc8d30fd..fdf08401c6 100644 --- a/accounts/abi/bind/bind_quorum_test.go +++ b/accounts/abi/bind/bind_quorum_test.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/private/engine" "github.com/stretchr/testify/require" ) @@ -140,6 +141,41 @@ func TestBoundContract_Transact_Transaction_PrivateTransaction(t *testing.T) { require.True(t, tx.IsPrivate()) } +func TestBoundContract_Transact_Transaction_PrivateTransaction_EnhancedPrivacy(t *testing.T) { + transactor := &mockTransactor{} + + contractAddr := common.HexToAddress("0x1932c48b2bf8102ba33b4a6b545c32236e342f34") + c := NewBoundContract(contractAddr, abi.ABI{}, nil, transactor, nil) + + senderNonce := 1 + + opts := &TransactOpts{ + Nonce: big.NewInt(int64(senderNonce)), + PrivateFor: []string{"tm1"}, + PrivacyFlag: engine.PrivacyFlagPartyProtection, + + // arbitrary values to skip the logic we're not testing + GasPrice: big.NewInt(0), + GasLimit: uint64(1), + Signer: passthroughSigner, + } + + tx, err := c.transact(opts, &contractAddr, nil) + + wantNonce := uint64(senderNonce) + wantTo := &contractAddr + wantData := tmPrivatePayloadHash.Bytes() + wantPrivacyFlag := engine.PrivacyFlagPartyProtection + + require.NoError(t, err) + require.NotNil(t, tx) + require.Equal(t, wantNonce, tx.Nonce()) + require.Equal(t, wantTo, tx.To()) + require.Equal(t, wantData, tx.Data()) + require.True(t, tx.IsPrivate()) + require.Equal(t, wantPrivacyFlag, transactor.capturedInternalPrivateTransactionArgs.PrivacyFlag) +} + func TestBoundContract_Transact_Transaction_PrivacyPrecompile(t *testing.T) { transactor := &mockTransactor{} @@ -210,7 +246,8 @@ func (s *mockTransactor) DistributeTransaction(_ context.Context, tx *types.Tran return tmPrivateTxHash.Hex(), nil } -func (s *mockTransactor) SendTransaction(_ context.Context, _ *types.Transaction, _ PrivateTxArgs) error { +func (s *mockTransactor) SendTransaction(_ context.Context, _ *types.Transaction, args PrivateTxArgs) error { + s.capturedInternalPrivateTransactionArgs = args return nil } diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 89dc61e188..27e7831215 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -546,7 +546,17 @@ func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction, ar return err } if args.PrivateFor != nil { - return ec.c.CallContext(ctx, nil, "eth_sendRawPrivateTransaction", hexutil.Encode(data), bind.PrivateTxArgs{PrivateFor: args.PrivateFor}) + privateTxArgs := bind.PrivateTxArgs{PrivateFor: args.PrivateFor} + if args.PrivacyFlag.IsNotStandardPrivate() { + privateTxArgs.PrivacyFlag = args.PrivacyFlag + } + if args.MandatoryRecipients != nil { + privateTxArgs.MandatoryRecipients = args.MandatoryRecipients + } + if args.PrivateFrom != "" { + privateTxArgs.PrivateFrom = args.PrivateFrom + } + return ec.c.CallContext(ctx, nil, "eth_sendRawPrivateTransaction", hexutil.Encode(data), privateTxArgs) } else { return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data)) }