Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions wallet/chain/p/signer/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/ava-labs/avalanchego/vms/components/avax"
"github.com/ava-labs/avalanchego/vms/platformvm/fx"
"github.com/ava-labs/avalanchego/vms/platformvm/txs"
"github.com/ava-labs/avalanchego/wallet/subnet/primary/common"

stdcontext "context"
)
Expand All @@ -24,7 +25,7 @@ type Signer interface {
//
// If the signer doesn't have the ability to provide a required signature,
// the signature slot will be skipped without reporting an error.
Sign(ctx stdcontext.Context, tx *txs.Tx) error
Sign(ctx stdcontext.Context, tx *txs.Tx, options ...common.Option) error
}

type Backend interface {
Expand All @@ -44,20 +45,24 @@ func New(kc keychain.Keychain, backend Backend) Signer {
}
}

func (s *txSigner) Sign(ctx stdcontext.Context, tx *txs.Tx) error {
func (s *txSigner) Sign(ctx stdcontext.Context, tx *txs.Tx, options ...common.Option) error {
ops := common.NewOptions(options)

return tx.Unsigned.Visit(&visitor{
kc: s.kc,
backend: s.backend,
ctx: ctx,
tx: tx,
kc: s.kc,
backend: s.backend,
ctx: ctx,
tx: tx,
forceSignHash: ops.ForceSignHash(),
})
}

func SignUnsigned(
ctx stdcontext.Context,
signer Signer,
utx txs.UnsignedTx,
options ...common.Option,
) (*txs.Tx, error) {
tx := &txs.Tx{Unsigned: utx}
return tx, signer.Sign(ctx, tx)
return tx, signer.Sign(ctx, tx, options...)
}
25 changes: 13 additions & 12 deletions wallet/chain/p/signer/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ var (

// visitor handles signing transactions for the signer
type visitor struct {
kc keychain.Keychain
backend Backend
ctx context.Context
tx *txs.Tx
kc keychain.Keychain
backend Backend
ctx context.Context
tx *txs.Tx
forceSignHash bool
}

func (*visitor) AdvanceTimeTx(*txs.AdvanceTimeTx) error {
Expand All @@ -56,7 +57,7 @@ func (s *visitor) AddValidatorTx(tx *txs.AddValidatorTx) error {
if err != nil {
return err
}
return sign(s.tx, false, txSigners)
return sign(s.tx, s.forceSignHash, txSigners)
}

func (s *visitor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) error {
Expand All @@ -69,15 +70,15 @@ func (s *visitor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) error {
return err
}
txSigners = append(txSigners, subnetAuthSigners)
return sign(s.tx, false, txSigners)
return sign(s.tx, s.forceSignHash, txSigners)
}

func (s *visitor) AddDelegatorTx(tx *txs.AddDelegatorTx) error {
txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins)
if err != nil {
return err
}
return sign(s.tx, false, txSigners)
return sign(s.tx, s.forceSignHash, txSigners)
}

func (s *visitor) CreateChainTx(tx *txs.CreateChainTx) error {
Expand All @@ -90,15 +91,15 @@ func (s *visitor) CreateChainTx(tx *txs.CreateChainTx) error {
return err
}
txSigners = append(txSigners, subnetAuthSigners)
return sign(s.tx, false, txSigners)
return sign(s.tx, s.forceSignHash, txSigners)
}

func (s *visitor) CreateSubnetTx(tx *txs.CreateSubnetTx) error {
txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins)
if err != nil {
return err
}
return sign(s.tx, false, txSigners)
return sign(s.tx, s.forceSignHash, txSigners)
}

func (s *visitor) ImportTx(tx *txs.ImportTx) error {
Expand All @@ -111,15 +112,15 @@ func (s *visitor) ImportTx(tx *txs.ImportTx) error {
return err
}
txSigners = append(txSigners, txImportSigners...)
return sign(s.tx, false, txSigners)
return sign(s.tx, s.forceSignHash, txSigners)
}

func (s *visitor) ExportTx(tx *txs.ExportTx) error {
txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins)
if err != nil {
return err
}
return sign(s.tx, false, txSigners)
return sign(s.tx, s.forceSignHash, txSigners)
}

func (s *visitor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error {
Expand Down Expand Up @@ -182,7 +183,7 @@ func (s *visitor) BaseTx(tx *txs.BaseTx) error {
if err != nil {
return err
}
return sign(s.tx, false, txSigners)
return sign(s.tx, s.forceSignHash, txSigners)
}

func (s *visitor) ConvertSubnetToL1Tx(tx *txs.ConvertSubnetToL1Tx) error {
Expand Down
35 changes: 35 additions & 0 deletions wallet/chain/p/signer/with_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package signer

import (
"context"

"github.com/ava-labs/avalanchego/vms/platformvm/txs"
"github.com/ava-labs/avalanchego/wallet/subnet/primary/common"
)

var _ Signer = (*withOptions)(nil)

type withOptions struct {
signer Signer
options []common.Option
}

// WithOptions returns a new signer that will use the given options by default.
//
// - [signer] is the signer that will be called to perform the underlying
// operations.
// - [options] will be provided to the signer in addition to the options
// provided in the method calls.
func WithOptions(signer Signer, options ...common.Option) Signer {
return &withOptions{
signer: signer,
options: options,
}
}

func (w *withOptions) Sign(ctx context.Context, tx *txs.Tx, options ...common.Option) error {
return w.signer.Sign(ctx, tx, common.UnionOptions(w.options, options)...)
}
2 changes: 1 addition & 1 deletion wallet/chain/p/wallet/with_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (w *withOptions) Builder() builder.Builder {
}

func (w *withOptions) Signer() walletsigner.Signer {
return w.wallet.Signer()
return walletsigner.WithOptions(w.wallet.Signer(), w.options...)
}

func (w *withOptions) IssueBaseTx(
Expand Down
19 changes: 12 additions & 7 deletions wallet/chain/x/signer/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/ava-labs/avalanchego/utils/crypto/keychain"
"github.com/ava-labs/avalanchego/vms/avm/txs"
"github.com/ava-labs/avalanchego/vms/components/avax"
"github.com/ava-labs/avalanchego/wallet/subnet/primary/common"
)

var _ Signer = (*signer)(nil)
Expand All @@ -23,7 +24,7 @@ type Signer interface {
//
// If the signer doesn't have the ability to provide a required signature,
// the signature slot will be skipped without reporting an error.
Sign(ctx context.Context, tx *txs.Tx) error
Sign(ctx context.Context, tx *txs.Tx, options ...common.Option) error
}

type Backend interface {
Expand All @@ -42,20 +43,24 @@ func New(kc keychain.Keychain, backend Backend) Signer {
}
}

func (s *signer) Sign(ctx context.Context, tx *txs.Tx) error {
func (s *signer) Sign(ctx context.Context, tx *txs.Tx, options ...common.Option) error {
ops := common.NewOptions(options)

return tx.Unsigned.Visit(&visitor{
kc: s.kc,
backend: s.backend,
ctx: ctx,
tx: tx,
kc: s.kc,
backend: s.backend,
ctx: ctx,
tx: tx,
forceSignHash: ops.ForceSignHash(),
})
}

func SignUnsigned(
ctx context.Context,
signer Signer,
utx txs.UnsignedTx,
options ...common.Option,
) (*txs.Tx, error) {
tx := &txs.Tx{Unsigned: utx}
return tx, signer.Sign(ctx, tx)
return tx, signer.Sign(ctx, tx, options...)
}
30 changes: 19 additions & 11 deletions wallet/chain/x/signer/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/crypto/keychain"
"github.com/ava-labs/avalanchego/utils/crypto/secp256k1"
"github.com/ava-labs/avalanchego/utils/hashing"
"github.com/ava-labs/avalanchego/vms/avm/fxs"
"github.com/ava-labs/avalanchego/vms/avm/txs"
"github.com/ava-labs/avalanchego/vms/components/avax"
Expand All @@ -37,26 +38,27 @@ var (

// visitor handles signing transactions for the signer
type visitor struct {
kc keychain.Keychain
backend Backend
ctx context.Context
tx *txs.Tx
kc keychain.Keychain
backend Backend
ctx context.Context
tx *txs.Tx
forceSignHash bool
}

func (s *visitor) BaseTx(tx *txs.BaseTx) error {
txCreds, txSigners, err := s.getSigners(s.ctx, tx.BlockchainID, tx.Ins)
if err != nil {
return err
}
return sign(s.tx, txCreds, txSigners)
return sign(s.tx, s.forceSignHash, txCreds, txSigners)
}

func (s *visitor) CreateAssetTx(tx *txs.CreateAssetTx) error {
txCreds, txSigners, err := s.getSigners(s.ctx, tx.BlockchainID, tx.Ins)
if err != nil {
return err
}
return sign(s.tx, txCreds, txSigners)
return sign(s.tx, s.forceSignHash, txCreds, txSigners)
}

func (s *visitor) OperationTx(tx *txs.OperationTx) error {
Expand All @@ -70,7 +72,7 @@ func (s *visitor) OperationTx(tx *txs.OperationTx) error {
}
txCreds = append(txCreds, txOpsCreds...)
txSigners = append(txSigners, txOpsSigners...)
return sign(s.tx, txCreds, txSigners)
return sign(s.tx, s.forceSignHash, txCreds, txSigners)
}

func (s *visitor) ImportTx(tx *txs.ImportTx) error {
Expand All @@ -84,15 +86,15 @@ func (s *visitor) ImportTx(tx *txs.ImportTx) error {
}
txCreds = append(txCreds, txImportCreds...)
txSigners = append(txSigners, txImportSigners...)
return sign(s.tx, txCreds, txSigners)
return sign(s.tx, s.forceSignHash, txCreds, txSigners)
}

func (s *visitor) ExportTx(tx *txs.ExportTx) error {
txCreds, txSigners, err := s.getSigners(s.ctx, tx.BlockchainID, tx.Ins)
if err != nil {
return err
}
return sign(s.tx, txCreds, txSigners)
return sign(s.tx, s.forceSignHash, txCreds, txSigners)
}

func (s *visitor) getSigners(ctx context.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([]verify.Verifiable, [][]keychain.Signer, error) {
Expand Down Expand Up @@ -218,12 +220,13 @@ func (s *visitor) getOpsSigners(ctx context.Context, sourceChainID ids.ID, ops [
return txCreds, txSigners, nil
}

func sign(tx *txs.Tx, creds []verify.Verifiable, txSigners [][]keychain.Signer) error {
func sign(tx *txs.Tx, signHash bool, creds []verify.Verifiable, txSigners [][]keychain.Signer) error {
codec := builder.Parser.Codec()
unsignedBytes, err := codec.Marshal(txs.CodecVersion, &tx.Unsigned)
if err != nil {
return fmt.Errorf("couldn't marshal unsigned tx: %w", err)
}
unsignedHash := hashing.ComputeHash256(unsignedBytes)

if expectedLen := len(txSigners); expectedLen != len(tx.Creds) {
tx.Creds = make([]*fxs.FxCredential, expectedLen)
Expand Down Expand Up @@ -282,7 +285,12 @@ func sign(tx *txs.Tx, creds []verify.Verifiable, txSigners [][]keychain.Signer)
continue
}

sig, err := signer.Sign(unsignedBytes)
var sig []byte
if signHash {
sig, err = signer.SignHash(unsignedHash)
} else {
sig, err = signer.Sign(unsignedBytes)
}
if err != nil {
return fmt.Errorf("problem signing tx: %w", err)
}
Expand Down
35 changes: 35 additions & 0 deletions wallet/chain/x/signer/with_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package signer

import (
"context"

"github.com/ava-labs/avalanchego/vms/avm/txs"
"github.com/ava-labs/avalanchego/wallet/subnet/primary/common"
)

var _ Signer = (*withOptions)(nil)

type withOptions struct {
signer Signer
options []common.Option
}

// WithOptions returns a new signer that will use the given options by default.
//
// - [signer] is the signer that will be called to perform the underlying
// operations.
// - [options] will be provided to the signer in addition to the options
// provided in the method calls.
func WithOptions(signer Signer, options ...common.Option) Signer {
return &withOptions{
signer: signer,
options: options,
}
}

func (w *withOptions) Sign(ctx context.Context, tx *txs.Tx, options ...common.Option) error {
return w.signer.Sign(ctx, tx, common.UnionOptions(w.options, options)...)
}
2 changes: 1 addition & 1 deletion wallet/chain/x/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ func (w *wallet) IssueUnsignedTx(
) (*txs.Tx, error) {
ops := common.NewOptions(options)
ctx := ops.Context()
tx, err := signer.SignUnsigned(ctx, w.signer, utx)
tx, err := signer.SignUnsigned(ctx, w.signer, utx, options...)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion wallet/chain/x/wallet_with_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (w *walletWithOptions) Builder() builder.Builder {
}

func (w *walletWithOptions) Signer() signer.Signer {
return w.wallet.Signer()
return signer.WithOptions(w.wallet.Signer(), w.options...)
}

func (w *walletWithOptions) IssueBaseTx(
Expand Down
Loading