|
| 1 | +// Copyright 2024 Blink Labs Software |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +// you may not use this file except in compliance with the License. |
| 5 | +// You may obtain a copy of the License at |
| 6 | +// |
| 7 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +// |
| 9 | +// Unless required by applicable law or agreed to in writing, software |
| 10 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +// See the License for the specific language governing permissions and |
| 13 | +// limitations under the License. |
| 14 | + |
| 15 | +package common_test |
| 16 | + |
| 17 | +import ( |
| 18 | + "encoding/hex" |
| 19 | + "testing" |
| 20 | + |
| 21 | + "github.com/blinklabs-io/gouroboros/ledger/common" |
| 22 | +) |
| 23 | + |
| 24 | +func TestNonceUnmarshalCBOR(t *testing.T) { |
| 25 | + testCases := []struct { |
| 26 | + name string |
| 27 | + data []byte |
| 28 | + expectedErr string |
| 29 | + }{ |
| 30 | + { |
| 31 | + name: "NonceTypeNeutral", |
| 32 | + data: []byte{0x81, 0x00}, |
| 33 | + }, |
| 34 | + { |
| 35 | + name: "NonceTypeNonce", |
| 36 | + data: []byte{0x82, 0x01, 0x42, 0x01, 0x02}, |
| 37 | + }, |
| 38 | + { |
| 39 | + name: "UnsupportedNonceType", |
| 40 | + data: []byte{0x82, 0x02}, |
| 41 | + expectedErr: "unsupported nonce type 2", |
| 42 | + }, |
| 43 | + } |
| 44 | + |
| 45 | + for _, tc := range testCases { |
| 46 | + t.Run(tc.name, func(t *testing.T) { |
| 47 | + n := &common.Nonce{} |
| 48 | + err := n.UnmarshalCBOR(tc.data) |
| 49 | + if err != nil { |
| 50 | + if tc.expectedErr == "" || err.Error() != tc.expectedErr { |
| 51 | + t.Errorf("unexpected error: %v", err) |
| 52 | + } |
| 53 | + } else if tc.expectedErr != "" { |
| 54 | + t.Errorf("expected error: %v, got nil", tc.expectedErr) |
| 55 | + } |
| 56 | + }) |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +func TestCalculateRollingNonce(t *testing.T) { |
| 61 | + testDefs := []struct { |
| 62 | + prevBlockNonce string |
| 63 | + blockVrf string |
| 64 | + expectedNonce string |
| 65 | + }{ |
| 66 | + { |
| 67 | + // Shelley genesis hash (mainnet) |
| 68 | + prevBlockNonce: "1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81", |
| 69 | + blockVrf: "36ec5378d1f5041a59eb8d96e61de96f0950fb41b49ff511f7bc7fd109d4383e1d24be7034e6749c6612700dd5ceb0c66577b88a19ae286b1321d15bce1ab736", |
| 70 | + expectedNonce: "2af15f57076a8ff225746624882a77c8d2736fe41d3db70154a22b50af851246", |
| 71 | + }, |
| 72 | + { |
| 73 | + blockVrf: "e0bf34a6b73481302f22987cde4c12807cbc2c3fea3f7fcb77261385a50e8ccdda3226db3efff73e9fb15eecf841bbc85ce37550de0435ebcdcb205e0ed08467", |
| 74 | + expectedNonce: "a815ff978369b57df09b0072485c26920dc0ec8e924a852a42f0715981cf0042", |
| 75 | + }, |
| 76 | + { |
| 77 | + blockVrf: "7107ef8c16058b09f4489715297e55d145a45fc0df75dfb419cab079cd28992854a034ad9dc4c764544fb70badd30a9611a942a03523c6f3d8967cf680c4ca6b", |
| 78 | + expectedNonce: "f112d91435b911b6b5acaf27198762905b1cdec8c5a7b712f925ce3c5c76bb5f", |
| 79 | + }, |
| 80 | + { |
| 81 | + blockVrf: "6f561aad83884ee0d7b19fd3d757c6af096bfd085465d1290b13a9dfc817dfcdfb0b59ca06300206c64d1ba75fd222a88ea03c54fbbd5d320b4fbcf1c228ba4e", |
| 82 | + expectedNonce: "5450d95d9be4194a0ded40fbb4036b48d1f1d6da796e933fefd2c5c888794b4b", |
| 83 | + }, |
| 84 | + { |
| 85 | + blockVrf: "3d3ba80724db0a028783afa56a85d684ee778ae45b9aa9af3120f5e1847be1983bd4868caf97fcfd82d5a3b0b7c1a6d53491d75440a75198014eb4e707785cad", |
| 86 | + expectedNonce: "c5c0f406cb522ad3fead4ecc60bce9c31e80879bc17eb1bb9acaa9b998cdf8bf", |
| 87 | + }, |
| 88 | + { |
| 89 | + blockVrf: "0b07976bc04321c2e7ba0f1acb3c61bd92b5fc780a855632e30e6746ab4ac4081490d816928762debd3e512d22ad512a558612adc569718df1784261f5c26aff", |
| 90 | + expectedNonce: "5857048c728580549de645e087ba20ef20bb7c51cc84b5bc89df6b8b0ed98c41", |
| 91 | + }, |
| 92 | + { |
| 93 | + blockVrf: "5e9e001fb1e2ddb0dc7ff40af917ecf4ba9892491d4bcbf2c81db2efc57627d40d7aac509c9bcf5070d4966faaeb84fd76bb285af2e51af21a8c024089f598c1", |
| 94 | + expectedNonce: "d6f40ef403687115db061b2cb9b1ab4ddeb98222075d5a3e03c8d217d4d7c40e", |
| 95 | + }, |
| 96 | + { |
| 97 | + blockVrf: "182e83f8c67ad2e6bddead128e7108499ebcbc272b50c42783ef08f035aa688fecc7d15be15a90dbfe7fe5d7cd9926987b6ec12b05f2eadfe0eb6cad5130aca4", |
| 98 | + expectedNonce: "5489d75a9f4971c1824462b5e2338609a91f121241f21fee09811bd5772ae0a8", |
| 99 | + }, |
| 100 | + { |
| 101 | + blockVrf: "275e7404b2385a9d606d67d0e29f5516fb84c1c14aaaf91afa9a9b3dcdfe09075efdadbaf158cfa1e9f250cc7c691ed2db4a29288d2426bd74a371a2a4b91b57", |
| 102 | + expectedNonce: "04716326833ecdb595153adac9566a4b39e5c16e8d02526cb4166e4099a00b1a", |
| 103 | + }, |
| 104 | + { |
| 105 | + blockVrf: "0f35c7217792f8b0cbb721ae4ae5c9ae7f2869df49a3db256aacc10d23997a09e0273261b44ebbcecd6bf916f2c1cd79cf25b0c2851645d75dd0747a8f6f92f5", |
| 106 | + expectedNonce: "39db709f50c8a279f0a94adcefb9360dbda6cdce168aed4288329a9cd53492b6", |
| 107 | + }, |
| 108 | + { |
| 109 | + blockVrf: "14c28bf9b10421e9f90ffc9ab05df0dc8c8a07ffac1c51725fba7e2b7972d0769baea248f93ed0f2067d11d719c2858c62fc1d8d59927b41d4c0fbc68d805b32", |
| 110 | + expectedNonce: "c784b8c8678e0a04748a3ad851dd7c34ed67141cd9dc0c50ceaff4df804699a7", |
| 111 | + }, |
| 112 | + { |
| 113 | + blockVrf: "e4ce96fee9deb9378a107db48587438cddf8e20a69e21e5e4fbd35ef0c56530df77eba666cb152812111ba66bbd333ed44f627c727115f8f4f15b31726049a19", |
| 114 | + expectedNonce: "cc1a5861358c075de93a26a91c5a951d5e71190d569aa2dc786d4ca8fc80cc38", |
| 115 | + }, |
| 116 | + { |
| 117 | + blockVrf: "b38f315e3ce369ea2551bf4f44e723dd15c7d67ba4b3763997909f65e46267d6540b9b00a7a65ae3d1f3a3316e57a821aeaac33e4e42ded415205073134cd185", |
| 118 | + expectedNonce: "514979c89313c49e8f59fb8445113fa7623e99375cc4917fe79df54f8d4bdfce", |
| 119 | + }, |
| 120 | + { |
| 121 | + blockVrf: "4bcbf774af9c8ff24d4d96099001ec06a24802c88fea81680ea2411392d32dbd9b9828a690a462954b894708d511124a2db34ec4179841e07a897169f0f1ac0e", |
| 122 | + expectedNonce: "6a783e04481b9e04e8f3498a3b74c90c06a1031fb663b6793ce592a6c26f56f4", |
| 123 | + }, |
| 124 | + { |
| 125 | + blockVrf: "65247ace6355f978a12235265410c44f3ded02849ec8f8e6db2ac705c3f57d322ea073c13cf698e15d7e1d7f2bc95e7b3533be0dee26f58864f1664df0c1ebba", |
| 126 | + expectedNonce: "1190f5254599dcee4f3cf1afdf4181085c36a6db6c30f334bfe6e6f320a6ed91", |
| 127 | + }, |
| 128 | + } |
| 129 | + var rollingNonce []byte |
| 130 | + for _, testDef := range testDefs { |
| 131 | + // Populate initial nonce |
| 132 | + if testDef.prevBlockNonce != "" { |
| 133 | + tmpNonce, err := hex.DecodeString(testDef.prevBlockNonce) |
| 134 | + if err != nil { |
| 135 | + t.Fatalf("unexpected error: %s", err) |
| 136 | + } |
| 137 | + rollingNonce = tmpNonce |
| 138 | + } |
| 139 | + blockVrfBytes, err := hex.DecodeString(testDef.blockVrf) |
| 140 | + if err != nil { |
| 141 | + t.Fatalf("unexpected error: %s", err) |
| 142 | + } |
| 143 | + nonce, err := common.CalculateRollingNonce(rollingNonce, blockVrfBytes) |
| 144 | + if err != nil { |
| 145 | + t.Fatalf("unexpected error: %s", err) |
| 146 | + } |
| 147 | + nonceHex := hex.EncodeToString(nonce.Bytes()) |
| 148 | + if nonceHex != testDef.expectedNonce { |
| 149 | + t.Fatalf("did not get expected nonce value: got %s, wanted %s", nonceHex, testDef.expectedNonce) |
| 150 | + } |
| 151 | + rollingNonce = nonce.Bytes() |
| 152 | + } |
| 153 | +} |
| 154 | + |
| 155 | +func TestCalculateEpochNonce(t *testing.T) { |
| 156 | + testDefs := []struct { |
| 157 | + stableBlockNonce string |
| 158 | + prevEpochFirstBlockHash string |
| 159 | + extraEntropy string |
| 160 | + expectedNonce string |
| 161 | + }{ |
| 162 | + { |
| 163 | + stableBlockNonce: "e86e133bd48ff5e79bec43af1ac3e348b539172f33e502d2c96735e8c51bd04d", |
| 164 | + prevEpochFirstBlockHash: "d7a1ff2a365abed59c9ae346cba842b6d3df06d055dba79a113e0704b44cc3e9", |
| 165 | + expectedNonce: "e536a0081ddd6d19786e9d708a85819a5c3492c0da7349f59c8ad3e17e4acd98", |
| 166 | + }, |
| 167 | + { |
| 168 | + stableBlockNonce: "d1340a9c1491f0face38d41fd5c82953d0eb48320d65e952414a0c5ebaf87587", |
| 169 | + prevEpochFirstBlockHash: "ee91d679b0a6ce3015b894c575c799e971efac35c7a8cbdc2b3f579005e69abd", |
| 170 | + extraEntropy: "d982e06fd33e7440b43cefad529b7ecafbaa255e38178ad4189a37e4ce9bf1fa", |
| 171 | + expectedNonce: "0022cfa563a5328c4fb5c8017121329e964c26ade5d167b1bd9b2ec967772b60", |
| 172 | + }, |
| 173 | + } |
| 174 | + for _, testDef := range testDefs { |
| 175 | + stableBlockNonce, err := hex.DecodeString(testDef.stableBlockNonce) |
| 176 | + if err != nil { |
| 177 | + t.Fatalf("unexpected error: %s", err) |
| 178 | + } |
| 179 | + prevEpochFirstBlockHash, err := hex.DecodeString(testDef.prevEpochFirstBlockHash) |
| 180 | + if err != nil { |
| 181 | + t.Fatalf("unexpected error: %s", err) |
| 182 | + } |
| 183 | + var extraEntropy []byte |
| 184 | + if testDef.extraEntropy != "" { |
| 185 | + tmpEntropy, err := hex.DecodeString(testDef.extraEntropy) |
| 186 | + if err != nil { |
| 187 | + t.Fatalf("unexpected error: %s", err) |
| 188 | + } |
| 189 | + extraEntropy = tmpEntropy |
| 190 | + } |
| 191 | + tmpNonce, err := common.CalculateEpochNonce(stableBlockNonce, prevEpochFirstBlockHash, extraEntropy) |
| 192 | + if err != nil { |
| 193 | + t.Fatalf("unexpected error: %s", err) |
| 194 | + } |
| 195 | + tmpNonceHex := hex.EncodeToString(tmpNonce.Bytes()) |
| 196 | + if tmpNonceHex != testDef.expectedNonce { |
| 197 | + t.Fatalf("did not get expected epoch nonce: got %s, wanted %s", tmpNonceHex, testDef.expectedNonce) |
| 198 | + } |
| 199 | + } |
| 200 | +} |
0 commit comments