From 29ffdc88eab98dc29a290e862d759b18f4464428 Mon Sep 17 00:00:00 2001 From: KadenaFriend <241389759+kdafriend@users.noreply.github.com> Date: Sat, 3 Jan 2026 18:36:49 +0000 Subject: [PATCH 1/6] Switch to Pact post_quatum branch --- cabal.project | 3 +-- test/lib/Chainweb/Test/Pact5/CmdBuilder.hs | 4 ++++ test/unit/Chainweb/Test/Pact5/RemotePactTest.hs | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/cabal.project b/cabal.project index 9ea31d9dfa..dc73952dd4 100644 --- a/cabal.project +++ b/cabal.project @@ -101,8 +101,7 @@ source-repository-package source-repository-package type: git location: https://github.com/kda-community/pact-5.git - tag: bfc5310c462aaefabe7c512407ac6dab87fc8c42 - --sha256: 05xp1vwxkvjxrn8pij9z4g1hadbkb8hrgziwzs408yxxxmkcv6kq + tag: cbf0f14286f9ffa3d86c0bee08e121b4e679459e source-repository-package type: git diff --git a/test/lib/Chainweb/Test/Pact5/CmdBuilder.hs b/test/lib/Chainweb/Test/Pact5/CmdBuilder.hs index 879018055b..234420cdab 100644 --- a/test/lib/Chainweb/Test/Pact5/CmdBuilder.hs +++ b/test/lib/Chainweb/Test/Pact5/CmdBuilder.hs @@ -263,6 +263,10 @@ mkDynKeyPairs (CmdSigner Signer{..} privKey) = privWebAuthn <- either diePrivKey return (parseWebAuthnPrivateKey =<< parseB16TextOnly priv) return $ (DynWebAuthnKeyPair wasPrefixed pubWebAuthn privWebAuthn, _siCapList) + -- TODO Implement them + (SlhDsaSha128s, _, _) -> error "Unsupported" + (SlhDsaSha192s, _, _) -> error "Unsupported" + (SlhDsaSha256s, _, _) -> error "Unsupported" where diePubKey str = error $ "pubkey: " <> str diePrivKey str = error $ "privkey: " <> str diff --git a/test/unit/Chainweb/Test/Pact5/RemotePactTest.hs b/test/unit/Chainweb/Test/Pact5/RemotePactTest.hs index 2a85b549db..497faabae3 100644 --- a/test/unit/Chainweb/Test/Pact5/RemotePactTest.hs +++ b/test/unit/Chainweb/Test/Pact5/RemotePactTest.hs @@ -474,7 +474,7 @@ sendInvalidTxsTest rdb = withResourceT (mkFixture v rdb) $ \fx -> { -- This is an invalid ED25519 signature, -- but length signers == length signatures is checked first - _cmdSigs = [ED25519Sig "fakeSig"] + _cmdSigs = [PlainSig "fakeSig"] } send fx v cid [cmdSignersSigsLengthMismatch2] & P.throws ? P.match _FailureResponse ? P.fun responseBody ? textContains @@ -609,7 +609,7 @@ sendInvalidTxsTest rdb = withResourceT (mkFixture v rdb) $ \fx -> validationFailed i cmd msg = "Transaction " <> sshow (_cmdHash cmd) <> " at index " <> sshow @Int i <> " failed with: " <> msg - mkCmdInvalidUserSig = mkCmdGood <&> set cmdSigs [ED25519Sig "fakeSig"] + mkCmdInvalidUserSig = mkCmdGood <&> set cmdSigs [PlainSig "fakeSig"] mkCmdGood = buildTextCmd v $ set cbRPC (mkExec "(+ 1 2)" (mkKeySetData "sender00" [sender00])) @@ -1102,7 +1102,7 @@ localTests baseRdb = let goodCmdHash <- _cmdHash <$> buildTextCmd v buildSender00Cmd sender01KeyPair <- either error return $ importEd25519KeyPair Nothing (PrivBS $ either error id $ B16.decode $ T.encodeUtf8 $ snd sender01) - let sender01Sig = ED25519Sig $ T.decodeUtf8 $ B16.encode $ exportEd25519Signature $ + let sender01Sig = PlainSig $ T.decodeUtf8 $ B16.encode $ exportEd25519Signature $ signEd25519 (fst sender01KeyPair) (snd sender01KeyPair) goodCmdHash buildTextCmd v buildSender00Cmd From e501570147abb4adeb3e867e6e1cb93b0dd7b456 Mon Sep 17 00:00:00 2001 From: KadenaFriend <241389759+kdafriend@users.noreply.github.com> Date: Mon, 5 Jan 2026 10:45:11 +0000 Subject: [PATCH 2/6] Make sure validateCommand is executed in the context of Pact4 --- src/Chainweb/Pact/RestAPI/Server.hs | 8 +++++++- src/Chainweb/Version/Guards.hs | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Chainweb/Pact/RestAPI/Server.hs b/src/Chainweb/Pact/RestAPI/Server.hs index 80f7ea94ea..94dd4e5004 100644 --- a/src/Chainweb/Pact/RestAPI/Server.hs +++ b/src/Chainweb/Pact/RestAPI/Server.hs @@ -106,6 +106,7 @@ import Chainweb.Pact.Types import Chainweb.Pact4.SPV qualified as Pact4 import Pact.Types.ChainMeta qualified as Pact4 import Chainweb.Payload +import Chainweb.Version.Guards (getForkHeight) import Chainweb.Payload.PayloadStore import Chainweb.RestAPI.Orphans () import Chainweb.RestAPI.Utils @@ -723,7 +724,12 @@ validateCommand v cid (fmap encodeUtf8 -> cmdBs) = case parsedCmd of Right () -> Right commandParsed Left e -> Left $ "Pact parsing error: " <> T.pack e where - bh = maxBound :: BlockHeight + -- It's supposed to be a Pact4 command, so take the height just before the Pact5 fork + bh = case getForkHeight Pact5Fork v cid of + ForkAtGenesis -> minBound :: BlockHeight + ForkNever -> maxBound :: BlockHeight + ForkAtBlockHeight bh' -> bh' -1 + decodeAndParse bs = traverse (Pact4.parsePact) =<< Aeson.eitherDecodeStrict' bs parsedCmd = Pact4.mkPayloadWithText <$> diff --git a/src/Chainweb/Version/Guards.hs b/src/Chainweb/Version/Guards.hs index 90cbd94321..f8c7d8453d 100644 --- a/src/Chainweb/Version/Guards.hs +++ b/src/Chainweb/Version/Guards.hs @@ -50,6 +50,7 @@ module Chainweb.Version.Guards , chainweb31 , migratePlatformShare , pact5 + , getForkHeight , pact44NewTrans , pact4ParserVersion , maxBlockGasLimit From 373ca26fd436caea9bce5bd1dbdeabb3e224773e Mon Sep 17 00:00:00 2001 From: KadenaFriend <241389759+kdafriend@users.noreply.github.com> Date: Mon, 5 Jan 2026 12:36:47 +0000 Subject: [PATCH 3/6] Implement the mixed Pact/4/Pact5 validPPKSchemes --- src/Chainweb/Pact4/Validations.hs | 8 ++++---- src/Chainweb/Version/Guards.hs | 22 ++++++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/Chainweb/Pact4/Validations.hs b/src/Chainweb/Pact4/Validations.hs index d279ec439e..6797750a10 100644 --- a/src/Chainweb/Pact4/Validations.hs +++ b/src/Chainweb/Pact4/Validations.hs @@ -63,7 +63,7 @@ import Chainweb.Pact.Utils (fromPactChainId) import Chainweb.Time (Seconds(..), Time(..), secondsToTimeSpan, scaleTimeSpan, second, add) import Chainweb.Pact4.Transaction import Chainweb.Version -import Chainweb.Version.Guards (isWebAuthnPrefixLegal, validPPKSchemes) +import Chainweb.Version.Guards (PactPPKScheme(..), isWebAuthnPrefixLegal, validPPKSchemes) import qualified Pact.Types.Gas as P import qualified Pact.Types.Hash as P @@ -174,7 +174,7 @@ assertTxSize initialGas gasLimit = initialGas < fromIntegral gasLimit -- transaction hash. -- assertValidateSigs :: () - => [P.PPKScheme] + => [PactPPKScheme] -> IsWebAuthnPrefixLegal -> P.PactHash -> [P.Signer] @@ -193,7 +193,7 @@ assertValidateSigs validSchemes webAuthnPrefixLegal hsh signers sigs = do iforM_ (zip sigs signers) $ \pos (sig, signer) -> do ebool_ (InvalidSignerScheme pos) - (fromMaybe P.ED25519 (P._siScheme signer) `elem` validSchemes) + ((SchemeV4 $ fromMaybe P.ED25519 $ P._siScheme signer) `elem` validSchemes) ebool_ (InvalidSignerWebAuthnPrefix pos) (webAuthnPrefixLegal == WebAuthnPrefixLegal || not (P.webAuthnPrefix `Text.isPrefixOf` P._siPubKey signer)) @@ -239,7 +239,7 @@ assertTxNotInFuture (ParentCreationTime (BlockCreationTime txValidationTime)) tx -- | Assert that the command hash matches its payload and -- its signatures are valid, without parsing the payload. -assertCommand :: P.Command (PayloadWithText m c) -> [P.PPKScheme] -> IsWebAuthnPrefixLegal -> Either AssertCommandError () +assertCommand :: P.Command (PayloadWithText m c) -> [PactPPKScheme] -> IsWebAuthnPrefixLegal -> Either AssertCommandError () assertCommand (P.Command pwt sigs hsh) ppkSchemePassList webAuthnPrefixLegal = do if isRight assertHash then first AssertValidateSigsError $ assertValidateSigs ppkSchemePassList webAuthnPrefixLegal hsh signers sigs diff --git a/src/Chainweb/Version/Guards.hs b/src/Chainweb/Version/Guards.hs index f8c7d8453d..510cd146f0 100644 --- a/src/Chainweb/Version/Guards.hs +++ b/src/Chainweb/Version/Guards.hs @@ -55,6 +55,7 @@ module Chainweb.Version.Guards , pact4ParserVersion , maxBlockGasLimit , minimumBlockHeaderHistory + , PactPPKScheme(..) , validPPKSchemes , isWebAuthnPrefixLegal , validKeyFormats @@ -79,7 +80,8 @@ import Pact.Core.Builtin qualified as Pact5 import Pact.Core.Info qualified as Pact5 import Pact.Core.Serialise qualified as Pact5 import Pact.Types.KeySet (PublicKeyText, ed25519HexFormat, webAuthnFormat) -import Pact.Types.Scheme (PPKScheme(ED25519, WebAuthn)) +import Pact.Types.Scheme qualified as Pact4 (PPKScheme(..)) +import Pact.Core.Scheme qualified as Pact5 (PPKScheme(..)) -- Gets the height which the fork is associated with. -- This may not be the first height at which the associated guard is `True` @@ -301,6 +303,10 @@ chainweb225Pact = checkFork atOrAfter Chainweb225Pact pact5 :: ChainwebVersion -> ChainId -> BlockHeight -> Bool pact5 = checkFork atOrAfter Pact5Fork +-- TODO Guard properly => For now, use the pact 5 fork +pactPostQuantum :: ChainwebVersion -> ChainId -> BlockHeight -> Bool +pactPostQuantum = pact5 + -- | Pact 5.1, including a new more succinct serializer for modules chainweb228Pact :: ChainwebVersion -> ChainId -> BlockHeight -> Bool chainweb228Pact = checkFork atOrAfter Chainweb228Pact @@ -341,11 +347,15 @@ minimumBlockHeaderHistory v bh = snd $ ruleZipperHere $ snd -- | Different versions of Chainweb allow different PPKSchemes. -- -validPPKSchemes :: ChainwebVersion -> ChainId -> BlockHeight -> [PPKScheme] -validPPKSchemes v cid bh = - if chainweb221Pact v cid bh - then [ED25519, WebAuthn] - else [ED25519] +data PactPPKScheme = SchemeV4 Pact4.PPKScheme | SchemeV5 Pact5.PPKScheme + deriving(Eq) + +validPPKSchemes :: ChainwebVersion -> ChainId -> BlockHeight -> [PactPPKScheme] +validPPKSchemes v cid bh + | pactPostQuantum v cid bh = map SchemeV5 [Pact5.ED25519, Pact5.WebAuthn, Pact5.SlhDsaSha128s, Pact5.SlhDsaSha192s, Pact5.SlhDsaSha256s] + | pact5 v cid bh = map SchemeV5 [Pact5.ED25519, Pact5.WebAuthn] + | chainweb221Pact v cid bh = map SchemeV4 [Pact4.ED25519, Pact4.WebAuthn] + | otherwise = [SchemeV4 Pact4.ED25519] isWebAuthnPrefixLegal :: ChainwebVersion -> ChainId -> BlockHeight -> Pact4.IsWebAuthnPrefixLegal isWebAuthnPrefixLegal v cid bh = From b9d632a110b288bec170515285262fbcad39949c Mon Sep 17 00:00:00 2001 From: KadenaFriend <241389759+kdafriend@users.noreply.github.com> Date: Mon, 5 Jan 2026 12:38:01 +0000 Subject: [PATCH 4/6] Guard the validSchemes for Pact5 --- src/Chainweb/Pact/PactService.hs | 10 +++++---- .../Pact/PactService/Pact5/ExecBlock.hs | 2 +- src/Chainweb/Pact/RestAPI/Server.hs | 9 +++++--- src/Chainweb/Pact5/Validations.hs | 22 ++++++++++++------- test/lib/Chainweb/Test/Pact5/CmdBuilder.hs | 10 +++++---- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/Chainweb/Pact/PactService.hs b/src/Chainweb/Pact/PactService.hs index 0852ac0c3f..30a9455a1f 100644 --- a/src/Chainweb/Pact/PactService.hs +++ b/src/Chainweb/Pact/PactService.hs @@ -860,7 +860,11 @@ execLocal cwtx preflight sigVerify rdepth = pactLabel "execLocal" $ do let localPact5 = do ph <- view psParentHeader - let pact5RequestKey = Pact5.RequestKey (Pact5.Hash $ Pact4.unHash $ Pact4.toUntypedHash $ Pact4._cmdHash cwtx) + let txCtx = Pact5.TxContext ph noMiner + bh = Pact5.ctxCurrentBlockHeight txCtx + pact5RequestKey = Pact5.RequestKey (Pact5.Hash $ Pact4.unHash $ Pact4.toUntypedHash $ Pact4._cmdHash cwtx) + spvSupport = Pact5.pactSPV bhdb (_parentHeader ph) + evalContT $ withEarlyReturn $ \earlyReturn -> do pact5Cmd <- case Pact5.parsePact4Command cwtx of Left (Left errText) -> do @@ -903,14 +907,12 @@ execLocal cwtx preflight sigVerify rdepth = pactLabel "execLocal" $ do review _MetadataValidationFailure $ NonEmpty.singleton $ Text.pack err Right _ -> return () _ -> do - let validated = Pact5.assertCommand pact5Cmd + let validated = Pact5.assertCommand pact5Cmd (validPPKSchemes v cid bh) case validated of Left err -> earlyReturn $ review _MetadataValidationFailure (pure $ displayAssertCommandError err) Right () -> return () - let txCtx = Pact5.TxContext ph noMiner - let spvSupport = Pact5.pactSPV bhdb (_parentHeader ph) case preflight of Just PreflightSimulation -> do -- preflight needs to do additional checks on the metadata diff --git a/src/Chainweb/Pact/PactService/Pact5/ExecBlock.hs b/src/Chainweb/Pact/PactService/Pact5/ExecBlock.hs index 557ff53ac2..2920c6d1e3 100644 --- a/src/Chainweb/Pact/PactService/Pact5/ExecBlock.hs +++ b/src/Chainweb/Pact/PactService/Pact5/ExecBlock.hs @@ -531,7 +531,7 @@ validateParsedChainwebTx _logger v cid db _blockHandle txValidationTime bh isGen checkTxSigs :: Pact5.Transaction -> ExceptT InsertError IO () checkTxSigs t = do - case Pact5.assertValidateSigs hsh signers sigs of + case Pact5.assertValidateSigs (validPPKSchemes v cid bh) hsh signers sigs of Right _ -> do pure () Left err -> do diff --git a/src/Chainweb/Pact/RestAPI/Server.hs b/src/Chainweb/Pact/RestAPI/Server.hs index 94dd4e5004..21c8c652c7 100644 --- a/src/Chainweb/Pact/RestAPI/Server.hs +++ b/src/Chainweb/Pact/RestAPI/Server.hs @@ -737,15 +737,18 @@ validateCommand v cid (fmap encodeUtf8 -> cmdBs) = case parsedCmd of -- TODO: all of the functions in this module can instead grab the current block height from consensus -- and pass it here to get a better estimate of what behavior is correct. -validatePact5Command :: ChainwebVersion -> Pact5.Command Text -> Either String Pact5.Transaction -validatePact5Command _v cmdText = case parsedCmd of +validatePact5Command :: ChainwebVersion -> ChainId -> Pact5.Command Text -> Either String Pact5.Transaction +validatePact5Command _v cid cmdText = case parsedCmd of Right (commandParsed :: Pact5.Transaction) -> - if isRight (Pact5.assertCommand commandParsed) + if isRight $ Pact5.assertCommand commandParsed $ validPPKSchemes _v cid bh then Right commandParsed else Left "Command failed validation" Left e -> Left $ "Pact parsing error: " ++ Pact5.renderCompactString e where parsedCmd = Pact5.parseCommand cmdText + -- For Pact5, we take the highest possible BlockHeight + bh = maxBound :: BlockHeight + -- | Validate the length of the request key's underlying hash. -- diff --git a/src/Chainweb/Pact5/Validations.hs b/src/Chainweb/Pact5/Validations.hs index bdafd74796..26f648b6ff 100644 --- a/src/Chainweb/Pact5/Validations.hs +++ b/src/Chainweb/Pact5/Validations.hs @@ -58,6 +58,7 @@ import qualified Pact.Core.Gas.Types as P import qualified Pact.Core.Hash as P import qualified Chainweb.Pact5.Transaction as P import qualified Pact.Types.Gas as Pact4 +import Chainweb.Version.Guards (PactPPKScheme(..), validPPKSchemes) import qualified Pact.Parse as Pact4 import Chainweb.Pact5.Types import qualified Chainweb.Pact5.Transaction as Pact5 @@ -79,6 +80,7 @@ assertPreflightMetadata cmd@(P.Command pay sigs hsh) txCtx sigVerify = do let P.PublicMeta pcid _ gl gp _ _ = P._pMeta pay nid = P._pNetworkId pay signers = P._pSigners pay + validSchemes = validPPKSchemes v cid $ ctxCurrentBlockHeight txCtx let errs = catMaybes [ eUnless "Chain id mismatch" $ assertChainId cid pcid @@ -88,7 +90,7 @@ assertPreflightMetadata cmd@(P.Command pay sigs hsh) txCtx sigVerify = do , eUnless "Gas price decimal precision too high" $ assertGasPrice gp , eUnless "Network id mismatch" $ assertNetworkId v nid , eUnless "Signature list size too big" $ assertSigSize sigs - , eUnless "Invalid transaction signatures" $ sigValidate signers + , eUnless "Invalid transaction signatures" $ sigValidate validSchemes signers , eUnless "Tx time outside of valid range" $ assertTxTimeRelativeToParent pct cmd ] @@ -96,9 +98,9 @@ assertPreflightMetadata cmd@(P.Command pay sigs hsh) txCtx sigVerify = do Nothing -> Right () Just vs -> Left vs where - sigValidate signers + sigValidate validSchemes signers | Just NoVerify <- sigVerify = True - | otherwise = isRight $ assertValidateSigs hsh signers sigs + | otherwise = isRight $ assertValidateSigs validSchemes hsh signers sigs pct = ParentCreationTime . view blockCreationTime @@ -153,11 +155,12 @@ assertTxSize initialGas gasLimit = P.GasLimit initialGas < gasLimit -- transaction hash. -- assertValidateSigs :: () - => P.Hash + => [PactPPKScheme] + -> P.Hash -> [P.Signer] -> [P.UserSig] -> Either AssertValidateSigsError () -assertValidateSigs hsh signers sigs = do +assertValidateSigs validSchemes hsh signers sigs = do let signersLength = length signers let sigsLength = length sigs ebool_ @@ -168,6 +171,9 @@ assertValidateSigs hsh signers sigs = do (signersLength == sigsLength) iforM_ (zip sigs signers) $ \pos (sig, signer) -> do + ebool_ (InvalidSignerScheme pos) + ((SchemeV5 $ fromMaybe P.ED25519 $ P._siScheme signer) `elem` validSchemes) + case P.verifyUserSig hsh sig signer of Left errMsg -> Left (InvalidUserSig pos (Text.pack errMsg)) Right () -> Right () @@ -209,10 +215,10 @@ assertTxNotInFuture (ParentCreationTime (BlockCreationTime txValidationTime)) tx -- | Assert that the command hash matches its payload and -- its signatures are valid, without parsing the payload. -assertCommand :: Pact5.Transaction -> Either AssertCommandError () -assertCommand cmd = do +assertCommand :: Pact5.Transaction -> [PactPPKScheme] -> Either AssertCommandError () +assertCommand cmd ppkSchemePassList = do _ <- assertHash & _Left .~ InvalidPayloadHash - assertValidateSigs hsh signers (P._cmdSigs cmd) & _Left %~ AssertValidateSigsError + assertValidateSigs ppkSchemePassList hsh signers (P._cmdSigs cmd) & _Left %~ AssertValidateSigsError where hsh = P._cmdHash cmd pwt = P._cmdPayload cmd diff --git a/test/lib/Chainweb/Test/Pact5/CmdBuilder.hs b/test/lib/Chainweb/Test/Pact5/CmdBuilder.hs index 234420cdab..efae41b929 100644 --- a/test/lib/Chainweb/Test/Pact5/CmdBuilder.hs +++ b/test/lib/Chainweb/Test/Pact5/CmdBuilder.hs @@ -189,10 +189,12 @@ defaultCmd cid = CmdBuilder -- | Build parsed + verified Pact command -- TODO: Use the new `assertPact4Command` function. buildCwCmd :: (MonadThrow m, MonadIO m) => ChainwebVersion -> CmdBuilder -> m Pact5.Transaction -buildCwCmd v cmd = buildTextCmd v cmd >>= \(c :: Command Text) -> - case validatePact5Command v c of - Left err -> throwM $ userError $ "buildCwCmd failed: " ++ err - Right cmd' -> return cmd' +buildCwCmd v cmd = do + cid <- Chainweb.chainIdFromText $ _cbChainId cmd + cmd' <- buildTextCmd v cmd + case validatePact5Command v cid cmd' of + Left err -> throwM $ userError $ "buildCwCmd failed: " ++ err + Right validatedCmd -> return validatedCmd -- | Build a Pact4 command without parsing it. This can be useful for inserting txs directly into the mempool for testing. buildCwCmdNoParse :: forall m. (MonadThrow m, MonadIO m) => ChainwebVersion -> CmdBuilder -> m Pact4.UnparsedTransaction From f04c866698b2b351a9bb8e8afe359d120d4948a2 Mon Sep 17 00:00:00 2001 From: KadenaFriend <241389759+kdafriend@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:51:20 +0000 Subject: [PATCH 5/6] Fix benchmarks -> Pact5 functions were used for Pact4 transactions --- bench/Chainweb/Pact/Backend/PactService.hs | 52 +++++++++++++++++----- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/bench/Chainweb/Pact/Backend/PactService.hs b/bench/Chainweb/Pact/Backend/PactService.hs index 6818e5d1bc..9bf9c832d0 100644 --- a/bench/Chainweb/Pact/Backend/PactService.hs +++ b/bench/Chainweb/Pact/Backend/PactService.hs @@ -82,17 +82,17 @@ bench :: RocksDb -> C.Benchmark bench rdb = do C.bgroup "PactService" [ C.bgroup "Pact4" - [ C.bench "1 tx" $ oneBlock pact4Version rdb 1 - , C.bench "10 txs" $ oneBlock pact4Version rdb 10 - , C.bench "20 txs" $ oneBlock pact4Version rdb 20 - , C.bench "30 txs" $ oneBlock pact4Version rdb 30 - , C.bench "40 txs" $ oneBlock pact4Version rdb 40 - , C.bench "50 txs" $ oneBlock pact4Version rdb 50 - , C.bench "60 txs" $ oneBlock pact4Version rdb 60 - , C.bench "70 txs" $ oneBlock pact4Version rdb 70 - , C.bench "80 txs" $ oneBlock pact4Version rdb 80 - , C.bench "90 txs" $ oneBlock pact4Version rdb 90 - , C.bench "100 txs" $ oneBlock pact4Version rdb 100 + [ C.bench "1 tx" $ oneBlockV4 pact4Version rdb 1 + , C.bench "10 txs" $ oneBlockV4 pact4Version rdb 10 + , C.bench "20 txs" $ oneBlockV4 pact4Version rdb 20 + , C.bench "30 txs" $ oneBlockV4 pact4Version rdb 30 + , C.bench "40 txs" $ oneBlockV4 pact4Version rdb 40 + , C.bench "50 txs" $ oneBlockV4 pact4Version rdb 50 + , C.bench "60 txs" $ oneBlockV4 pact4Version rdb 60 + , C.bench "70 txs" $ oneBlockV4 pact4Version rdb 70 + , C.bench "80 txs" $ oneBlockV4 pact4Version rdb 80 + , C.bench "90 txs" $ oneBlockV4 pact4Version rdb 90 + , C.bench "100 txs" $ oneBlockV4 pact4Version rdb 100 ] , C.bgroup "Pact5" [ C.bench "1 tx" $ oneBlock pact5Version rdb 1 @@ -163,6 +163,36 @@ destroyFixture fx = do closeSQLiteConnection sql deleteNamespaceRocksDb fx._fixtureBlockDbRocksDb + +oneBlockV4 :: ChainwebVersion -> RocksDb -> Word -> C.Benchmarkable +oneBlockV4 v rdb numTxs = + let cid = unsafeChainId 0 + cfg = testPactServiceConfig + + setupEnv _ = do + fx <- createFixture v rdb cfg + txs <- forM [1..numTxs] $ \_ -> do + buildCwCmdNoParse v (transferCmd cid 1.0) + return (fx, txs) + + cleanupEnv _ (fx, _) = do + destroyFixture fx + in + C.perBatchEnvWithCleanup setupEnv cleanupEnv $ \ ~(fx, txs) -> do + prevCut <- getCut fx + result <- advanceAllChains fx $ onChain cid $ \ph pactQueue mempool -> do + mempoolClear mempool + mempoolInsert (fx._fixtureMempools ^?! atChain cid) UncheckedInsert $ Vector.fromList txs + + bip <- throwIfNoHistory =<< + newBlock noMiner NewBlockFill (ParentHeader ph) pactQueue + let block = forAnyPactVersion finalizeBlock bip + fromIntegral @_ @Word (Vector.length (_payloadWithOutputsTransactions block)) + & P.equals numTxs + return block + revert fx prevCut + return result + oneBlock :: ChainwebVersion -> RocksDb -> Word -> C.Benchmarkable oneBlock v rdb numTxs = let cid = unsafeChainId 0 From be1817ea6bcbe17b765eeaa8550aa466a0b6f416 Mon Sep 17 00:00:00 2001 From: KadenaFriend <241389759+kdafriend@users.noreply.github.com> Date: Tue, 6 Jan 2026 10:34:36 +0000 Subject: [PATCH 6/6] Guard schemes by fork number --- src/Chainweb/ForkState.hs | 5 +++++ src/Chainweb/Miner/Coordinator.hs | 2 +- src/Chainweb/Pact/PactService.hs | 9 ++++++--- .../Pact/PactService/Pact4/ExecBlock.hs | 3 ++- .../Pact/PactService/Pact5/ExecBlock.hs | 19 +++++++++++++------ src/Chainweb/Pact/RestAPI/Server.hs | 8 +++++--- src/Chainweb/Pact/Types.hs | 7 ++++--- src/Chainweb/Pact4/Validations.hs | 3 ++- src/Chainweb/Pact5/Types.hs | 5 +++++ src/Chainweb/Pact5/Validations.hs | 2 +- src/Chainweb/Version/Guards.hs | 11 ++++++----- src/Chainweb/WebPactExecutionService.hs | 5 +++-- 12 files changed, 53 insertions(+), 26 deletions(-) diff --git a/src/Chainweb/ForkState.hs b/src/Chainweb/ForkState.hs index dc793d341a..e7da0f17db 100644 --- a/src/Chainweb/ForkState.hs +++ b/src/Chainweb/ForkState.hs @@ -25,6 +25,7 @@ module Chainweb.ForkState -- * Fork Number , ForkNumber(..) , forkNumber +, pact4ForkNumber -- * Fork Votes , ForkVotes(..) @@ -132,6 +133,10 @@ forkNumber = lens _forkNumber $ \(ForkState w) v -> ForkState $ (w .&. 0xFFFFFFFF00000000) .|. (fromIntegral v .&. 0xFFFFFFFF) +-- Pact4 -> Pact5 trnasition happened during ForkNumber=0 era. +pact4ForkNumber:: ForkNumber +pact4ForkNumber = 0 + -- --------------------------------------------------------------------------- -- Fork Votes diff --git a/src/Chainweb/Miner/Coordinator.hs b/src/Chainweb/Miner/Coordinator.hs index a5a2fc210d..e4bc18affc 100644 --- a/src/Chainweb/Miner/Coordinator.hs +++ b/src/Chainweb/Miner/Coordinator.hs @@ -238,7 +238,7 @@ newWork logFun choice targetFork eminer@(Miner mid _) hdb pact tpw c = do logFun @T.Text Debug $ "newWork: chain " <> toText cid <> " not mineable" newWork logFun Anything targetFork eminer hdb pact tpw c Just (T2 (WorkReady newBlock) extension) -> do - let (primedParentHash, primedParentHeight, _) = newBlockParent newBlock + let (primedParentHash, _, primedParentHeight, _) = newBlockParent newBlock if primedParentHash == view blockHash (_parentHeader (_cutExtensionParent extension)) then do let payload = newBlockToPayloadWithOutputs newBlock diff --git a/src/Chainweb/Pact/PactService.hs b/src/Chainweb/Pact/PactService.hs index 30a9455a1f..d3571bfa14 100644 --- a/src/Chainweb/Pact/PactService.hs +++ b/src/Chainweb/Pact/PactService.hs @@ -115,6 +115,7 @@ import qualified Chainweb.Pact4.Transaction as Pact4 import Chainweb.TreeDB import Chainweb.Utils hiding (check) import Chainweb.Version +import Chainweb.ForkState (pact4ForkNumber) import Chainweb.Version.Guards import Utils.Logging.Trace import Chainweb.Counter @@ -818,7 +819,7 @@ execLocal cwtx preflight sigVerify rdepth = pactLabel "execLocal" $ do Left err -> earlyReturn $ review _MetadataValidationFailure $ NonEmpty.singleton $ Text.pack err Right _ -> return () _ -> do - let validated = Pact4.assertCommand pact4Cwtx (validPPKSchemes v cid bh) (isWebAuthnPrefixLegal v cid bh) + let validated = Pact4.assertCommand pact4Cwtx (validPPKSchemes v cid pact4ForkNumber bh) (isWebAuthnPrefixLegal v cid bh) case validated of Left err -> earlyReturn $ review _MetadataValidationFailure (pure $ displayAssertCommandError err) Right () -> return () @@ -862,6 +863,7 @@ execLocal cwtx preflight sigVerify rdepth = pactLabel "execLocal" $ do ph <- view psParentHeader let txCtx = Pact5.TxContext ph noMiner bh = Pact5.ctxCurrentBlockHeight txCtx + fn = Pact5.ctxCurrentForkNumber txCtx pact5RequestKey = Pact5.RequestKey (Pact5.Hash $ Pact4.unHash $ Pact4.toUntypedHash $ Pact4._cmdHash cwtx) spvSupport = Pact5.pactSPV bhdb (_parentHeader ph) @@ -907,7 +909,7 @@ execLocal cwtx preflight sigVerify rdepth = pactLabel "execLocal" $ do review _MetadataValidationFailure $ NonEmpty.singleton $ Text.pack err Right _ -> return () _ -> do - let validated = Pact5.assertCommand pact5Cmd (validPPKSchemes v cid bh) + let validated = Pact5.assertCommand pact5Cmd (validPPKSchemes v cid fn bh) case validated of Left err -> earlyReturn $ review _MetadataValidationFailure (pure $ displayAssertCommandError err) @@ -1183,13 +1185,14 @@ execPreInsertCheckReq txs = pactLabel "execPreInsertCheckReq" $ do let parentTime = ParentCreationTime (view blockCreationTime $ _parentHeader ph) currHeight = succ $ view blockHeight $ _parentHeader ph + parentForkNumber = view blockForkNumber $ _parentHeader ph isGenesis = False forM txs $ \tx -> fmap (either Just (\_ -> Nothing)) $ runExceptT $ do -- it's safe to use initialBlockHandle here because it's -- only used to check for duplicate pending txs in a block pact5Tx <- mapExceptT liftIO $ Pact5.validateRawChainwebTx - logger v cid db initialBlockHandle parentTime currHeight isGenesis tx + logger v cid db initialBlockHandle parentTime parentForkNumber currHeight isGenesis tx let logger' = addLabel ("transaction", "attemptBuyGas") logger ExceptT $ Pact5.pactTransaction Nothing $ \pactDb -> runExceptT $ do let txCtx = Pact5.TxContext ph noMiner diff --git a/src/Chainweb/Pact/PactService/Pact4/ExecBlock.hs b/src/Chainweb/Pact/PactService/Pact4/ExecBlock.hs index b7e92d4487..ec398ab210 100644 --- a/src/Chainweb/Pact/PactService/Pact4/ExecBlock.hs +++ b/src/Chainweb/Pact/PactService/Pact4/ExecBlock.hs @@ -95,6 +95,7 @@ import Chainweb.Payload.PayloadStore import Chainweb.Time import Chainweb.Utils hiding (check) import Chainweb.Version +import Chainweb.ForkState (pact4ForkNumber) import Chainweb.Version.Guards import Chainweb.Pact4.Backend.ChainwebPactDb import Data.Coerce @@ -336,7 +337,7 @@ checkTxSigs logger v cid bh t = do hsh = Pact4._cmdHash t sigs = Pact4._cmdSigs t signers = Pact4._pSigners $ Pact4.payloadObj $ Pact4._cmdPayload t - validSchemes = validPPKSchemes v cid bh + validSchemes = validPPKSchemes v cid pact4ForkNumber bh webAuthnPrefixLegal = isWebAuthnPrefixLegal v cid bh checkCompile diff --git a/src/Chainweb/Pact/PactService/Pact5/ExecBlock.hs b/src/Chainweb/Pact/PactService/Pact5/ExecBlock.hs index 2920c6d1e3..6e23251022 100644 --- a/src/Chainweb/Pact/PactService/Pact5/ExecBlock.hs +++ b/src/Chainweb/Pact/PactService/Pact5/ExecBlock.hs @@ -36,6 +36,7 @@ import Chainweb.Pact5.Transaction import Chainweb.Pact5.TransactionExec import Chainweb.Pact5.Types import Chainweb.Payload +import Chainweb.ForkState import Chainweb.Payload.PayloadStore import Chainweb.Time import Chainweb.Utils @@ -328,11 +329,11 @@ continueBlock mpAccess blockInProgress = do cid <- view chainId logger <- view (psServiceEnv . psLogger) dbEnv <- view psBlockDbEnv - let (pHash, pHeight, parentTime) = blockInProgressParent blockInProgress + let (pHash, pForkNumber, pHeight, parentTime) = blockInProgressParent blockInProgress isGenesis <- view psIsGenesis let validate bhi _bha txs = do forM txs $ - runExceptT . validateRawChainwebTx logger v cid dbEnv (_blockInProgressHandle blockInProgress) (ParentCreationTime parentTime) bhi isGenesis + runExceptT . validateRawChainwebTx logger v cid dbEnv (_blockInProgressHandle blockInProgress) (ParentCreationTime parentTime) pForkNumber bhi isGenesis liftIO $ mpaGetBlock mpAccess blockFillState validate (succ pHeight) pHash @@ -477,13 +478,15 @@ validateParsedChainwebTx -> BlockHandle Pact5 -> ParentCreationTime -- ^ reference time for tx validation. + -> ForkNumber + -- ^ Parent Fork number -> BlockHeight -- ^ Current block height -> Bool -- ^ Genesis? -> Pact5.Transaction -> ExceptT InsertError IO () -validateParsedChainwebTx _logger v cid db _blockHandle txValidationTime bh isGenesis tx +validateParsedChainwebTx _logger v cid db _blockHandle txValidationTime fn bh isGenesis tx | isGenesis = pure () | otherwise = do checkUnique tx @@ -531,7 +534,7 @@ validateParsedChainwebTx _logger v cid db _blockHandle txValidationTime bh isGen checkTxSigs :: Pact5.Transaction -> ExceptT InsertError IO () checkTxSigs t = do - case Pact5.assertValidateSigs (validPPKSchemes v cid bh) hsh signers sigs of + case Pact5.assertValidateSigs (validPPKSchemes v cid fn bh) hsh signers sigs of Right _ -> do pure () Left err -> do @@ -558,17 +561,19 @@ validateRawChainwebTx -> BlockHandle Pact5 -> ParentCreationTime -- ^ reference time for tx validation. + -> ForkNumber + -- ^ Parent Fork number -> BlockHeight -- ^ Current block height -> Bool -- ^ Genesis? -> Pact4.UnparsedTransaction -> ExceptT InsertError IO Pact5.Transaction -validateRawChainwebTx logger v cid db blockHandle parentTime bh isGenesis tx = do +validateRawChainwebTx logger v cid db blockHandle parentTime fn bh isGenesis tx = do tx' <- either (throwError . InsertErrorPactParseError . either id Pact5.renderText) return $ Pact5.parsePact4Command tx liftIO $ do logDebug_ logger $ "validateRawChainwebTx: parse succeeded" - validateParsedChainwebTx logger v cid db blockHandle parentTime bh isGenesis tx' + validateParsedChainwebTx logger v cid db blockHandle parentTime fn bh isGenesis tx' return $! tx' execExistingBlock @@ -591,9 +596,11 @@ execExistingBlock currHeader payload = do blockHandlePreCoinbase <- use pbBlockHandle let txValidationTime = ParentCreationTime (view blockCreationTime $ _parentHeader parentBlockHeader) + parentForkNumber = (view blockForkNumber $ _parentHeader parentBlockHeader) errors <- liftIO $ flip foldMap txs $ \tx -> do errorOrSuccess <- runExceptT $ validateParsedChainwebTx logger v cid db blockHandlePreCoinbase txValidationTime + parentForkNumber (view blockHeight currHeader) isGenesis tx diff --git a/src/Chainweb/Pact/RestAPI/Server.hs b/src/Chainweb/Pact/RestAPI/Server.hs index 21c8c652c7..9dfb80d425 100644 --- a/src/Chainweb/Pact/RestAPI/Server.hs +++ b/src/Chainweb/Pact/RestAPI/Server.hs @@ -91,6 +91,7 @@ import Chainweb.BlockHash import Chainweb.BlockHeader import Chainweb.BlockHeaderDB import Chainweb.BlockHeight +import Chainweb.ForkState import Chainweb.ChainId import Chainweb.Crypto.MerkleLog import Chainweb.Cut @@ -719,7 +720,7 @@ barf e = maybe (throwError e) return validateCommand :: ChainwebVersion -> ChainId -> Pact4.Command Text -> Either Text Pact4.Transaction validateCommand v cid (fmap encodeUtf8 -> cmdBs) = case parsedCmd of Right (commandParsed :: Pact4.Transaction) -> - case Pact4.assertCommand commandParsed (validPPKSchemes v cid bh) (isWebAuthnPrefixLegal v cid bh) of + case Pact4.assertCommand commandParsed (validPPKSchemes v cid pact4ForkNumber bh) (isWebAuthnPrefixLegal v cid bh) of Left err -> Left $ "Command failed validation: " <> Pact4.displayAssertCommandError err Right () -> Right commandParsed Left e -> Left $ "Pact parsing error: " <> T.pack e @@ -740,14 +741,15 @@ validateCommand v cid (fmap encodeUtf8 -> cmdBs) = case parsedCmd of validatePact5Command :: ChainwebVersion -> ChainId -> Pact5.Command Text -> Either String Pact5.Transaction validatePact5Command _v cid cmdText = case parsedCmd of Right (commandParsed :: Pact5.Transaction) -> - if isRight $ Pact5.assertCommand commandParsed $ validPPKSchemes _v cid bh + if isRight $ Pact5.assertCommand commandParsed $ validPPKSchemes _v cid fn bh then Right commandParsed else Left "Command failed validation" Left e -> Left $ "Pact parsing error: " ++ Pact5.renderCompactString e where parsedCmd = Pact5.parseCommand cmdText - -- For Pact5, we take the highest possible BlockHeight + -- For Pact5, we take the highest possible BlockHeight and ForkNumber bh = maxBound :: BlockHeight + fn = maxBound :: ForkNumber -- | Validate the length of the request key's underlying hash. diff --git a/src/Chainweb/Pact/Types.hs b/src/Chainweb/Pact/Types.hs index c7c4d4e589..f0489857fc 100644 --- a/src/Chainweb/Pact/Types.hs +++ b/src/Chainweb/Pact/Types.hs @@ -227,6 +227,7 @@ import Chainweb.BlockHeader import Chainweb.BlockHeight import Chainweb.BlockHeaderDB import Chainweb.ChainId +import Chainweb.ForkState import Chainweb.Counter import Chainweb.Mempool.Mempool (TransactionHash, BlockFill, MempoolPreBlockCheck, InsertError) import Chainweb.Miner.Pact @@ -1189,11 +1190,11 @@ instance HasChainId (BlockInProgress pv) where _chainId = _blockInProgressChainId {-# INLINE _chainId #-} -blockInProgressParent :: BlockInProgress pv -> (BlockHash, BlockHeight, BlockCreationTime) +blockInProgressParent :: BlockInProgress pv -> (BlockHash, ForkNumber, BlockHeight, BlockCreationTime) blockInProgressParent bip = maybe - (genesisParentBlockHash v cid, genesisHeight v cid, v ^?! versionGenesis . genesisTime . atChain cid) - (\bh -> (view blockHash bh, view blockHeight bh, view blockCreationTime bh)) + (genesisParentBlockHash v cid, genesisForkState ^. forkNumber, genesisHeight v cid, v ^?! versionGenesis . genesisTime . atChain cid) + (\bh -> (view blockHash bh, view blockForkNumber bh, view blockHeight bh, view blockCreationTime bh)) (_parentHeader <$> _blockInProgressParentHeader bip) where v = _blockInProgressChainwebVersion bip diff --git a/src/Chainweb/Pact4/Validations.hs b/src/Chainweb/Pact4/Validations.hs index 6797750a10..e3c61035d8 100644 --- a/src/Chainweb/Pact4/Validations.hs +++ b/src/Chainweb/Pact4/Validations.hs @@ -57,6 +57,7 @@ import Data.Word (Word8) -- internal modules import Chainweb.BlockHeader +import Chainweb.ForkState (pact4ForkNumber) import Chainweb.BlockCreationTime (BlockCreationTime(..)) import Chainweb.Pact.Types import Chainweb.Pact.Utils (fromPactChainId) @@ -89,7 +90,7 @@ assertPreflightMetadata cmd@(P.Command pay sigs hsh) txCtx sigVerify = do bgl <- view psBlockGasLimit let bh = ctxCurrentBlockHeight txCtx - let validSchemes = validPPKSchemes v cid bh + let validSchemes = validPPKSchemes v cid pact4ForkNumber bh let webAuthnPrefixLegal = isWebAuthnPrefixLegal v cid bh let P.PublicMeta pcid _ gl gp _ _ = P._pMeta pay diff --git a/src/Chainweb/Pact5/Types.hs b/src/Chainweb/Pact5/Types.hs index 785be552e8..2f72fbf282 100644 --- a/src/Chainweb/Pact5/Types.hs +++ b/src/Chainweb/Pact5/Types.hs @@ -11,6 +11,7 @@ module Chainweb.Pact5.Types ( TxContext(..) , guardCtx , ctxCurrentBlockHeight + , ctxCurrentForkNumber , GasSupply(..) , PactBlockM(..) , PactBlockState(..) @@ -34,6 +35,7 @@ import Chainweb.BlockHeader import Chainweb.Miner.Pact (Miner) import Chainweb.BlockHeight import Chainweb.Version +import Chainweb.ForkState import Chainweb.Pact.Types import qualified Chainweb.ChainId import Control.Lens @@ -84,6 +86,9 @@ ctxBlockHeader = _parentHeader . _tcParentHeader ctxCurrentBlockHeight :: TxContext -> BlockHeight ctxCurrentBlockHeight = succ . view blockHeight . ctxBlockHeader +ctxCurrentForkNumber :: TxContext -> ForkNumber +ctxCurrentForkNumber = view blockForkNumber . ctxBlockHeader + ctxChainId :: TxContext -> Chainweb.ChainId.ChainId ctxChainId = _chainId . ctxBlockHeader diff --git a/src/Chainweb/Pact5/Validations.hs b/src/Chainweb/Pact5/Validations.hs index 26f648b6ff..866f57a0cb 100644 --- a/src/Chainweb/Pact5/Validations.hs +++ b/src/Chainweb/Pact5/Validations.hs @@ -80,7 +80,7 @@ assertPreflightMetadata cmd@(P.Command pay sigs hsh) txCtx sigVerify = do let P.PublicMeta pcid _ gl gp _ _ = P._pMeta pay nid = P._pNetworkId pay signers = P._pSigners pay - validSchemes = validPPKSchemes v cid $ ctxCurrentBlockHeight txCtx + validSchemes = validPPKSchemes v cid (ctxCurrentForkNumber txCtx) (ctxCurrentBlockHeight txCtx) let errs = catMaybes [ eUnless "Chain id mismatch" $ assertChainId cid pcid diff --git a/src/Chainweb/Version/Guards.hs b/src/Chainweb/Version/Guards.hs index 510cd146f0..d7e3bf533f 100644 --- a/src/Chainweb/Version/Guards.hs +++ b/src/Chainweb/Version/Guards.hs @@ -73,6 +73,7 @@ import Chainweb.ChainId import Chainweb.Pact4.Transaction qualified as Pact4 import Chainweb.Utils.Rule import Chainweb.Version +import Chainweb.ForkState import Control.Lens import Data.Word (Word64) import Numeric.Natural @@ -304,8 +305,8 @@ pact5 :: ChainwebVersion -> ChainId -> BlockHeight -> Bool pact5 = checkFork atOrAfter Pact5Fork -- TODO Guard properly => For now, use the pact 5 fork -pactPostQuantum :: ChainwebVersion -> ChainId -> BlockHeight -> Bool -pactPostQuantum = pact5 +pactPostQuantum :: ChainwebVersion -> ChainId -> ForkNumber -> BlockHeight -> Bool +pactPostQuantum v cid _ bh = pact5 v cid bh -- | Pact 5.1, including a new more succinct serializer for modules chainweb228Pact :: ChainwebVersion -> ChainId -> BlockHeight -> Bool @@ -350,9 +351,9 @@ minimumBlockHeaderHistory v bh = snd $ ruleZipperHere $ snd data PactPPKScheme = SchemeV4 Pact4.PPKScheme | SchemeV5 Pact5.PPKScheme deriving(Eq) -validPPKSchemes :: ChainwebVersion -> ChainId -> BlockHeight -> [PactPPKScheme] -validPPKSchemes v cid bh - | pactPostQuantum v cid bh = map SchemeV5 [Pact5.ED25519, Pact5.WebAuthn, Pact5.SlhDsaSha128s, Pact5.SlhDsaSha192s, Pact5.SlhDsaSha256s] +validPPKSchemes :: ChainwebVersion -> ChainId -> ForkNumber -> BlockHeight -> [PactPPKScheme] +validPPKSchemes v cid fn bh + | pactPostQuantum v cid fn bh = map SchemeV5 [Pact5.ED25519, Pact5.WebAuthn, Pact5.SlhDsaSha128s, Pact5.SlhDsaSha192s, Pact5.SlhDsaSha256s] | pact5 v cid bh = map SchemeV5 [Pact5.ED25519, Pact5.WebAuthn] | chainweb221Pact v cid bh = map SchemeV4 [Pact4.ED25519, Pact4.WebAuthn] | otherwise = [SchemeV4 Pact4.ED25519] diff --git a/src/Chainweb/WebPactExecutionService.hs b/src/Chainweb/WebPactExecutionService.hs index 0e689c1775..1ee2956192 100644 --- a/src/Chainweb/WebPactExecutionService.hs +++ b/src/Chainweb/WebPactExecutionService.hs @@ -34,6 +34,7 @@ import Chainweb.BlockHeight import Chainweb.ChainId import Chainweb.Mempool.Mempool (InsertError) import Chainweb.Miner.Pact +import Chainweb.ForkState import Chainweb.Pact.Service.BlockValidation import Chainweb.Pact.Service.PactQueue import Chainweb.Pact.Types @@ -67,10 +68,10 @@ newBlockToPayloadWithOutputs (NewBlockInProgress bip) newBlockToPayloadWithOutputs (NewBlockPayload _ pwo) = pwo -newBlockParent :: NewBlock -> (BlockHash, BlockHeight, BlockCreationTime) +newBlockParent :: NewBlock -> (BlockHash, ForkNumber, BlockHeight, BlockCreationTime) newBlockParent (NewBlockInProgress (ForSomePactVersion _ bip)) = blockInProgressParent bip newBlockParent (NewBlockPayload (ParentHeader ph) _) = - (view blockHash ph, view blockHeight ph, view blockCreationTime ph) + (view blockHash ph, view blockForkNumber ph, view blockHeight ph, view blockCreationTime ph) instance HasChainwebVersion NewBlock where _chainwebVersion (NewBlockInProgress (ForSomePactVersion _ bip)) = _chainwebVersion bip