github.com/MetalBlockchain/metalgo@v1.11.9/vms/proposervm/block/parse_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package block 5 6 import ( 7 "crypto" 8 "encoding/hex" 9 "testing" 10 "time" 11 12 "github.com/stretchr/testify/require" 13 14 "github.com/MetalBlockchain/metalgo/codec" 15 "github.com/MetalBlockchain/metalgo/ids" 16 "github.com/MetalBlockchain/metalgo/staking" 17 ) 18 19 func TestParse(t *testing.T) { 20 parentID := ids.ID{1} 21 timestamp := time.Unix(123, 0) 22 pChainHeight := uint64(2) 23 innerBlockBytes := []byte{3} 24 chainID := ids.ID{4} 25 26 tlsCert, err := staking.NewTLSCert() 27 require.NoError(t, err) 28 29 cert, err := staking.ParseCertificate(tlsCert.Leaf.Raw) 30 require.NoError(t, err) 31 key := tlsCert.PrivateKey.(crypto.Signer) 32 33 signedBlock, err := Build( 34 parentID, 35 timestamp, 36 pChainHeight, 37 cert, 38 innerBlockBytes, 39 chainID, 40 key, 41 ) 42 require.NoError(t, err) 43 44 unsignedBlock, err := BuildUnsigned(parentID, timestamp, pChainHeight, innerBlockBytes) 45 require.NoError(t, err) 46 47 signedWithoutCertBlockIntf, err := BuildUnsigned(parentID, timestamp, pChainHeight, innerBlockBytes) 48 require.NoError(t, err) 49 signedWithoutCertBlock := signedWithoutCertBlockIntf.(*statelessBlock) 50 signedWithoutCertBlock.Signature = []byte{5} 51 52 signedWithoutCertBlock.bytes, err = Codec.Marshal(CodecVersion, &signedWithoutCertBlockIntf) 53 require.NoError(t, err) 54 55 optionBlock, err := BuildOption(parentID, innerBlockBytes) 56 require.NoError(t, err) 57 58 tests := []struct { 59 name string 60 block Block 61 chainID ids.ID 62 expectedErr error 63 }{ 64 { 65 name: "correct chainID", 66 block: signedBlock, 67 chainID: chainID, 68 expectedErr: nil, 69 }, 70 { 71 name: "invalid chainID", 72 block: signedBlock, 73 chainID: ids.ID{5}, 74 expectedErr: staking.ErrECDSAVerificationFailure, 75 }, 76 { 77 name: "unsigned block", 78 block: unsignedBlock, 79 chainID: chainID, 80 expectedErr: nil, 81 }, 82 { 83 name: "invalid signature", 84 block: signedWithoutCertBlockIntf, 85 chainID: chainID, 86 expectedErr: errUnexpectedSignature, 87 }, 88 { 89 name: "option block", 90 block: optionBlock, 91 chainID: chainID, 92 expectedErr: nil, 93 }, 94 } 95 for _, test := range tests { 96 t.Run(test.name, func(t *testing.T) { 97 require := require.New(t) 98 99 blockBytes := test.block.Bytes() 100 parsedBlockWithoutVerification, err := ParseWithoutVerification(blockBytes) 101 require.NoError(err) 102 equal(require, test.block, parsedBlockWithoutVerification) 103 104 parsedBlock, err := Parse(blockBytes, test.chainID) 105 require.ErrorIs(err, test.expectedErr) 106 if test.expectedErr == nil { 107 equal(require, test.block, parsedBlock) 108 } 109 }) 110 } 111 } 112 113 func TestParseBytes(t *testing.T) { 114 chainID := ids.ID{4} 115 tests := []struct { 116 name string 117 hex string 118 expectedErr error 119 }{ 120 { 121 name: "duplicate extensions in certificate", 122 hex: "0000000000000100000000000000000000000000000000000000000000000000000000000000000000000000007b0000000000000002000004bd308204b9308202a1a003020102020100300d06092a864886f70d01010b050030003020170d3939313233313030303030305a180f32313232303830333233323835335a300030820222300d06092a864886f70d01010105000382020f003082020a0282020100c2b2de1c16924d9b9254a0d5b80a4bc5f9beaa4f4f40a0e4efb69eb9b55d7d37f8c82328c237d7c5b451f5427b487284fa3f365f9caa53c7fcfef8d7a461d743bd7d88129f2da62b877ebe9d6feabf1bd12923e6c12321382c782fc3bb6b6cb4986a937a1edc3814f4e621e1a62053deea8c7649e43edd97ab6b56315b00d9ab5026bb9c31fb042dc574ba83c54e720e0120fcba2e8a66b77839be3ece0d4a6383ef3f76aac952b49a15b65e18674cd1340c32cecbcbaf80ae45be001366cb56836575fb0ab51ea44bf7278817e99b6b180fdd110a49831a132968489822c56692161bbd372cf89d9b8ee5a734cff15303b3a960ee78d79e76662a701941d9ec084429f26707f767e9b1d43241c0e4f96655d95c1f4f4aa00add78eff6bf0a6982766a035bf0b465786632c5bb240788ca0fdf032d8815899353ea4bec5848fd30118711e5b356bde8a0da074cc25709623225e734ff5bd0cf65c40d9fd8fccf746d8f8f35145bcebcf378d2b086e57d78b11e84f47fa467c4d037f92bff6dd4e934e0189b58193f24c4222ffb72b5c06361cf68ca64345bc3e230cc0f40063ad5f45b1659c643662996328c2eeddcd760d6f7c9cbae081ccc065844f7ea78c858564a408979764de882793706acc67d88092790dff567ed914b03355330932616a0f26f994b963791f0b1dbd8df979db86d1ea490700a3120293c3c2b10bef10203010001a33c303a300e0603551d0f0101ff0404030204b030130603551d25040c300a06082b0601050507030230130603551d25040c300a06082b06010505070302300d06092a864886f70d01010b05000382020100a21a0d73ec9ef4eb39f810557ac70b0b775772b8bae5f42c98565bc50b5b2c57317aa9cb1da12f55d0aac7bb36a00cd4fd0d7384c4efa284b53520c5a3c4b8a65240b393eeab02c802ea146c0728c3481c9e8d3aaad9d4dd7607103dcfaa96da83460adbe18174ed5b71bde7b0a93d4fb52234a9ff54e3fd25c5b74790dfb090f2e59dc5907357f510cc3a0b70ccdb87aee214def794b316224f318b471ffa13b66e44b467670e881cb1628c99c048a503376d9b6d7b8eef2e7be47ff7d5c1d56221f4cf7fa2519b594cb5917815c64dc75d8d281bcc99b5a12899b08f2ca0f189857b64a1afc5963337f3dd6e79390e85221569f6dbbb13aadce06a3dfb5032f0cc454809627872cd7cd0cea5eba187723f07652c8abc3fc42bd62136fc66287f2cc19a7cb416923ad1862d7f820b55cacb65e43731cb6df780e2651e457a3438456aeeeb278ad9c0ad2e760f6c1cbe276eeb621c8a4e609b5f2d902beb3212e3e45df99497021ff536d0b56390c5d785a8bf7909f6b61bdc705d7d92ae22f58e7b075f164a0450d82d8286bf449072751636ab5185f59f518b845a75d112d6f7b65223479202cff67635e2ad88106bc8a0cc9352d87c5b182ac19a4680a958d814a093acf46730f87da0df6926291d02590f215041b44a0a1a32eeb3a52cddabc3d256689bace18a8d85e644cf9137cce3718f7caac1cb16ae06e874f4c701000000010300000200b8e3a4d9a4394bac714cb597f5ba1a81865185e35c782d0317e7abc0b52d49ff8e10f787bedf86f08148e3dbd2d2d478caa2a2893d31db7d5ee51339883fe84d3004440f16cb3797a7fab0f627d3ebd79217e995488e785cd6bb7b96b9d306f8109daa9cfc4162f9839f60fb965bcb3b56a5fa787549c153a4c80027398f73a617b90b7f24f437b140cd3ac832c0b75ec98b9423b275782988a9fd426937b8f82fbb0e88a622934643fb6335c1a080a4d13125544b04585d5f5295be7cd2c8be364246ea3d5df3e837b39a85074575a1fa2f4799050460110bdfb20795c8a9172a20f61b95e1c5c43eccd0c2c155b67385366142c63409cb3fb488e7aba6c8930f7f151abf1c24a54bd21c3f7a06856ea9db35beddecb30d2c61f533a3d0590bdbb438c6f2a2286dfc3c71b383354f0abad72771c2cc3687b50c2298783e53857cf26058ed78d0c1cf53786eb8d006a058ee3c85a7b2b836b5d03ef782709ce8f2725548e557b3de45a395a669a15f1d910e97015d22ac70020cab7e2531e8b1f739b023b49e742203e9e19a7fe0053826a9a2fe2e118d3b83498c2cb308573202ad41aa4a390aee4b6b5dd2164e5c5cd1b5f68b7d5632cf7dbb9a9139663c9aac53a74b2c6fc73cad80e228a186ba027f6f32f0182d62503e04fcced385f2e7d2e11c00940622ebd533b4d144689082f9777e5b16c36f9af9066e0ad6564d43", 123 expectedErr: nil, 124 }, 125 { 126 name: "gibberish", 127 hex: "000102030405", 128 expectedErr: codec.ErrUnknownVersion, 129 }, 130 } 131 for _, test := range tests { 132 t.Run(test.name, func(t *testing.T) { 133 require := require.New(t) 134 135 bytes, err := hex.DecodeString(test.hex) 136 require.NoError(err) 137 138 _, err = Parse(bytes, chainID) 139 require.ErrorIs(err, test.expectedErr) 140 }) 141 } 142 } 143 144 func TestParseHeader(t *testing.T) { 145 require := require.New(t) 146 147 chainID := ids.ID{1} 148 parentID := ids.ID{2} 149 bodyID := ids.ID{3} 150 151 builtHeader, err := BuildHeader( 152 chainID, 153 parentID, 154 bodyID, 155 ) 156 require.NoError(err) 157 158 builtHeaderBytes := builtHeader.Bytes() 159 160 parsedHeader, err := ParseHeader(builtHeaderBytes) 161 require.NoError(err) 162 163 equalHeader(require, builtHeader, parsedHeader) 164 }