diff --git a/go.mod b/go.mod index b4bd03102a..92e69d503f 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22.8 require ( github.com/VictoriaMetrics/fastcache v1.12.1 - github.com/ava-labs/avalanchego v1.12.3-0.20250128183416-7d2fd6ad37f4 + github.com/ava-labs/avalanchego v1.12.3-warp-verify4 github.com/cespare/cp v0.1.0 github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 github.com/davecgh/go-spew v1.1.1 diff --git a/go.sum b/go.sum index 7f684d73b4..168caf4a40 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,8 @@ github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/avalanchego v1.12.3-0.20250128183416-7d2fd6ad37f4 h1:twEyoj604JLd0pmMktRjVixtdjxiYuTvQ5nHmP/BVzg= -github.com/ava-labs/avalanchego v1.12.3-0.20250128183416-7d2fd6ad37f4/go.mod h1:B7l4fA/BZL6VMC1HCtaHt1RpkC2HWxjAXxTZbc+n3ZI= +github.com/ava-labs/avalanchego v1.12.3-warp-verify4 h1:8YsFAZUC7PyvgZVpZe+kwpHBa7p1e3pDedS8/NeXQhU= +github.com/ava-labs/avalanchego v1.12.3-warp-verify4/go.mod h1:Er2qCyxI4qQKDlNjwwWdOa+/cxCbuEy/z8WgxtXy0N0= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= diff --git a/precompile/contracts/warp/config.go b/precompile/contracts/warp/config.go index ce90cf282c..23b3bbdbe3 100644 --- a/precompile/contracts/warp/config.go +++ b/precompile/contracts/warp/config.go @@ -31,16 +31,17 @@ var ( ) var ( - errOverflowSignersGasCost = errors.New("overflow calculating warp signers gas cost") - errInvalidPredicateBytes = errors.New("cannot unpack predicate bytes") - errInvalidWarpMsg = errors.New("cannot unpack warp message") - errCannotParseWarpMsg = errors.New("cannot parse warp message") - errInvalidWarpMsgPayload = errors.New("cannot unpack warp message payload") - errInvalidAddressedPayload = errors.New("cannot unpack addressed payload") - errInvalidBlockHashPayload = errors.New("cannot unpack block hash payload") - errCannotGetNumSigners = errors.New("cannot fetch num signers from warp message") - errWarpCannotBeActivated = errors.New("warp cannot be activated before Durango") - errFailedVerification = errors.New("cannot verify warp signature") + errOverflowSignersGasCost = errors.New("overflow calculating warp signers gas cost") + errInvalidPredicateBytes = errors.New("cannot unpack predicate bytes") + errInvalidWarpMsg = errors.New("cannot unpack warp message") + errCannotParseWarpMsg = errors.New("cannot parse warp message") + errInvalidWarpMsgPayload = errors.New("cannot unpack warp message payload") + errInvalidAddressedPayload = errors.New("cannot unpack addressed payload") + errInvalidBlockHashPayload = errors.New("cannot unpack block hash payload") + errCannotGetNumSigners = errors.New("cannot fetch num signers from warp message") + errWarpCannotBeActivated = errors.New("warp cannot be activated before Durango") + errFailedVerification = errors.New("cannot verify warp signature") + errCannotRetrieveValidatorSet = errors.New("cannot retrieve validator set") ) // Config implements the precompileconfig.Config interface and @@ -208,16 +209,25 @@ func (c *Config) VerifyPredicate(predicateContext *precompileconfig.PredicateCon warpMsg.SourceChainID, c.RequirePrimaryNetworkSigners, ) - err = warpMsg.Signature.Verify( + + validatorSet, err := warp.GetCanonicalValidatorSetFromChainID( context.Background(), - &warpMsg.UnsignedMessage, - predicateContext.SnowCtx.NetworkID, state, predicateContext.ProposerVMBlockCtx.PChainHeight, + warpMsg.UnsignedMessage.SourceChainID, + ) + if err != nil { + log.Debug("failed to retrieve canonical validator set", "msgID", warpMsg.ID(), "err", err) + return fmt.Errorf("%w: %w", errCannotRetrieveValidatorSet, err) + } + + err = warpMsg.Signature.Verify( + &warpMsg.UnsignedMessage, + predicateContext.SnowCtx.NetworkID, + validatorSet, quorumNumerator, WarpQuorumDenominator, ) - if err != nil { log.Debug("failed to verify warp signature", "msgID", warpMsg.ID(), "err", err) return fmt.Errorf("%w: %w", errFailedVerification, err) diff --git a/precompile/contracts/warp/contract_test.go b/precompile/contracts/warp/contract_test.go index 7650d5953a..a3bb563b3b 100644 --- a/precompile/contracts/warp/contract_test.go +++ b/precompile/contracts/warp/contract_test.go @@ -11,7 +11,6 @@ import ( "github.com/ava-labs/avalanchego/ids" agoUtils "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/platformvm/warp" avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" "github.com/ava-labs/coreth/core/state" @@ -96,7 +95,7 @@ func TestSendWarpMessage(t *testing.T) { sendWarpMessagePayload, ) require.NoError(t, err) - unsignedWarpMessage, err := warp.NewUnsignedMessage( + unsignedWarpMessage, err := avalancheWarp.NewUnsignedMessage( defaultSnowCtx.NetworkID, blockchainID, sendWarpMessageAddressedPayload.Bytes(), @@ -747,7 +746,7 @@ func TestPackEvents(t *testing.T) { ) require.NoError(t, err) - unsignedWarpMessage, err := warp.NewUnsignedMessage( + unsignedWarpMessage, err := avalancheWarp.NewUnsignedMessage( networkID, sourceChainID, addressedPayload.Bytes(), diff --git a/precompile/contracts/warp/signature_verification_test.go b/precompile/contracts/warp/signature_verification_test.go index d52f0a0f89..90ee808f91 100644 --- a/precompile/contracts/warp/signature_verification_test.go +++ b/precompile/contracts/warp/signature_verification_test.go @@ -19,12 +19,13 @@ import ( ) type signatureTest struct { - name string - stateF func(*gomock.Controller) validators.State - quorumNum uint64 - quorumDen uint64 - msgF func(*require.Assertions) *avalancheWarp.Message - err error + name string + stateF func(*gomock.Controller) validators.State + quorumNum uint64 + quorumDen uint64 + msgF func(*require.Assertions) *avalancheWarp.Message + verifyErr error + canonicalErr error } // This test copies the test coverage from https://github.com/ava-labs/avalanchego/blob/0117ab96/vms/platformvm/warp/signature_test.go#L137. @@ -55,7 +56,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: errTest, + canonicalErr: errTest, }, { name: "can't get validator set", @@ -82,7 +83,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: errTest, + canonicalErr: errTest, }, { name: "weight overflow", @@ -122,7 +123,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: avalancheWarp.ErrWeightOverflow, + canonicalErr: avalancheWarp.ErrWeightOverflow, }, { name: "invalid bit set index", @@ -152,7 +153,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: avalancheWarp.ErrInvalidBitSet, + verifyErr: avalancheWarp.ErrInvalidBitSet, }, { name: "unknown index", @@ -185,7 +186,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: avalancheWarp.ErrUnknownValidator, + verifyErr: avalancheWarp.ErrUnknownValidator, }, { name: "insufficient weight", @@ -229,7 +230,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: avalancheWarp.ErrInsufficientWeight, + verifyErr: avalancheWarp.ErrInsufficientWeight, }, { name: "can't parse sig", @@ -263,7 +264,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: avalancheWarp.ErrParseSignature, + verifyErr: avalancheWarp.ErrParseSignature, }, { name: "no validators", @@ -298,7 +299,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: bls.ErrNoPublicKeys, + verifyErr: bls.ErrNoPublicKeys, }, { name: "invalid signature (substitute)", @@ -342,7 +343,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: avalancheWarp.ErrInvalidSignature, + verifyErr: avalancheWarp.ErrInvalidSignature, }, { name: "invalid signature (missing one)", @@ -382,7 +383,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: avalancheWarp.ErrInvalidSignature, + verifyErr: avalancheWarp.ErrInvalidSignature, }, { name: "invalid signature (extra one)", @@ -427,7 +428,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: avalancheWarp.ErrInvalidSignature, + verifyErr: avalancheWarp.ErrInvalidSignature, }, { name: "valid signature", @@ -471,7 +472,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: nil, + verifyErr: nil, }, { name: "valid signature (boundary)", @@ -515,7 +516,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: nil, + verifyErr: nil, }, { name: "valid signature (missing key)", @@ -576,7 +577,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: nil, + verifyErr: nil, }, { name: "valid signature (duplicate key)", @@ -635,7 +636,7 @@ func TestSignatureVerification(t *testing.T) { require.NoError(err) return msg }, - err: nil, + verifyErr: nil, }, } @@ -648,16 +649,24 @@ func TestSignatureVerification(t *testing.T) { msg := tt.msgF(require) pChainState := tt.stateF(ctrl) - err := msg.Signature.Verify( + validatorSet, err := avalancheWarp.GetCanonicalValidatorSetFromChainID( context.Background(), - &msg.UnsignedMessage, - networkID, pChainState, pChainHeight, + msg.UnsignedMessage.SourceChainID, + ) + require.ErrorIs(err, tt.canonicalErr) + if err != nil { + return + } + err = msg.Signature.Verify( + &msg.UnsignedMessage, + networkID, + validatorSet, tt.quorumNum, tt.quorumDen, ) - require.ErrorIs(err, tt.err) + require.ErrorIs(err, tt.verifyErr) }) } } diff --git a/scripts/versions.sh b/scripts/versions.sh index fa2a939bc2..12aed7d162 100644 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -6,4 +6,4 @@ set -euo pipefail # Don't export them as they're used in the context of other calls -AVALANCHE_VERSION=${AVALANCHE_VERSION:-'7d2fd6ad3'} +AVALANCHE_VERSION=${AVALANCHE_VERSION:-'2eea9338'} diff --git a/warp/service.go b/warp/service.go index 610fc85a91..01123950ff 100644 --- a/warp/service.go +++ b/warp/service.go @@ -112,22 +112,22 @@ func (a *API) aggregateSignatures(ctx context.Context, unsignedMessage *warp.Uns } state := warpValidators.NewState(a.state, a.sourceSubnetID, a.sourceChainID, a.requirePrimaryNetworkSigners()) - validators, totalWeight, err := warp.GetCanonicalValidatorSet(ctx, state, pChainHeight, subnetID) + validatorSet, err := warp.GetCanonicalValidatorSetFromSubnetID(ctx, state, pChainHeight, subnetID) if err != nil { return nil, fmt.Errorf("failed to get validator set: %w", err) } - if len(validators) == 0 { + if len(validatorSet.Validators) == 0 { return nil, fmt.Errorf("%w (SubnetID: %s, Height: %d)", errNoValidators, subnetID, pChainHeight) } log.Debug("Fetching signature", "sourceSubnetID", subnetID, "height", pChainHeight, - "numValidators", len(validators), - "totalWeight", totalWeight, + "numValidators", len(validatorSet.Validators), + "totalWeight", validatorSet.TotalWeight, ) - agg := aggregator.New(aggregator.NewSignatureGetter(a.client), validators, totalWeight) + agg := aggregator.New(aggregator.NewSignatureGetter(a.client), validatorSet.Validators, validatorSet.TotalWeight) signatureResult, err := agg.AggregateSignatures(ctx, unsignedMessage, quorumNum) if err != nil { return nil, err