packages feed

musig2-0.2.0: test/NonceGen.hs

{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module NonceGen (testNonceGen) where

import Crypto.Curve.Secp256k1 (Pub)
import Crypto.Curve.Secp256k1.MuSig2 (PubNonce (..), SecKey (..), SecNonceGenParams (..), publicNonce, secNonceGenWithRand)
import Crypto.Curve.Secp256k1.MuSig2.Internal (secNonceScalars)
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Test.Tasty
import Test.Tasty.HUnit
import Util (decodeHex, parsePoint, parseScalar, unsafeRight)

-- | Test vector structure.
data NonceGenTestVector = NonceGenTestVector
  { rand_ :: BS.ByteString
  , sk :: Maybe Integer
  , pk :: Pub
  , aggpk :: Maybe Pub
  , msg :: Maybe ByteString
  , extra_in :: Maybe ByteString
  , expected_k1 :: Integer
  , expected_k2 :: Integer
  , expected_r1 :: Pub
  , expected_r2 :: Pub
  }

-- | Hardcoded test vectors from @bip-0327/vectors/nonce_gen_vectors.json@.
testVectors :: [NonceGenTestVector]
testVectors =
  [ NonceGenTestVector
      { rand_ = decodeHex "0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F"
      , sk = Just 0x0202020202020202020202020202020202020202020202020202020202020202
      , pk = parsePoint "024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766"
      , aggpk = Just $ parsePoint "0707070707070707070707070707070707070707070707070707070707070707"
      , msg = Just $ decodeHex "0101010101010101010101010101010101010101010101010101010101010101"
      , extra_in = Just $ decodeHex "0808080808080808080808080808080808080808080808080808080808080808"
      , expected_k1 = parseScalar "B114E502BEAA4E301DD08A50264172C84E41650E6CB726B410C0694D59EFFB64"
      , expected_k2 = parseScalar "95B5CAF28D045B973D63E3C99A44B807BDE375FD6CB39E46DC4A511708D0E9D2"
      , expected_r1 = parsePoint "02F7BE7089E8376EB355272368766B17E88E7DB72047D05E56AA881EA52B3B35DF"
      , expected_r2 = parsePoint "02C29C8046FDD0DED4C7E55869137200FBDBFE2EB654267B6D7013602CAED3115A"
      }
  , NonceGenTestVector
      { rand_ = decodeHex "0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F"
      , sk = Just 0x0202020202020202020202020202020202020202020202020202020202020202
      , pk = parsePoint "024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766"
      , aggpk = Just $ parsePoint "0707070707070707070707070707070707070707070707070707070707070707"
      , msg = Just $ decodeHex ""
      , extra_in = Just $ decodeHex "0808080808080808080808080808080808080808080808080808080808080808"
      , expected_k1 = parseScalar "E862B068500320088138468D47E0E6F147E01B6024244AE45EAC40ACE5929B9F"
      , expected_k2 = parseScalar "0789E051170B9E705D0B9EB49049A323BBBBB206D8E05C19F46C6228742AA7A9"
      , expected_r1 = parsePoint "023034FA5E2679F01EE66E12225882A7A48CC66719B1B9D3B6C4DBD743EFEDA2C5"
      , expected_r2 = parsePoint "03F3FD6F01EB3A8E9CB315D73F1F3D287CAFBB44AB321153C6287F407600205109"
      }
  , NonceGenTestVector
      { rand_ = decodeHex "0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F"
      , sk = Just 0x0202020202020202020202020202020202020202020202020202020202020202
      , pk = parsePoint "024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766"
      , aggpk = Just $ parsePoint "0707070707070707070707070707070707070707070707070707070707070707"
      , msg = Just $ decodeHex "2626262626262626262626262626262626262626262626262626262626262626262626262626"
      , extra_in = Just $ decodeHex "0808080808080808080808080808080808080808080808080808080808080808"
      , expected_k1 = parseScalar "3221975ACBDEA6820EABF02A02B7F27D3A8EF68EE42787B88CBEFD9AA06AF363"
      , expected_k2 = parseScalar "2EE85B1A61D8EF31126D4663A00DD96E9D1D4959E72D70FE5EBB6E7696EBA66F"
      , expected_r1 = parsePoint "02E5BBC21C69270F59BD634FCBFA281BE9D76601295345112C58954625BF23793A"
      , expected_r2 = parsePoint "021307511C79F95D38ACACFF1B4DA98228B77E65AA216AD075E9673286EFB4EAF3"
      }
  , NonceGenTestVector
      { rand_ = decodeHex "0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F"
      , sk = Nothing
      , pk = parsePoint "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9"
      , aggpk = Nothing
      , msg = Nothing
      , extra_in = Nothing
      , expected_k1 = parseScalar "89BDD787D0284E5E4D5FC572E49E316BAB7E21E3B1830DE37DFE80156FA41A6D"
      , expected_k2 = parseScalar "0B17AE8D024C53679699A6FD7944D9C4A366B514BAF43088E0708B1023DD2897"
      , expected_r1 = parsePoint "02C96E7CB1E8AA5DAC64D872947914198F607D90ECDE5200DE52978AD5DED63C00"
      , expected_r2 = parsePoint "0299EC5117C2D29EDEE8A2092587C3909BE694D5CFF0667D6C02EA4059F7CD9786"
      }
  ]

-- | Creates a test case from a test vector.
makeNonceGenTestCase :: Int -> NonceGenTestVector -> TestTree
makeNonceGenTestCase i NonceGenTestVector{..} =
  testCase ("BIP-0327 NonceGen Vector " ++ show (i + 1)) $ do
    let params =
          SecNonceGenParams
            { _pk = pk
            , _sk = fmap SecKey sk
            , _aggpk = aggpk
            , _msg = msg
            , _extraIn = extra_in
            }
    let sec = unsafeRight $ secNonceGenWithRand rand_ params
    let pub = unsafeRight $ publicNonce sec
    let (k1, k2) = secNonceScalars sec
    assertEqual "k1 mismatch" expected_k1 k1
    assertEqual "k2 mismatch" expected_k2 k2
    assertEqual "r1 mismatch" expected_r1 pub.r1
    assertEqual "r2 mismatch" expected_r2 pub.r2

-- | Main test group for NonceGen.
testNonceGen :: TestTree
testNonceGen =
  testGroup "BIP-0327 NonceGen Vectors" $
    zipWith makeNonceGenTestCase [0 ..] testVectors