Skip to content

Commit

Permalink
Fix abigen not supporting enhanced privacy for go
Browse files Browse the repository at this point in the history
  • Loading branch information
rodion-lim-partior committed Aug 28, 2023
1 parent 65de7ae commit 7b9ddc9
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 5 deletions.
12 changes: 9 additions & 3 deletions accounts/abi/bind/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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
}
}
Expand All @@ -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
Expand Down
39 changes: 38 additions & 1 deletion accounts/abi/bind/bind_quorum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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{}

Expand Down Expand Up @@ -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
}

Expand Down
12 changes: 11 additions & 1 deletion ethclient/ethclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down

0 comments on commit 7b9ddc9

Please sign in to comment.