diff --git a/chains/manager.go b/chains/manager.go index 6e233d5e365..a088cd15fdb 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -475,7 +475,7 @@ func (m *manager) buildChain(chainParams ChainParameters, sb subnets.Subnet) (*c BCLookup: m, Metrics: vmMetrics, - WarpSigner: warp.NewSigner(m.StakingBLSKey, chainParams.ID), + WarpSigner: warp.NewSigner(m.StakingBLSKey, m.NetworkID, chainParams.ID), ValidatorState: m.validatorState, ChainDataDir: chainDataDir, diff --git a/proto/pb/warp/message.pb.go b/proto/pb/warp/message.pb.go index 954689132fc..d6cb3736081 100644 --- a/proto/pb/warp/message.pb.go +++ b/proto/pb/warp/message.pb.go @@ -25,9 +25,9 @@ type SignRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SourceChainId []byte `protobuf:"bytes,1,opt,name=source_chain_id,json=sourceChainId,proto3" json:"source_chain_id,omitempty"` - DestinationChainId []byte `protobuf:"bytes,2,opt,name=destination_chain_id,json=destinationChainId,proto3" json:"destination_chain_id,omitempty"` - Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"` + NetworkId uint32 `protobuf:"varint,1,opt,name=network_id,json=networkId,proto3" json:"network_id,omitempty"` + SourceChainId []byte `protobuf:"bytes,2,opt,name=source_chain_id,json=sourceChainId,proto3" json:"source_chain_id,omitempty"` + Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"` } func (x *SignRequest) Reset() { @@ -62,16 +62,16 @@ func (*SignRequest) Descriptor() ([]byte, []int) { return file_warp_message_proto_rawDescGZIP(), []int{0} } -func (x *SignRequest) GetSourceChainId() []byte { +func (x *SignRequest) GetNetworkId() uint32 { if x != nil { - return x.SourceChainId + return x.NetworkId } - return nil + return 0 } -func (x *SignRequest) GetDestinationChainId() []byte { +func (x *SignRequest) GetSourceChainId() []byte { if x != nil { - return x.DestinationChainId + return x.SourceChainId } return nil } @@ -134,25 +134,24 @@ var File_warp_message_proto protoreflect.FileDescriptor var file_warp_message_proto_rawDesc = []byte{ 0x0a, 0x12, 0x77, 0x61, 0x72, 0x70, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x77, 0x61, 0x72, 0x70, 0x22, 0x81, 0x01, 0x0a, 0x0b, 0x53, - 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x2c, - 0x0a, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x32, 0x37, 0x0a, 0x06, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x04, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x11, - 0x2e, 0x77, 0x61, 0x72, 0x70, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x12, 0x2e, 0x77, 0x61, 0x72, 0x70, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x76, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x61, 0x76, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, - 0x62, 0x2f, 0x77, 0x61, 0x72, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x77, 0x61, 0x72, 0x70, 0x22, 0x6e, 0x0a, 0x0b, 0x53, 0x69, + 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, + 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x2c, 0x0a, 0x0c, 0x53, 0x69, + 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x32, 0x37, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x04, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x11, 0x2e, 0x77, 0x61, 0x72, + 0x70, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, + 0x77, 0x61, 0x72, 0x70, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x61, 0x76, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x61, 0x76, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x68, 0x65, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x2f, 0x77, 0x61, + 0x72, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/warp/message.proto b/proto/warp/message.proto index e2f52db6acb..8cd6a9efa66 100644 --- a/proto/warp/message.proto +++ b/proto/warp/message.proto @@ -9,8 +9,8 @@ service Signer { } message SignRequest { - bytes source_chain_id = 1; - bytes destination_chain_id = 2; + uint32 network_id = 1; + bytes source_chain_id = 2; bytes payload = 3; } diff --git a/scripts/install_anr.sh b/scripts/install_anr.sh new file mode 100755 index 00000000000..148321dee50 --- /dev/null +++ b/scripts/install_anr.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -e +set -o nounset +set -o pipefail + +# Avalanche root directory +AVALANCHE_PATH=$( + cd "$(dirname "${BASH_SOURCE[0]}")" + cd .. && pwd +) + +# Load the constants +source "$AVALANCHE_PATH"/scripts/constants.sh + +################################# +# download avalanche-network-runner +# https://github.com/ava-labs/avalanche-network-runner +GOARCH=$(go env GOARCH) +GOOS=$(go env GOOS) +NETWORK_RUNNER_VERSION=1.3.9 +anr_workdir=${ANR_WORKDIR:-"/tmp"} +DOWNLOAD_PATH=${anr_workdir}/avalanche-network-runner-v${NETWORK_RUNNER_VERSION}.tar.gz +DOWNLOAD_URL="https://github.com/ava-labs/avalanche-network-runner/releases/download/v${NETWORK_RUNNER_VERSION}/avalanche-network-runner_${NETWORK_RUNNER_VERSION}_${GOOS}_${GOARCH}.tar.gz" +echo "Installing avalanche-network-runner ${NETWORK_RUNNER_VERSION} to ${anr_workdir}/avalanche-network-runner" + +# download only if not already downloaded +if [ ! -f "$DOWNLOAD_PATH" ]; then + echo "downloading avalanche-network-runner ${NETWORK_RUNNER_VERSION} at ${DOWNLOAD_URL} to ${DOWNLOAD_PATH}" + curl --fail -L ${DOWNLOAD_URL} -o ${DOWNLOAD_PATH} +else + echo "avalanche-network-runner ${NETWORK_RUNNER_VERSION} already downloaded at ${DOWNLOAD_PATH}" +fi + +rm -f ${anr_workdir}/avalanche-network-runner + +echo "extracting downloaded avalanche-network-runner" +tar xzvf ${DOWNLOAD_PATH} -C ${anr_workdir} +${anr_workdir}/avalanche-network-runner -h diff --git a/scripts/tests.e2e.sh b/scripts/tests.e2e.sh index a12bea6d0a1..67fd1b538b7 100755 --- a/scripts/tests.e2e.sh +++ b/scripts/tests.e2e.sh @@ -14,41 +14,14 @@ fi AVALANCHEGO_PATH="${1-}" if [[ -z "${AVALANCHEGO_PATH}" ]]; then echo "Missing AVALANCHEGO_PATH argument!" - echo "Usage: ${0} [AVALANCHEGO_PATH]" >> /dev/stderr + echo "Usage: ${0} [AVALANCHEGO_PATH]" >>/dev/stderr exit 255 fi -# Set the CGO flags to use the portable version of BLST -# -# We use "export" here instead of just setting a bash variable because we need -# to pass this flag to all child processes spawned by the shell. -export CGO_CFLAGS="-O -D__BLST_PORTABLE__" -# While CGO_ENABLED doesn't need to be explicitly set, it produces a much more -# clear error due to the default value change in go1.20. -export CGO_ENABLED=1 - ################################# -# download avalanche-network-runner -# https://github.com/ava-labs/avalanche-network-runner -# TODO: migrate to upstream avalanche-network-runner -GOARCH=$(go env GOARCH) -GOOS=$(go env GOOS) -NETWORK_RUNNER_VERSION=1.3.5-rc.0 -DOWNLOAD_PATH=/tmp/avalanche-network-runner.tar.gz -DOWNLOAD_URL="https://github.com/ava-labs/avalanche-network-runner/releases/download/v${NETWORK_RUNNER_VERSION}/avalanche-network-runner_${NETWORK_RUNNER_VERSION}_${GOOS}_${GOARCH}.tar.gz" - -rm -f ${DOWNLOAD_PATH} -rm -f /tmp/avalanche-network-runner - -echo "downloading avalanche-network-runner ${NETWORK_RUNNER_VERSION} at ${DOWNLOAD_URL} to ${DOWNLOAD_PATH}" -curl --fail -L ${DOWNLOAD_URL} -o ${DOWNLOAD_PATH} - -echo "extracting downloaded avalanche-network-runner" -tar xzvf ${DOWNLOAD_PATH} -C /tmp -/tmp/avalanche-network-runner -h - -GOPATH="$(go env GOPATH)" -PATH="${GOPATH}/bin:${PATH}" +echo "installing avalanche-network-runner" +ANR_WORKDIR="/tmp" +./scripts/install_anr.sh ################################# echo "building e2e.test" @@ -60,23 +33,23 @@ ACK_GINKGO_RC=true ginkgo build ./tests/e2e ################################# # run "avalanche-network-runner" server echo "launch avalanche-network-runner in the background" -/tmp/avalanche-network-runner \ -server \ ---log-level debug \ ---port=":12342" \ ---disable-grpc-gateway & +$ANR_WORKDIR/avalanche-network-runner \ + server \ + --log-level debug \ + --port=":12342" \ + --disable-grpc-gateway & PID=${!} ################################# echo "running e2e tests against the local cluster with ${AVALANCHEGO_PATH}" ./tests/e2e/e2e.test \ ---ginkgo.v \ ---log-level debug \ ---network-runner-grpc-endpoint="0.0.0.0:12342" \ ---network-runner-avalanchego-path=${AVALANCHEGO_PATH} \ ---network-runner-avalanchego-log-level="WARN" \ ---test-keys-file=tests/test.insecure.secp256k1.keys \ -&& EXIT_CODE=$? || EXIT_CODE=$? + --ginkgo.v \ + --log-level debug \ + --network-runner-grpc-endpoint="0.0.0.0:12342" \ + --network-runner-avalanchego-path=${AVALANCHEGO_PATH} \ + --network-runner-avalanchego-log-level="WARN" \ + --test-keys-file=tests/test.insecure.secp256k1.keys && + EXIT_CODE=$? || EXIT_CODE=$? kill ${PID} diff --git a/scripts/tests.upgrade.sh b/scripts/tests.upgrade.sh index 64608fafbaf..14cba2b2a0e 100755 --- a/scripts/tests.upgrade.sh +++ b/scripts/tests.upgrade.sh @@ -12,14 +12,14 @@ fi VERSION=$1 if [[ -z "${VERSION}" ]]; then echo "Missing version argument!" - echo "Usage: ${0} [VERSION] [NEW-BINARY]" >> /dev/stderr + echo "Usage: ${0} [VERSION] [NEW-BINARY]" >>/dev/stderr exit 255 fi NEW_BINARY=$2 if [[ -z "${NEW_BINARY}" ]]; then echo "Missing new binary path argument!" - echo "Usage: ${0} [VERSION] [NEW-BINARY]" >> /dev/stderr + echo "Usage: ${0} [VERSION] [NEW-BINARY]" >>/dev/stderr exit 255 fi @@ -52,24 +52,9 @@ fi find /tmp/avalanchego-v${VERSION} ################################# -# download avalanche-network-runner -# https://github.com/ava-labs/avalanche-network-runner -NETWORK_RUNNER_VERSION=1.3.5-rc.0 -DOWNLOAD_PATH=/tmp/avalanche-network-runner.tar.gz -DOWNLOAD_URL="https://github.com/ava-labs/avalanche-network-runner/releases/download/v${NETWORK_RUNNER_VERSION}/avalanche-network-runner_${NETWORK_RUNNER_VERSION}_${GOOS}_${GOARCH}.tar.gz" -if [[ ${GOOS} == "darwin" ]]; then - DOWNLOAD_URL="https://github.com/ava-labs/avalanche-network-runner/releases/download/v${NETWORK_RUNNER_VERSION}/avalanche-network-runner_${NETWORK_RUNNER_VERSION}_darwin_amd64.tar.gz" -fi - -rm -f ${DOWNLOAD_PATH} -rm -f /tmp/avalanche-network-runner - -echo "downloading avalanche-network-runner ${NETWORK_RUNNER_VERSION} at ${DOWNLOAD_URL}" -curl -L ${DOWNLOAD_URL} -o ${DOWNLOAD_PATH} - -echo "extracting downloaded avalanche-network-runner" -tar xzvf ${DOWNLOAD_PATH} -C /tmp -/tmp/avalanche-network-runner -h +echo "installing avalanche-network-runner" +ANR_WORKDIR="/tmp" +./scripts/install_anr.sh ################################# echo "building upgrade.test" @@ -81,23 +66,23 @@ ACK_GINKGO_RC=true ginkgo build ./tests/upgrade ################################# # run "avalanche-network-runner" server echo "launch avalanche-network-runner in the background" -/tmp/avalanche-network-runner \ -server \ ---log-level debug \ ---port=":12340" \ ---disable-grpc-gateway & +$ANR_WORKDIR/avalanche-network-runner \ + server \ + --log-level debug \ + --port=":12340" \ + --disable-grpc-gateway & PID=${!} ################################# # By default, it runs all upgrade test cases! echo "running upgrade tests against the local cluster with ${NEW_BINARY}" ./tests/upgrade/upgrade.test \ ---ginkgo.v \ ---log-level debug \ ---network-runner-grpc-endpoint="0.0.0.0:12340" \ ---network-runner-avalanchego-path=/tmp/avalanchego-v${VERSION}/avalanchego \ ---network-runner-avalanchego-path-to-upgrade=${NEW_BINARY} \ ---network-runner-avalanchego-log-level="WARN" || EXIT_CODE=$? + --ginkgo.v \ + --log-level debug \ + --network-runner-grpc-endpoint="0.0.0.0:12340" \ + --network-runner-avalanchego-path=/tmp/avalanchego-v${VERSION}/avalanchego \ + --network-runner-avalanchego-path-to-upgrade=${NEW_BINARY} \ + --network-runner-avalanchego-log-level="WARN" || EXIT_CODE=$? # "e2e.test" already terminates the cluster # just in case tests are aborted, manually terminate them again diff --git a/vms/platformvm/warp/gwarp/client.go b/vms/platformvm/warp/gwarp/client.go index 96446fc8296..6619b4ff6ab 100644 --- a/vms/platformvm/warp/gwarp/client.go +++ b/vms/platformvm/warp/gwarp/client.go @@ -23,9 +23,9 @@ func NewClient(client pb.SignerClient) *Client { func (c *Client) Sign(unsignedMsg *warp.UnsignedMessage) ([]byte, error) { resp, err := c.client.Sign(context.Background(), &pb.SignRequest{ - SourceChainId: unsignedMsg.SourceChainID[:], - DestinationChainId: unsignedMsg.DestinationChainID[:], - Payload: unsignedMsg.Payload, + NetworkId: unsignedMsg.NetworkID, + SourceChainId: unsignedMsg.SourceChainID[:], + Payload: unsignedMsg.Payload, }) if err != nil { return nil, err diff --git a/vms/platformvm/warp/gwarp/server.go b/vms/platformvm/warp/gwarp/server.go index f1ac8964fa4..4fbee3a3e73 100644 --- a/vms/platformvm/warp/gwarp/server.go +++ b/vms/platformvm/warp/gwarp/server.go @@ -29,14 +29,9 @@ func (s *Server) Sign(_ context.Context, unsignedMsg *pb.SignRequest) (*pb.SignR return nil, err } - destinationChainID, err := ids.ToID(unsignedMsg.DestinationChainId) - if err != nil { - return nil, err - } - msg, err := warp.NewUnsignedMessage( + unsignedMsg.NetworkId, sourceChainID, - destinationChainID, unsignedMsg.Payload, ) if err != nil { diff --git a/vms/platformvm/warp/gwarp/signer_test.go b/vms/platformvm/warp/gwarp/signer_test.go index 3876b40966a..d1d6e8f7147 100644 --- a/vms/platformvm/warp/gwarp/signer_test.go +++ b/vms/platformvm/warp/gwarp/signer_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/rpcchainvm/grpcutils" @@ -17,11 +18,12 @@ import ( ) type testSigner struct { - client *Client - server warp.Signer - sk *bls.SecretKey - chainID ids.ID - closeFn func() + client *Client + server warp.Signer + sk *bls.SecretKey + networkID uint32 + chainID ids.ID + closeFn func() } func setupSigner(t testing.TB) *testSigner { @@ -33,9 +35,10 @@ func setupSigner(t testing.TB) *testSigner { chainID := ids.GenerateTestID() s := &testSigner{ - server: warp.NewSigner(sk, chainID), - sk: sk, - chainID: chainID, + server: warp.NewSigner(sk, constants.UnitTestID, chainID), + sk: sk, + networkID: constants.UnitTestID, + chainID: chainID, } listener, err := grpcutils.NewListener() @@ -63,7 +66,7 @@ func setupSigner(t testing.TB) *testSigner { func TestInterface(t *testing.T) { for _, test := range warp.SignerTests { s := setupSigner(t) - test(t, s.client, s.sk, s.chainID) + test(t, s.client, s.sk, s.networkID, s.chainID) s.closeFn() } } diff --git a/vms/platformvm/warp/message_test.go b/vms/platformvm/warp/message_test.go index f9df318314e..910abd3403c 100644 --- a/vms/platformvm/warp/message_test.go +++ b/vms/platformvm/warp/message_test.go @@ -10,6 +10,7 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" ) @@ -17,7 +18,7 @@ func TestMessage(t *testing.T) { require := require.New(t) unsignedMsg, err := NewUnsignedMessage( - ids.GenerateTestID(), + constants.UnitTestID, ids.GenerateTestID(), []byte("payload"), ) diff --git a/vms/platformvm/warp/signature.go b/vms/platformvm/warp/signature.go index df3973ccd63..1be4398509a 100644 --- a/vms/platformvm/warp/signature.go +++ b/vms/platformvm/warp/signature.go @@ -37,6 +37,7 @@ type Signature interface { Verify( ctx context.Context, msg *UnsignedMessage, + networkID uint32, pChainState validators.State, pChainHeight uint64, quorumNum uint64, @@ -67,11 +68,16 @@ func (s *BitSetSignature) NumSigners() (int, error) { func (s *BitSetSignature) Verify( ctx context.Context, msg *UnsignedMessage, + networkID uint32, pChainState validators.State, pChainHeight uint64, quorumNum uint64, quorumDen uint64, ) error { + if msg.NetworkID != networkID { + return errWrongNetworkID + } + subnetID, err := pChainState.GetSubnetID(ctx, msg.SourceChainID) if err != nil { return err diff --git a/vms/platformvm/warp/signature_test.go b/vms/platformvm/warp/signature_test.go index a28914f8830..46553cd3bde 100644 --- a/vms/platformvm/warp/signature_test.go +++ b/vms/platformvm/warp/signature_test.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/set" ) @@ -155,6 +156,7 @@ func TestSignatureVerification(t *testing.T) { tests := []struct { name string + networkID uint32 stateF func(*gomock.Controller) validators.State quorumNum uint64 quorumDen uint64 @@ -162,7 +164,8 @@ func TestSignatureVerification(t *testing.T) { err error }{ { - name: "can't get subnetID", + name: "can't get subnetID", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, errTest) @@ -172,8 +175,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 2, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, nil, ) require.NoError(err) @@ -188,7 +191,8 @@ func TestSignatureVerification(t *testing.T) { err: errTest, }, { - name: "can't get validator set", + name: "can't get validator set", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -199,8 +203,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 2, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, nil, ) require.NoError(err) @@ -215,7 +219,8 @@ func TestSignatureVerification(t *testing.T) { err: errTest, }, { - name: "weight overflow", + name: "weight overflow", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -238,6 +243,7 @@ func TestSignatureVerification(t *testing.T) { msgF: func(*require.Assertions) *Message { return &Message{ UnsignedMessage: UnsignedMessage{ + NetworkID: constants.UnitTestID, SourceChainID: sourceChainID, }, Signature: &BitSetSignature{ @@ -248,7 +254,8 @@ func TestSignatureVerification(t *testing.T) { err: ErrWeightOverflow, }, { - name: "invalid bit set index", + name: "invalid bit set index", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -259,8 +266,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 2, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -278,7 +285,8 @@ func TestSignatureVerification(t *testing.T) { err: ErrInvalidBitSet, }, { - name: "unknown index", + name: "unknown index", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -289,8 +297,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 2, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -311,7 +319,8 @@ func TestSignatureVerification(t *testing.T) { err: ErrUnknownValidator, }, { - name: "insufficient weight", + name: "insufficient weight", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -322,8 +331,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 1, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -355,7 +364,8 @@ func TestSignatureVerification(t *testing.T) { err: ErrInsufficientWeight, }, { - name: "can't parse sig", + name: "can't parse sig", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -366,8 +376,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 2, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -389,7 +399,8 @@ func TestSignatureVerification(t *testing.T) { err: ErrParseSignature, }, { - name: "no validators", + name: "no validators", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -400,8 +411,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 2, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -424,7 +435,8 @@ func TestSignatureVerification(t *testing.T) { err: bls.ErrNoPublicKeys, }, { - name: "invalid signature (substitute)", + name: "invalid signature (substitute)", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -435,8 +447,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 5, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -468,7 +480,8 @@ func TestSignatureVerification(t *testing.T) { err: ErrInvalidSignature, }, { - name: "invalid signature (missing one)", + name: "invalid signature (missing one)", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -479,8 +492,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 5, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -508,7 +521,8 @@ func TestSignatureVerification(t *testing.T) { err: ErrInvalidSignature, }, { - name: "invalid signature (extra one)", + name: "invalid signature (extra one)", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -519,8 +533,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 5, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -553,7 +567,8 @@ func TestSignatureVerification(t *testing.T) { err: ErrInvalidSignature, }, { - name: "valid signature", + name: "valid signature", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -564,8 +579,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 2, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -597,7 +612,8 @@ func TestSignatureVerification(t *testing.T) { err: nil, }, { - name: "valid signature (boundary)", + name: "valid signature (boundary)", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -608,8 +624,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 3, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -641,7 +657,8 @@ func TestSignatureVerification(t *testing.T) { err: nil, }, { - name: "valid signature (missing key)", + name: "valid signature (missing key)", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -668,8 +685,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 3, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -702,7 +719,8 @@ func TestSignatureVerification(t *testing.T) { err: nil, }, { - name: "valid signature (duplicate key)", + name: "valid signature (duplicate key)", + networkID: constants.UnitTestID, stateF: func(ctrl *gomock.Controller) validators.State { state := validators.NewMockState(ctrl) state.EXPECT().GetSubnetID(gomock.Any(), sourceChainID).Return(subnetID, nil) @@ -729,8 +747,8 @@ func TestSignatureVerification(t *testing.T) { quorumDen: 3, msgF: func(require *require.Assertions) *Message { unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID, sourceChainID, - ids.Empty, []byte{1, 2, 3}, ) require.NoError(err) @@ -760,6 +778,49 @@ func TestSignatureVerification(t *testing.T) { }, err: nil, }, + { + name: "incorrect networkID", + networkID: constants.UnitTestID, + stateF: func(ctrl *gomock.Controller) validators.State { + state := validators.NewMockState(ctrl) + return state + }, + quorumNum: 1, + quorumDen: 2, + msgF: func(require *require.Assertions) *Message { + unsignedMsg, err := NewUnsignedMessage( + constants.UnitTestID+1, + sourceChainID, + []byte{1, 2, 3}, + ) + require.NoError(err) + + // [signers] has weight from [vdr[1], vdr[2]], + // which is 6, which is greater than 4.5 + signers := set.NewBits() + signers.Add(1) + signers.Add(2) + + unsignedBytes := unsignedMsg.Bytes() + vdr1Sig := bls.Sign(testVdrs[1].sk, unsignedBytes) + vdr2Sig := bls.Sign(testVdrs[2].sk, unsignedBytes) + aggSig, err := bls.AggregateSignatures([]*bls.Signature{vdr1Sig, vdr2Sig}) + require.NoError(err) + aggSigBytes := [bls.SignatureLen]byte{} + copy(aggSigBytes[:], bls.SignatureToBytes(aggSig)) + + msg, err := NewMessage( + unsignedMsg, + &BitSetSignature{ + Signers: signers.Bytes(), + Signature: aggSigBytes, + }, + ) + require.NoError(err) + return msg + }, + err: errWrongNetworkID, + }, } for _, tt := range tests { @@ -774,6 +835,7 @@ func TestSignatureVerification(t *testing.T) { err := msg.Signature.Verify( context.Background(), &msg.UnsignedMessage, + tt.networkID, pChainState, pChainHeight, tt.quorumNum, diff --git a/vms/platformvm/warp/signer.go b/vms/platformvm/warp/signer.go index dddb0816def..badf52710b4 100644 --- a/vms/platformvm/warp/signer.go +++ b/vms/platformvm/warp/signer.go @@ -14,6 +14,7 @@ var ( _ Signer = (*signer)(nil) errWrongSourceChainID = errors.New("wrong SourceChainID") + errWrongNetworkID = errors.New("wrong networkID") ) type Signer interface { @@ -25,22 +26,27 @@ type Signer interface { Sign(msg *UnsignedMessage) ([]byte, error) } -func NewSigner(sk *bls.SecretKey, chainID ids.ID) Signer { +func NewSigner(sk *bls.SecretKey, networkID uint32, chainID ids.ID) Signer { return &signer{ - sk: sk, - chainID: chainID, + sk: sk, + networkID: networkID, + chainID: chainID, } } type signer struct { - sk *bls.SecretKey - chainID ids.ID + sk *bls.SecretKey + networkID uint32 + chainID ids.ID } func (s *signer) Sign(msg *UnsignedMessage) ([]byte, error) { if msg.SourceChainID != s.chainID { return nil, errWrongSourceChainID } + if msg.NetworkID != s.networkID { + return nil, errWrongNetworkID + } msgBytes := msg.Bytes() sig := bls.Sign(s.sk, msgBytes) diff --git a/vms/platformvm/warp/signer_test.go b/vms/platformvm/warp/signer_test.go index 46ee6eeba3f..d4e83c24a85 100644 --- a/vms/platformvm/warp/signer_test.go +++ b/vms/platformvm/warp/signer_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" ) @@ -18,8 +19,8 @@ func TestSigner(t *testing.T) { require.NoError(t, err) chainID := ids.GenerateTestID() - s := NewSigner(sk, chainID) + s := NewSigner(sk, constants.UnitTestID, chainID) - test(t, s, sk, chainID) + test(t, s, sk, constants.UnitTestID, chainID) } } diff --git a/vms/platformvm/warp/test_signer.go b/vms/platformvm/warp/test_signer.go index aee6616ddac..2b2dd8adde2 100644 --- a/vms/platformvm/warp/test_signer.go +++ b/vms/platformvm/warp/test_signer.go @@ -9,21 +9,22 @@ import ( "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" ) // SignerTests is a list of all signer tests -var SignerTests = []func(t *testing.T, s Signer, sk *bls.SecretKey, chainID ids.ID){ +var SignerTests = []func(t *testing.T, s Signer, sk *bls.SecretKey, networkID uint32, chainID ids.ID){ TestSignerWrongChainID, TestSignerVerifies, } // Test that using a random SourceChainID results in an error -func TestSignerWrongChainID(t *testing.T, s Signer, _ *bls.SecretKey, _ ids.ID) { +func TestSignerWrongChainID(t *testing.T, s Signer, _ *bls.SecretKey, _ uint32, _ ids.ID) { require := require.New(t) msg, err := NewUnsignedMessage( - ids.GenerateTestID(), + constants.UnitTestID, ids.GenerateTestID(), []byte("payload"), ) @@ -34,13 +35,29 @@ func TestSignerWrongChainID(t *testing.T, s Signer, _ *bls.SecretKey, _ ids.ID) require.Error(err) //nolint:forbidigo // currently returns grpc errors too } +// Test that using a different networkID results in an error +func TestSignerWrongNetworkID(t *testing.T, s Signer, _ *bls.SecretKey, networkID uint32, blockchainID ids.ID) { + require := require.New(t) + + msg, err := NewUnsignedMessage( + networkID+1, + blockchainID, + []byte("payload"), + ) + require.NoError(err) + + _, err = s.Sign(msg) + // TODO: require error to be errWrongNetworkID + require.Error(err) //nolint:forbidigo // currently returns grpc errors too +} + // Test that a signature generated with the signer verifies correctly -func TestSignerVerifies(t *testing.T, s Signer, sk *bls.SecretKey, chainID ids.ID) { +func TestSignerVerifies(t *testing.T, s Signer, sk *bls.SecretKey, networkID uint32, chainID ids.ID) { require := require.New(t) msg, err := NewUnsignedMessage( + networkID, chainID, - ids.GenerateTestID(), []byte("payload"), ) require.NoError(err) diff --git a/vms/platformvm/warp/unsigned_message.go b/vms/platformvm/warp/unsigned_message.go index be266834a39..95ef0d2d07f 100644 --- a/vms/platformvm/warp/unsigned_message.go +++ b/vms/platformvm/warp/unsigned_message.go @@ -12,9 +12,9 @@ import ( // UnsignedMessage defines the standard format for an unsigned Warp message. type UnsignedMessage struct { - SourceChainID ids.ID `serialize:"true"` - DestinationChainID ids.ID `serialize:"true"` - Payload []byte `serialize:"true"` + NetworkID uint32 `serialize:"true"` + SourceChainID ids.ID `serialize:"true"` + Payload []byte `serialize:"true"` bytes []byte id ids.ID @@ -22,14 +22,14 @@ type UnsignedMessage struct { // NewUnsignedMessage creates a new *UnsignedMessage and initializes it. func NewUnsignedMessage( + networkID uint32, sourceChainID ids.ID, - destinationChainID ids.ID, payload []byte, ) (*UnsignedMessage, error) { msg := &UnsignedMessage{ - SourceChainID: sourceChainID, - DestinationChainID: destinationChainID, - Payload: payload, + NetworkID: networkID, + SourceChainID: sourceChainID, + Payload: payload, } return msg, msg.Initialize() } diff --git a/vms/platformvm/warp/unsigned_message_test.go b/vms/platformvm/warp/unsigned_message_test.go index e9029aec7df..f3be73ef6c7 100644 --- a/vms/platformvm/warp/unsigned_message_test.go +++ b/vms/platformvm/warp/unsigned_message_test.go @@ -10,13 +10,14 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" ) func TestUnsignedMessage(t *testing.T) { require := require.New(t) msg, err := NewUnsignedMessage( - ids.GenerateTestID(), + constants.UnitTestID, ids.GenerateTestID(), []byte("payload"), )