diff --git a/chainweb.cabal b/chainweb.cabal index 60540a963..ce8058a13 100644 --- a/chainweb.cabal +++ b/chainweb.cabal @@ -328,8 +328,10 @@ library , Chainweb.Pact.Service.PactInProcApi , Chainweb.Pact.Service.PactQueue , Chainweb.Pact.Service.Types - , Chainweb.Pact.Templates - , Chainweb.Pact.TransactionExec + , Chainweb.Pact.Templates.Pact4 + , Chainweb.Pact.Templates.Pact5 + , Chainweb.Pact.TransactionExec.Pact4 + , Chainweb.Pact.TransactionExec.Pact5 , Chainweb.Pact.Transactions.FungibleV2Transactions , Chainweb.Pact.Transactions.CoinV3Transactions , Chainweb.Pact.Transactions.CoinV4Transactions diff --git a/src/Chainweb/Pact/PactService/ExecBlock.hs b/src/Chainweb/Pact/PactService/ExecBlock.hs index f94d1a6b3..fcf2e0da5 100644 --- a/src/Chainweb/Pact/PactService/ExecBlock.hs +++ b/src/Chainweb/Pact/PactService/ExecBlock.hs @@ -89,7 +89,8 @@ import Chainweb.Pact.Backend.Types import Chainweb.Pact.NoCoinbase import Chainweb.Pact.Service.Types import Chainweb.Pact.SPV -import Chainweb.Pact.TransactionExec +import Chainweb.Pact.TransactionExec.Pact4 +import qualified Chainweb.Pact.TransactionExec.Pact5 as Pact5 import Chainweb.Pact.Types import Chainweb.Pact.Validations import Chainweb.Payload @@ -116,6 +117,9 @@ execBlock currHeader payload = do let plData = checkablePayloadToPayloadData payload dbEnv <- view psBlockDbEnv miner <- decodeStrictOrThrow' (_minerData $ _payloadDataMiner plData) + + -- if + trans <- liftIO $ pact4TransactionsFromPayload (pactParserVersion v (_blockChainId currHeader) (_blockHeight currHeader)) plData @@ -303,7 +307,7 @@ execTransactions -> CoinbaseUsePrecompiled -> Maybe P.Gas -> Maybe Micros - -> PactBlockM logger tbl (Transactions (Either CommandInvalidError (Either (P.CommandResult [P.TxLogJson]) PCore.CommandResult))) + -> PactBlockM logger tbl (Transactions (Either CommandInvalidError (P.CommandResult [P.TxLogJson]))) execTransactions isGenesis miner ctxs enfCBFail usePrecomp gasLimit timeLimit = do mc <- initModuleCacheForBlock isGenesis -- for legacy reasons (ask Emily) we don't use the module cache resulting diff --git a/src/Chainweb/Pact/Templates.hs b/src/Chainweb/Pact/Templates/Pact4.hs similarity index 66% rename from src/Chainweb/Pact/Templates.hs rename to src/Chainweb/Pact/Templates/Pact4.hs index 11003c602..f0dd577ef 100644 --- a/src/Chainweb/Pact/Templates.hs +++ b/src/Chainweb/Pact/Templates/Pact4.hs @@ -14,17 +14,12 @@ -- -- Prebuilt Term templates for automated operations (coinbase, gas buy) -- -module Chainweb.Pact.Templates +module Chainweb.Pact.Templates.Pact4 ( mkFundTxTerm , mkBuyGasTerm , mkRedeemGasTerm , mkCoinbaseTerm -, mkFundTxCoreTerm -, mkBuyGasCoreTerm -, mkRedeemGasCoreTerm -, mkCoinbaseCoreTerm - , mkCoinbaseCmd ) where @@ -48,12 +43,6 @@ import Chainweb.Miner.Pact import Chainweb.Pact.Types import Chainweb.Pact.Service.Types -import qualified Pact.Core.Literal as Core -import qualified Pact.Core.Names as Core -import qualified Pact.Core.Info as PCore -import qualified Pact.Core.Syntax.ParseTree as CoreLisp - - inf :: Info inf = Info $ Just (Code "",Parsed (Columns 0 0) 0) {-# NOINLINE inf #-} @@ -100,22 +89,6 @@ buyGasTemplate = , strArgSetter 0 ) -fundTxTemplateCore :: Text -> Text -> CoreLisp.Expr PCore.SpanInfo -fundTxTemplateCore sender mid = - let senderTerm = coreStrLit sender - midTerm = coreStrLit mid - varApp = coreQn "fund-tx" "coin" - rks = coreApp (coreBn "read-keyset") [coreStrLit "miner-keyset"] - rds = coreApp (coreBn "read-decimal") [coreStrLit "total"] - in coreApp varApp [senderTerm, midTerm, rks, rds] - -buyGasTemplateCore :: Text -> CoreLisp.Expr PCore.SpanInfo -buyGasTemplateCore sender = - let senderTerm = coreStrLit sender - varApp = coreQn "buy-gas" "coin" - rds = coreApp (coreBn "read-decimal") [coreStrLit "total"] - in coreApp varApp [senderTerm, rds] - redeemGasTemplate :: (Term Name, ASetter' (Term Name) Text, ASetter' (Term Name) Text) redeemGasTemplate = ( app (qn "coin" "redeem-gas") @@ -128,27 +101,6 @@ redeemGasTemplate = , strArgSetter 0 ) -redeemGasTemplateCore :: Text -> Text -> CoreLisp.Expr PCore.SpanInfo -redeemGasTemplateCore mid sender = - let midTerm = coreStrLit mid - senderTerm = coreStrLit sender - varApp = coreQn "redeem-gas" "coin" - rks = coreApp (coreBn "read-keyset") [coreStrLit "miner-keyset"] - rds = coreApp (coreBn "read-decimal") [coreStrLit "total"] - in coreApp varApp [midTerm, rks, senderTerm, rds] - -coreApp :: CoreLisp.Expr PCore.SpanInfo -> [CoreLisp.Expr PCore.SpanInfo] -> CoreLisp.Expr PCore.SpanInfo -coreApp arg args = CoreLisp.App arg args def - -coreStrLit :: Text -> CoreLisp.Expr PCore.SpanInfo -coreStrLit txt = CoreLisp.Constant (Core.LString txt) def - -coreQn :: Text -> Text -> CoreLisp.Expr PCore.SpanInfo -coreQn name modname = CoreLisp.Var (Core.QN (Core.QualifiedName name (Core.ModuleName modname Nothing))) def - -coreBn :: Text -> CoreLisp.Expr PCore.SpanInfo -coreBn name = CoreLisp.Var (Core.BN (Core.BareName name)) def - dummyParsedCode :: ParsedCode dummyParsedCode = ParsedCode "1" [ELiteral $ LiteralExp (LInteger 1) def] {-# NOINLINE dummyParsedCode #-} @@ -200,26 +152,6 @@ mkRedeemGasTerm (MinerId mid) (MinerKeys ks) sender total fee = (populatedTerm, ] {-# INLINABLE mkRedeemGasTerm #-} -mkFundTxCoreTerm - :: MinerId -- ^ Id of the miner to fund - -> Text -- ^ Address of the sender from the command - -> CoreLisp.Expr PCore.SpanInfo -mkFundTxCoreTerm (MinerId mid) sender = fundTxTemplateCore sender mid -{-# INLINABLE mkFundTxCoreTerm #-} - -mkBuyGasCoreTerm - :: Text -- ^ Address of the sender from the command - -> CoreLisp.Expr PCore.SpanInfo -mkBuyGasCoreTerm sender = buyGasTemplateCore sender -{-# INLINABLE mkBuyGasCoreTerm #-} - -mkRedeemGasCoreTerm - :: MinerId -- ^ Id of the miner to fund - -> Text -- ^ Address of the sender from the command - -> CoreLisp.Expr PCore.SpanInfo -mkRedeemGasCoreTerm (MinerId mid) sender = redeemGasTemplateCore mid sender -{-# INLINABLE mkRedeemGasCoreTerm #-} - coinbaseTemplate :: (Term Name,ASetter' (Term Name) Text) coinbaseTemplate = ( app (qn "coin" "coinbase") @@ -231,14 +163,6 @@ coinbaseTemplate = ) {-# NOINLINE coinbaseTemplate #-} -coinbaseTemplateCore :: Text -> CoreLisp.Expr PCore.SpanInfo -coinbaseTemplateCore mid = - let midTerm = coreStrLit mid - varApp = coreQn "coinbase" "coin" - rks = coreApp (coreBn "read-keyset") [coreStrLit "miner-keyset"] - rds = coreApp (coreBn "read-decimal") [coreStrLit "reward"] - in coreApp varApp [midTerm, rks, rds] - mkCoinbaseTerm :: MinerId -> MinerKeys -> ParsedDecimal -> (Term Name,ExecMsg ParsedCode) mkCoinbaseTerm (MinerId mid) (MinerKeys ks) reward = (populatedTerm, execMsg) where @@ -251,12 +175,6 @@ mkCoinbaseTerm (MinerId mid) (MinerKeys ks) reward = (populatedTerm, execMsg) ] {-# INLINABLE mkCoinbaseTerm #-} -mkCoinbaseCoreTerm - :: MinerId -- ^ Id of the miner to fund - -> CoreLisp.Expr PCore.SpanInfo -mkCoinbaseCoreTerm (MinerId mid) = coinbaseTemplateCore mid -{-# INLINABLE mkCoinbaseCoreTerm #-} - -- | "Old method" to build a coinbase 'ExecMsg' for back-compat. -- mkCoinbaseCmd :: MinerId -> MinerKeys -> ParsedDecimal -> IO (ExecMsg ParsedCode) diff --git a/src/Chainweb/Pact/Templates/Pact5.hs b/src/Chainweb/Pact/Templates/Pact5.hs new file mode 100644 index 000000000..70cbcd6cc --- /dev/null +++ b/src/Chainweb/Pact/Templates/Pact5.hs @@ -0,0 +1,146 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} + +-- | +-- Module : Chainweb.Pact.Templates +-- Copyright : Copyright © 2010 Kadena LLC. +-- License : (see the file LICENSE) +-- Maintainer : Stuart Popejoy +-- Stability : experimental +-- +-- Prebuilt Term templates for automated operations (coinbase, gas buy) +-- +module Chainweb.Pact.Templates.Pact5 +( mkFundTxTerm +, mkBuyGasTerm +, mkRedeemGasTerm +, mkCoinbaseTerm +) where + + +import Control.Lens +import Data.Default (def) +import Data.Decimal +import Data.Text (Text, pack) + +import Text.Trifecta.Delta (Delta(..)) + +-- internal modules + +import qualified Pact.Types.RPC as Pact4 +import qualified Pact.JSON.Encode as J +import qualified Pact.JSON.Legacy.Value as J + +import Chainweb.Miner.Pact +import Chainweb.Pact.Types +import Chainweb.Pact.Service.Types + +import Pact.Core.Evaluate +import Pact.Core.Literal +import Pact.Core.Names +import Pact.Core.Info +import Pact.Core.Syntax.ParseTree + +fundTxTemplate :: Text -> Text -> Expr SpanInfo +fundTxTemplate sender mid = + let senderTerm = strLit sender + midTerm = strLit mid + varApp = qn "fund-tx" "coin" + rks = app (bn "read-keyset") [strLit "miner-keyset"] + rds = app (bn "read-decimal") [strLit "total"] + in app varApp [senderTerm, midTerm, rks, rds] + +buyGasTemplate :: Text -> Expr SpanInfo +buyGasTemplate sender = + let senderTerm = strLit sender + varApp = qn "buy-gas" "coin" + rds = app (bn "read-decimal") [strLit "total"] + in app varApp [senderTerm, rds] + +redeemGasTemplate :: Text -> Text -> Expr SpanInfo +redeemGasTemplate mid sender = + let midTerm = strLit mid + senderTerm = strLit sender + varApp = qn "redeem-gas" "coin" + rks = app (bn "read-keyset") [strLit "miner-keyset"] + rds = app (bn "read-decimal") [strLit "total"] + in app varApp [midTerm, rks, senderTerm, rds] + +app :: Expr SpanInfo -> [Expr SpanInfo] -> Expr SpanInfo +app arg args = App arg args def + +strLit :: Text -> Expr SpanInfo +strLit txt = Constant (LString txt) def + +qn :: Text -> Text -> Expr SpanInfo +qn name modname = Var (QN (QualifiedName name (ModuleName modname Nothing))) def + +bn :: Text -> Expr SpanInfo +bn name = Var (BN (BareName name)) def + +mkFundTxTerm + :: MinerId -- ^ Id of the miner to fund + -> MinerKeys + -> Text -- ^ Address of the sender from the command + -> GasSupply + -> (Expr SpanInfo, Pact4.ExecMsg RawCode) +mkFundTxTerm (MinerId mid) (MinerKeys ks) sender total = + let + term = fundTxTemplate sender mid + buyGasData = J.object + [ "miner-keyset" J..= ks + , "total" J..= total + ] + execMsg = Pact4.ExecMsg (RawCode "") (J.toLegacyJsonViaEncode buyGasData) + in (term, execMsg) +{-# INLINABLE mkFundTxTerm #-} + +mkBuyGasTerm + :: Text -- ^ Address of the sender from the command + -> GasSupply + -> (Expr SpanInfo, Pact4.ExecMsg RawCode) +mkBuyGasTerm sender total = (buyGasTemplate sender, execMsg) + where + execMsg = Pact4.ExecMsg (RawCode "") (J.toLegacyJsonViaEncode buyGasData) + buyGasData = J.object + [ "total" J..= total ] +{-# INLINABLE mkBuyGasTerm #-} + +mkRedeemGasTerm + :: MinerId -- ^ Id of the miner to fund + -> MinerKeys -- ^ Miner keyset + -> Text -- ^ Address of the sender from the command + -> GasSupply -- ^ The gas limit total * price + -> GasSupply -- ^ The gas used * price + -> (Expr SpanInfo, Pact4.ExecMsg RawCode) +mkRedeemGasTerm (MinerId mid) (MinerKeys ks) sender total fee = (redeemGasTemplate mid sender, execMsg) + where + execMsg = Pact4.ExecMsg (RawCode "") (J.toLegacyJsonViaEncode redeemGasData) + redeemGasData = J.object + [ "total" J..= total + , "fee" J..= J.toJsonViaEncode fee + , "miner-keyset" J..= ks + ] +{-# INLINABLE mkRedeemGasTerm #-} + +coinbaseTemplate :: Text -> Expr SpanInfo +coinbaseTemplate mid = + let midTerm = strLit mid + varApp = qn "coinbase" "coin" + rks = app (bn "read-keyset") [strLit "miner-keyset"] + rds = app (bn "read-decimal") [strLit "reward"] + in app varApp [midTerm, rks, rds] + +mkCoinbaseTerm :: MinerId -> MinerKeys -> GasSupply -> (Expr SpanInfo, Pact4.ExecMsg RawCode) +mkCoinbaseTerm (MinerId mid) (MinerKeys ks) reward = (coinbaseTemplate mid, execMsg) + where + execMsg = Pact4.ExecMsg (RawCode "") (J.toLegacyJsonViaEncode coinbaseData) + coinbaseData = J.object + [ "miner-keyset" J..= ks + , "reward" J..= reward + ] +{-# INLINABLE mkCoinbaseTerm #-} \ No newline at end of file diff --git a/src/Chainweb/Pact/TransactionExec.hs b/src/Chainweb/Pact/TransactionExec/Pact4.hs similarity index 58% rename from src/Chainweb/Pact/TransactionExec.hs rename to src/Chainweb/Pact/TransactionExec/Pact4.hs index 5d71af6ff..63db1b3b8 100644 --- a/src/Chainweb/Pact/TransactionExec.hs +++ b/src/Chainweb/Pact/TransactionExec/Pact4.hs @@ -8,7 +8,6 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TupleSections #-} -- | -- Module : Chainweb.Pact.TransactionExec -- Copyright : Copyright © 2018 Kadena LLC. @@ -18,19 +17,15 @@ -- -- Pact command execution and coin-contract transaction logic for Chainweb -- -module Chainweb.Pact.TransactionExec +module Chainweb.Pact.TransactionExec.Pact4 ( -- * Transaction Execution applyCmd , applyGenesisCmd , applyLocal , applyExec , applyExec' -, applyExecTng -, applyExecTng' , applyContinuation , applyContinuation' -, applyContinuationTng -, applyContinuationTng' , runPayload , readInitModules , enablePactEvents' @@ -68,16 +63,13 @@ import Control.Parallel.Strategies(using, rseq) import Data.Aeson hiding ((.=)) import qualified Data.Aeson as A -import qualified Data.Aeson.Types as A import Data.Bifunctor import qualified Data.ByteString as B import qualified Data.ByteString.Short as SB -import Data.Coerce (coerce) import Data.Decimal (Decimal, roundTo) import Data.Default (def) import Data.Foldable (fold, for_) import Data.IORef -import qualified Data.Map.Strict as Map import qualified Data.HashMap.Strict as HM import qualified Data.List as List import qualified Data.Map.Strict as M @@ -89,15 +81,15 @@ import qualified System.LogLevel as L -- internal Pact modules +import Chainweb.Pact.Backend.Types (_cpPactDbEnv) import Pact.Eval (eval, liftTerm) import Pact.Gas (freeGasEnv) import Pact.Interpreter -import qualified Pact.JSON.Decode as J import qualified Pact.JSON.Encode as J import Pact.JSON.Legacy.Value import Pact.Native.Capabilities (evalCap) import Pact.Native.Internal (appToCap) -import Pact.Parse (ParsedDecimal(..), ParsedInteger(..)) +import Pact.Parse (ParsedDecimal(..)) import Pact.Runtime.Capabilities (popCapStack) import Pact.Runtime.Utils (lookupModule) import Pact.Types.Capability @@ -114,31 +106,7 @@ import Pact.Types.Verifier import Pact.Types.Util as PU -import Pact.Core.Serialise.LegacyPact () -import qualified Pact.Core.Compile as PCore -import qualified Pact.Core.Evaluate as PCore -import qualified Pact.Core.Command as PCore -import qualified Pact.Core.Capabilities as PCore -import qualified Pact.Core.Errors as PCore -import qualified Pact.Core.Names as PCore -import qualified Pact.Core.Namespace as PCore -import qualified Pact.Core.Persistence as PCore -import qualified Pact.Core.Pretty as PCore -import qualified Pact.Core.Gas as PCore -import qualified Pact.Core.Hash as PCore -import qualified Pact.Core.PactValue as PCore -import qualified Pact.Core.Environment as PCore -import qualified Pact.Core.Builtin as PCore -import qualified Pact.Core.Syntax.ParseTree as PCore -import qualified Pact.Core.DefPacts.Types as PCore -import qualified Pact.Core.Scheme as PCore -import qualified Pact.Core.StableEncoding as PCore -import qualified Pact.Core.SPV as PCore -import qualified Pact.Core.Verifiers as PCore -import qualified Pact.Core.Info as PCore - -- internal Chainweb modules -import qualified Chainweb.Pact.Transactions.CoinCoreV4Transactions as CoinCoreV4 import Chainweb.BlockHeader import Chainweb.BlockHeight @@ -147,21 +115,16 @@ import qualified Chainweb.ChainId as Chainweb import Chainweb.Mempool.Mempool (requestKeyToTransactionHash) import Chainweb.Miner.Pact import Chainweb.Pact.Service.Types -import Chainweb.Pact.Templates -import Chainweb.Pact.Utils -import qualified Chainweb.Pact.Conversion as PactConversion +import Chainweb.Pact.Templates.Pact4 import Chainweb.Pact.Types hiding (logError) -import Chainweb.Pact.Backend.Types import Chainweb.Transaction +import Chainweb.Utils (encodeToByteString, sshow, tryAllSynchronous, T2(..), T3(..)) import Chainweb.VerifierPlugin -import Chainweb.Utils (encodeToByteString, sshow, tryAllSynchronous, T2(..), T4(..)) import Chainweb.Version as V import Chainweb.Version.Guards as V import Chainweb.Version.Utils as V import Pact.JSON.Encode (toJsonViaEncode) -import qualified Debug.Trace as TRACE - -- Note [Throw out verifier proofs eagerly] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- We try to discard verifier proofs eagerly so that we don't hang onto them in @@ -192,15 +155,6 @@ magic_GENESIS = mkMagicCapSlot "GENESIS" debitCap :: Text -> SigCapability debitCap s = mkCoinCap "DEBIT" [PLiteral (LString s)] -core_magic_COINBASE :: PCore.CapSlot PCore.QualifiedName PCore.PactValue -core_magic_COINBASE = mkMagicCoreCapSlot "COINBASE" - -core_magic_GAS :: PCore.CapSlot PCore.QualifiedName PCore.PactValue -core_magic_GAS = mkMagicCoreCapSlot "GAS" - --- core_magic_GENESIS :: PCore.CapSlot PCore.QualifiedName PCore.PactValue --- core_magic_GENESIS = mkMagicCoreCapSlot "GENESIS" - onChainErrorPrintingFor :: TxContext -> UnexpectedErrorPrinting onChainErrorPrintingFor txCtx = if guardCtx chainweb219Pact txCtx @@ -218,11 +172,11 @@ applyCmd -- ^ Pact logger -> Maybe logger -- ^ Pact gas logger - -> (PactDbEnv p, CoreDb) + -> PactDbEnv p -- ^ Pact db environment -> Miner -- ^ The miner chosen to mine the block - -> (GasModel, PCore.GasModel PCore.CoreBuiltin) + -> GasModel -- ^ Gas model (pact Service config) -> TxContext -- ^ tx metadata and parent header @@ -232,28 +186,23 @@ applyCmd -- ^ command with payload to execute -> Gas -- ^ initial gas used - -> (ModuleCache, CoreModuleCache) + -> ModuleCache -- ^ cached module state -> ApplyCmdExecutionContext -- ^ is this a local or send execution context? - -> IO (T4 (Either (CommandResult [TxLogJson]) PCore.CommandResult) ModuleCache CoreModuleCache (S.Set PactWarning)) -applyCmd v logger gasLogger (pdbenv, coreDb) miner (gasModel, gasModelCore) txCtx spv cmd initialGas (mcache0, mccache0) callCtx = do + -> IO (T3 (CommandResult [TxLogJson]) ModuleCache (S.Set PactWarning)) +applyCmd v logger gasLogger pdbenv miner gasModel txCtx spv cmd initialGas mcache0 callCtx = do T2 cr st <- runTransactionM cenv txst applyBuyGas let cache = _txCache st - coreCache = _txCoreCache st warns = _txWarnings st - pure $ T4 cr cache coreCache warns + pure $ T3 cr cache warns where stGasModel | chainweb217Pact' = gasModel | otherwise = _geGasModel freeGasEnv - - stGasModelCore - | chainweb217Pact' = gasModelCore - | otherwise = PCore.freeGasModel - txst = TransactionState mcache0 mccache0 mempty 0 Nothing stGasModel stGasModelCore mempty + txst = TransactionState mcache0 mempty 0 Nothing (Left stGasModel) mempty quirkGasFee = v ^? versionQuirks . quirkGasFees . ix requestKey executionConfigNoHistory = ExecutionConfig @@ -264,8 +213,8 @@ applyCmd v logger gasLogger (pdbenv, coreDb) miner (gasModel, gasModelCore) txCt ++ [ FlagPreserveNsModuleInstallBug | not isModuleNameFix2 ]) <> flagsFor v (ctxChainId txCtx) (ctxCurrentBlockHeight txCtx) - cenv = TransactionEnv Transactional pdbenv coreDb logger gasLogger (ctxToPublicData txCtx) spv nid gasPrice - requestKey (fromIntegral gasLimit) executionConfigNoHistory quirkGasFee usePact5 + cenv = TransactionEnv Transactional (Left pdbenv) logger gasLogger (ctxToPublicData txCtx) spv nid gasPrice + requestKey (fromIntegral gasLimit) executionConfigNoHistory quirkGasFee !requestKey = cmdToRequestKey cmd !gasPrice = view cmdGasPrice cmd @@ -281,7 +230,6 @@ applyCmd v logger gasLogger (pdbenv, coreDb) miner (gasModel, gasModelCore) txCt chainweb219Pact' = guardCtx chainweb219Pact txCtx chainweb223Pact' = guardCtx chainweb223Pact txCtx allVerifiers = verifiersAt v cid currHeight - usePact5 = pact5 v cid currHeight toEmptyPactError (PactError errty _ _ _) = PactError errty def [] mempty toOldListErr pe = pe { peDoc = listErrMsg } @@ -294,7 +242,6 @@ applyCmd v logger gasLogger (pdbenv, coreDb) miner (gasModel, gasModelCore) txCt applyRedeem r applyBuyGas = - -- TRACE.traceShowM ("applyBuyGas.CACHE: ", LHM.keys $ _getModuleCache mcache0, M.keys $ _getCoreModuleCache mccache0) catchesPactError logger (onChainErrorPrintingFor txCtx) (buyGas txCtx cmd miner) >>= \case Left e -> view txRequestKey >>= \rk -> throwM $ BuyGasFailure $ GasPurchaseFailure (requestKeyToTransactionHash rk) e @@ -320,42 +267,35 @@ applyCmd v logger gasLogger (pdbenv, coreDb) miner (gasModel, gasModelCore) txCt case verifierResult of Left err -> do let errMsg = "Tx verifier error: " <> getVerifierError err - Left <$> do - cmdResult <- failTxWith - (PactError TxFailure def [] (pretty errMsg)) - errMsg - redeemAllGas cmdResult + cmdResult <- failTxWith + (PactError TxFailure def [] (pretty errMsg)) + errMsg + redeemAllGas cmdResult Right verifierGasRemaining -> do txGasUsed += initGasRemaining - verifierGasRemaining applyPayload else applyPayload applyPayload = do - txGasModel .= gasModel - txGasModelCore .= gasModelCore + txGasModel .= (Left gasModel) if chainweb217Pact' then txGasUsed += initialGas else txGasUsed .= initialGas - if usePactTng then do - cr <- runPayloadTng cmd managedNamespacePolicy - return $ Right $ cr - else Left <$> do - cr <- catchesPactError logger (onChainErrorPrintingFor txCtx) $! runPayload cmd managedNamespacePolicy - case cr of - Left e - -- 2.19 onwards errors return on chain - | chainweb219Pact' -> displayPactError e - -- 2.17 errors were removed - | chainweb217Pact' -> stripPactError e - | chainweb213Pact' || not (isOldListErr e) -> displayPactError e - | otherwise -> do - r <- failTxWith (toOldListErr e) "tx failure for request key when running cmd" - redeemAllGas r - Right r -> applyRedeem r + cr <- catchesPactError logger (onChainErrorPrintingFor txCtx) $! runPayload cmd managedNamespacePolicy + case cr of + Left e + -- 2.19 onwards errors return on chain + | chainweb219Pact' -> displayPactError e + -- 2.17 errors were removed + | chainweb217Pact' -> stripPactError e + | chainweb213Pact' || not (isOldListErr e) -> displayPactError e + | otherwise -> do + r <- failTxWith (toOldListErr e) "tx failure for request key when running cmd" + redeemAllGas r + Right r -> applyRedeem r applyRedeem cr = do - txGasModel .= _geGasModel freeGasEnv - txGasModelCore .= PCore.freeGasModel + txGasModel .= Left (_geGasModel freeGasEnv) r <- catchesPactError logger (onChainErrorPrintingFor txCtx) $! redeemGas txCtx cmd miner case r of @@ -374,7 +314,7 @@ applyCmd v logger gasLogger (pdbenv, coreDb) miner (gasModel, gasModelCore) txCt $ set crLogs (Just logs) $ over crEvents (es ++) cr - return $ cr' + return cr' listErrMsg :: Doc listErrMsg = @@ -384,7 +324,7 @@ applyGenesisCmd :: (Logger logger) => logger -- ^ Pact logger - -> (PactDbEnv p, CoreDb) + -> PactDbEnv p -- ^ Pact db environment -> SPVSupport -- ^ SPV support (validates cont proofs) @@ -392,16 +332,15 @@ applyGenesisCmd -- ^ tx metadata -> Command (Payload PublicMeta ParsedCode) -- ^ command with payload to execute - -> IO (T2 (CommandResult [TxLogJson]) (ModuleCache, CoreModuleCache)) -applyGenesisCmd logger (dbEnv, coreDb) spv txCtx cmd = - second (\s -> (_txCache s, _txCoreCache s)) <$!> runTransactionM tenv txst go + -> IO (T2 (CommandResult [TxLogJson]) ModuleCache) +applyGenesisCmd logger dbEnv spv txCtx cmd = + second _txCache <$!> runTransactionM tenv txst go where nid = networkIdOf cmd rk = cmdToRequestKey cmd tenv = TransactionEnv { _txMode = Transactional - , _txDbEnv = dbEnv - , _txCoreDb = coreDb + , _txDbEnv = Left dbEnv , _txLogger = logger , _txGasLogger = Nothing , _txPublicData = def @@ -419,16 +358,13 @@ applyGenesisCmd logger (dbEnv, coreDb) spv txCtx cmd = -- after the block height where pact4.4 is on. <> S.fromList [ FlagDisableInlineMemCheck, FlagDisablePact44 ] , _txQuirkGasFee = Nothing - , _txusePact5 = False } txst = TransactionState { _txCache = mempty - , _txCoreCache = mempty , _txLogs = mempty , _txGasUsed = 0 , _txGasId = Nothing - , _txGasModel = _geGasModel freeGasEnv - , _txGasModelCore = PCore.freeGasModel + , _txGasModel = Left $ _geGasModel freeGasEnv , _txWarnings = mempty } @@ -469,7 +405,7 @@ applyCoinbase => ChainwebVersion -> logger -- ^ Pact logger - -> (PactDbEnv p, CoreDb) + -> PactDbEnv p -- ^ Pact db environment -> Miner -- ^ The miner chosen to mine the block @@ -481,10 +417,10 @@ applyCoinbase -- ^ enforce coinbase failure or not -> CoinbaseUsePrecompiled -- ^ always enable precompilation - -> (ModuleCache, CoreModuleCache) - -> IO (T2 (Either (CommandResult [TxLogJson]) PCore.CommandResult) (Maybe (ModuleCache, CoreModuleCache))) -applyCoinbase v logger (dbEnv, coreDb) (Miner mid mks@(MinerKeys mk)) reward@(ParsedDecimal d) txCtx - (EnforceCoinbaseFailure enfCBFailure) (CoinbaseUsePrecompiled enablePC) (mc, cmc) + -> ModuleCache + -> IO (T2 (CommandResult [TxLogJson]) (Maybe ModuleCache)) +applyCoinbase v logger dbEnv (Miner mid mks@(MinerKeys mk)) reward@(ParsedDecimal d) txCtx + (EnforceCoinbaseFailure enfCBFailure) (CoinbaseUsePrecompiled enablePC) mc | fork1_3InEffect || enablePC = do when chainweb213Pact' $ enforceKeyFormats (\k -> throwM $ CoinbaseFailure $ "Invalid miner key: " <> sshow k) @@ -492,14 +428,12 @@ applyCoinbase v logger (dbEnv, coreDb) (Miner mid mks@(MinerKeys mk)) reward@(Pa mk let (cterm, cexec) = mkCoinbaseTerm mid mks reward interp = Interpreter $ \_ -> do put initState; fmap pure (eval cterm) - coreState = setCoreModuleCache cmc $ initCoreCapabilities [core_magic_COINBASE] - coinbaseTerm = mkCoinbaseCoreTerm mid - go interp coreState cexec (Just coinbaseTerm) + + go interp cexec | otherwise = do cexec <- mkCoinbaseCmd mid mks reward let interp = initStateInterpreter initState - let coreState = setCoreModuleCache cmc $ initCoreCapabilities [core_magic_COINBASE] - go interp coreState cexec Nothing + go interp cexec where chainweb213Pact' = chainweb213Pact v cid bh fork1_3InEffect = vuln797Fix v cid bh @@ -509,10 +443,9 @@ applyCoinbase v logger (dbEnv, coreDb) (Miner mid mks@(MinerKeys mk)) reward@(Pa , S.singleton FlagDisableHistoryInTransactionalMode , flagsFor v (ctxChainId txCtx) (ctxCurrentBlockHeight txCtx) ] - usePact5 = pact5 v (ctxChainId txCtx) bh - tenv = TransactionEnv Transactional dbEnv coreDb logger Nothing (ctxToPublicData txCtx) noSPVSupport - Nothing 0.0 rk 0 ec Nothing usePact5 - txst = TransactionState mc cmc mempty 0 Nothing (_geGasModel freeGasEnv) (PCore.freeGasModel) mempty + tenv = TransactionEnv Transactional (Left dbEnv) logger Nothing (ctxToPublicData txCtx) noSPVSupport + Nothing 0.0 rk 0 ec Nothing + txst = TransactionState mc mempty 0 Nothing (Left $ _geGasModel freeGasEnv) mempty initState = setModuleCache mc $ initCapabilities [magic_COINBASE] rk = RequestKey chash parent = _tcParentHeader txCtx @@ -523,63 +456,37 @@ applyCoinbase v logger (dbEnv, coreDb) (Miner mid mks@(MinerKeys mk)) reward@(Pa -- NOTE: it holds that @ _pdPrevBlockHash pd == encode _blockHash@ -- NOTE: chash includes the /quoted/ text of the parent header. - go interp evState cexec@(ExecMsg _ execData) mCoinbaseTerm = evalTransactionM tenv txst $! do - case mCoinbaseTerm of - Just coinbaseTerm | usePact5 -> do - evalEnv <- mkCoreEvalEnv managedNamespacePolicy (MsgData execData Nothing chash mempty []) - cr <- liftIO $ PCore.evalTermExec evalEnv evState coinbaseTerm - - case cr of - Right er -> do - debug - $! "successful coinbase of " - <> T.take 18 (sshow d) - <> " to " - <> sshow mid - - upgradedModuleCache <- applyUpgrades v cid bh - - txCoreCache .= (CoreModuleCache (PCore._erLoadedModules er)) - - return $! T2 - (Right $ PCore.CommandResult $ PCore.PactResult $ Right $ PCore.PERExpr er) - upgradedModuleCache - - Left e - | throwCritical -> throwM $ CoinbaseFailure $ sshow e - | otherwise -> (`T2` Nothing) <$> (Left <$> failTxWith (PactError EvalError (Info Nothing) [] mempty) "coinbase tx failure") - _ -> do - cr <- catchesPactError logger (onChainErrorPrintingFor txCtx) $ - applyExec' 0 interp cexec [] [] chash managedNamespacePolicy - - -- liftIO $ print cr - case cr of - Left e - | throwCritical -> throwM $ CoinbaseFailure $ sshow e - | otherwise -> (`T2` Nothing) <$> (Left <$> failTxWith e "coinbase tx failure") - Right er -> do - debug - $! "successful coinbase of " - <> T.take 18 (sshow d) - <> " to " - <> sshow mid - - upgradedModuleCache <- applyUpgrades v cid bh - - logs <- use txLogs - - return $! T2 - (Left $ CommandResult - { _crReqKey = rk - , _crTxId = _erTxId er - , _crResult = PactResult (Right (last (_erOutput er))) - , _crGas = _erGas er - , _crLogs = Just logs - , _crContinuation = _erExec er - , _crMetaData = Nothing - , _crEvents = _erEvents er - }) - upgradedModuleCache + go interp cexec = evalTransactionM tenv txst $! do + cr <- catchesPactError logger (onChainErrorPrintingFor txCtx) $ + applyExec' 0 interp cexec [] [] chash managedNamespacePolicy + + case cr of + Left e + | throwCritical -> throwM $ CoinbaseFailure $ sshow e + | otherwise -> (`T2` Nothing) <$> failTxWith e "coinbase tx failure" + Right er -> do + debug + $! "successful coinbase of " + <> T.take 18 (sshow d) + <> " to " + <> sshow mid + + upgradedModuleCache <- applyUpgrades v cid bh + + logs <- use txLogs + + return $! T2 + CommandResult + { _crReqKey = rk + , _crTxId = _erTxId er + , _crResult = PactResult (Right (last (_erOutput er))) + , _crGas = _erGas er + , _crLogs = Just logs + , _crContinuation = _erExec er + , _crMetaData = Nothing + , _crEvents = _erEvents er + } + upgradedModuleCache applyLocal :: (Logger logger) @@ -587,9 +494,9 @@ applyLocal -- ^ Pact logger -> Maybe logger -- ^ Pact gas logger - -> (PactDbEnv p, CoreDb) + -> PactDbEnv p -- ^ Pact db environment - -> (GasModel, PCore.GasModel PCore.CoreBuiltin) + -> GasModel -- ^ Gas model (pact Service config) -> TxContext -- ^ tx metadata and parent header @@ -597,10 +504,10 @@ applyLocal -- ^ SPV support (validates cont proofs) -> Command PayloadWithText -- ^ command with payload to execute - -> (ModuleCache, CoreModuleCache) + -> ModuleCache -> ExecutionConfig - -> IO (Either (CommandResult [TxLogJson]) PCore.CommandResult) -applyLocal logger gasLogger (dbEnv, coreDb) (gasModel, gasModelCore) txCtx spv cmdIn (mc, cmc) execConfig = + -> IO (CommandResult [TxLogJson]) +applyLocal logger gasLogger dbEnv gasModel txCtx spv cmdIn mc execConfig = evalTransactionM tenv txst go where !cmd = payloadObj <$> cmdIn `using` traverse rseq @@ -611,15 +518,14 @@ applyLocal logger gasLogger (dbEnv, coreDb) (gasModel, gasModelCore) txCtx spv c !verifiers = fromMaybe [] $ _pVerifiers $ _cmdPayload cmd !gasPrice = view cmdGasPrice cmd !gasLimit = view cmdGasLimit cmd - tenv = TransactionEnv Local dbEnv coreDb logger gasLogger (ctxToPublicData txCtx) spv nid gasPrice - rk (fromIntegral gasLimit) execConfig Nothing usePact5 - txst = TransactionState mc cmc mempty 0 Nothing gasModel gasModelCore mempty + tenv = TransactionEnv Local (Left dbEnv) logger gasLogger (ctxToPublicData txCtx) spv nid gasPrice + rk (fromIntegral gasLimit) execConfig Nothing + txst = TransactionState mc mempty 0 Nothing (Left gasModel) mempty gas0 = initialGasOf (_cmdPayload cmdIn) currHeight = ctxCurrentBlockHeight txCtx cid = V._chainId txCtx v = _chainwebVersion txCtx allVerifiers = verifiersAt v cid currHeight - usePact5 = pact5 (ctxVersion txCtx) (ctxChainId txCtx) currHeight -- Note [Throw out verifier proofs eagerly] !verifiersWithNoProof = (fmap . fmap) (\_ -> ()) verifiers @@ -631,7 +537,7 @@ applyLocal logger gasLogger (dbEnv, coreDb) (gasModel, gasModelCore) txCtx spv c case verifierResult of Left err -> do let errMsg = "Tx verifier error: " <> getVerifierError err - Left <$> failTxWith + failTxWith (PactError TxFailure def [] (pretty errMsg)) errMsg Right verifierGasRemaining -> do @@ -640,45 +546,24 @@ applyLocal logger gasLogger (dbEnv, coreDb) (gasModel, gasModelCore) txCtx spv c applyPayload gas1 m = do interp <- gasInterpreter gas1 - coreState <- do - cmc' <- use txCoreCache - pure $ setCoreModuleCache cmc' def cr <- catchesPactError logger PrintsUnexpectedError $! case m of - Exec em -> do - if usePact5 then applyExecTng gas1 coreState em signers chash managedNamespacePolicy - else applyExec gas1 interp em signers verifiersWithNoProof chash managedNamespacePolicy + Exec em -> + applyExec gas1 interp em signers verifiersWithNoProof chash managedNamespacePolicy Continuation cm -> - if usePact5 then applyContinuationTng gas1 coreState cm signers chash managedNamespacePolicy - else applyContinuation gas1 interp cm signers chash managedNamespacePolicy - - if usePactTng then do - cr <- case m of - Exec em -> applyExecTng gas1 coreState em signers chash managedNamespacePolicy - Continuation cm -> applyContinuationTng gas1 coreState cm signers chash managedNamespacePolicy - - Right <$> case PCore._pactResult $ PCore._crResult cr of - Left e -> do - failTx5With e "applyLocal" - pure cr - Right _ -> pure cr - else do - cr <- catchesPactError logger PrintsUnexpectedError $! case m of - Exec em -> applyExec gas1 interp em signers verifiersWithNoProof chash managedNamespacePolicy - Continuation cm -> applyContinuation gas1 interp cm signers chash managedNamespacePolicy - - Left <$> case cr of - Left e -> failTxWith e "applyLocal" - Right r -> return $! r { _crMetaData = Just (J.toJsonViaEncode $ ctxToPublicData' txCtx) } + applyContinuation gas1 interp cm signers chash managedNamespacePolicy + + case cr of + Left e -> failTxWith e "applyLocal" + Right r -> return $! r { _crMetaData = Just (J.toJsonViaEncode $ ctxToPublicData' txCtx) } go = checkTooBigTx gas0 gasLimit (applyVerifiers $ _pPayload $ _cmdPayload cmd) return readInitModules :: forall logger tbl. (Logger logger) - => PactBlockM logger tbl (ModuleCache, CoreModuleCache) + => PactBlockM logger tbl ModuleCache readInitModules = do logger <- view (psServiceEnv . psLogger) dbEnv <- _cpPactDbEnv <$> view psBlockDbEnv - coreDb <- _cpPactCoreDbEnv <$> view psBlockDbEnv txCtx <- getTxContext def -- guarding chainweb 2.17 here to allow for @@ -695,15 +580,14 @@ readInitModules = do rk = RequestKey chash nid = Nothing chash = pactInitialHash - usePact5 = True - tenv = TransactionEnv Local dbEnv coreDb logger Nothing (ctxToPublicData txCtx) noSPVSupport nid 0.0 - rk 0 def Nothing usePact5 - txst = TransactionState mempty mempty mempty 0 Nothing (_geGasModel freeGasEnv) PCore.freeGasModel mempty + tenv = TransactionEnv Local (Left dbEnv) logger Nothing (ctxToPublicData txCtx) noSPVSupport nid 0.0 + rk 0 def Nothing + txst = TransactionState mempty mempty 0 Nothing (Left $ _geGasModel freeGasEnv) mempty interp = defaultInterpreter die msg = throwM $ PactInternalError $ "readInitModules: " <> msg mkCmd = buildExecParsedCode (pactParserVersion v cid h) Nothing run msg cmd = do - er <- catchesPactError logger (onChainErrorPrintingFor txCtx) $! do + er <- catchesPactError logger (onChainErrorPrintingFor txCtx) $! applyExec' 0 interp cmd [] [] chash permissiveNamespacePolicy case er of Left e -> die $ msg <> ": failed: " <> sshow e @@ -711,8 +595,10 @@ readInitModules = do [] -> die $ msg <> ": empty result" (o:_) -> return o - go :: TransactionM logger p (ModuleCache, CoreModuleCache) + + go :: TransactionM logger p ModuleCache go = do + -- see if fungible-v2 is there checkCmd <- liftIO $ mkCmd "(contains \"fungible-v2\" (list-modules))" checkFv2 <- run "check fungible-v2" checkCmd @@ -738,22 +624,18 @@ readInitModules = do void $ run "load modules" refModsCmd -- return loaded cache - c <- use txCache - cc <- use txCoreCache - pure (c, cc) + use txCache -- Only load coin and its dependencies for chainweb >=2.17 -- Note: no need to check if things are there, because this -- requires a block height that witnesses the invariant. -- -- if this changes, we must change the filter in 'updateInitCache' - goCw217 :: TransactionM logger p (ModuleCache, CoreModuleCache) + goCw217 :: TransactionM logger p ModuleCache goCw217 = do coinDepCmd <- liftIO $ mkCmd "coin.MINIMUM_PRECISION" void $ run "load modules" coinDepCmd - c <- use txCache - cc <- use txCoreCache - pure (c, cc) + use txCache if | chainweb224Pact' -> pure mempty | chainweb217Pact' -> liftIO $ evalTransactionM tenv txst goCw217 @@ -773,25 +655,18 @@ applyUpgrades => ChainwebVersion -> Chainweb.ChainId -> BlockHeight - -> TransactionM logger p (Maybe (ModuleCache, CoreModuleCache)) + -> TransactionM logger p (Maybe ModuleCache) applyUpgrades v cid height | Just upg <- v ^? versionUpgrades . onChain cid . at height . _Just = applyUpgrade upg | cleanModuleCache v cid height = filterModuleCache | otherwise = return Nothing where - coinModuleName = ModuleName "coin" Nothing - coinCoreModuleName = PCore.ModuleName "coin" Nothing - installCoinModuleAdmin = set (evalCapabilities . capModuleAdmin) $ S.singleton coinModuleName - -- installCoreCoinModuleAdmin = set (PCore.esCaps . PCore.csModuleAdmin) $ S.singleton coinCoreModuleName + installCoinModuleAdmin = set (evalCapabilities . capModuleAdmin) $ S.singleton (ModuleName "coin" Nothing) filterModuleCache = do mc <- use txCache - cmc <- use txCoreCache - pure $ Just $ - ( filterModuleCacheByKey (== coinModuleName) mc - , filterCoreModuleCacheByKey (== coinCoreModuleName) cmc - ) + pure $ Just $ filterModuleCacheByKey (== "coin") mc applyUpgrade upg = do infoLog "Applying upgrade!" @@ -808,20 +683,17 @@ applyUpgrades v cid height caches <- local (txExecutionConfig .~ ExecutionConfig flags) (mapM applyTx payloads) - return $ Just $ bimap mconcat mconcat $ unzip $ reverse caches + return $ Just $ mconcat $ reverse caches interp = initStateInterpreter $ installCoinModuleAdmin $ initCapabilities [mkMagicCapSlot "REMEDIATE"] - -- coreInitState = installCoreCoinModuleAdmin $ initCoreCapabilities [mkMagicCoreCapSlot "REMEDIATE"] applyTx tx = do infoLog $ "Running upgrade tx " <> sshow (_cmdHash tx) + tryAllSynchronous (runGenesis tx permissiveNamespacePolicy interp) >>= \case - Right _ -> do - c <- use txCache - cc <- use txCoreCache - pure (c, cc) + Right _ -> use txCache Left e -> do logError $ "Upgrade transaction failed! " <> sshow e throwM e @@ -843,20 +715,6 @@ failTxWith err msg = do return $! CommandResult rk Nothing (PactResult (Left err)) gas (Just logs) Nothing Nothing [] -failTx5With - :: (Logger logger) - => PCore.PactError PCore.SpanInfo - -> Text - -> TransactionM logger p () -failTx5With err msg = do - logs <- use txLogs - gas <- view txGasLimit -- error means all gas was charged - rk <- view txRequestKey - l <- view txLogger - - liftIO $ logFunction l L.Info - (Pact5TxFailureLog rk err msg) - runPayload :: (Logger logger) => Command (Payload PublicMeta ParsedCode) @@ -865,46 +723,18 @@ runPayload runPayload cmd nsp = do g0 <- use txGasUsed interp <- gasInterpreter g0 - coreState <- do - cmc <- use txCoreCache - pure $ setCoreModuleCache cmc def -- Note [Throw out verifier proofs eagerly] let !verifiersWithNoProof = (fmap . fmap) (\_ -> ()) verifiers `using` (traverse . traverse) rseq - usePact5 <- view txusePact5 case payload of - Exec pm -> applyExec g0 interp pm signers verifiersWithNoProof chash nsp - Continuation ym -> applyContinuation g0 interp ym signers chash nsp - - where - verifiers = fromMaybe [] $ _pVerifiers $ _cmdPayload cmd - signers = _pSigners $ _cmdPayload cmd - chash = toUntypedHash $ _cmdHash cmd - payload = _pPayload $ _cmdPayload cmd + Exec pm -> + applyExec g0 interp pm signers verifiersWithNoProof chash nsp + Continuation ym -> + applyContinuation g0 interp ym signers chash nsp -runPayloadTng - :: (Logger logger) - => Command (Payload PublicMeta ParsedCode) - -> NamespacePolicy - -> TransactionM logger p PCore.CommandResult -runPayloadTng cmd nsp = do - g0 <- use txGasUsed - interp <- gasInterpreter g0 - coreState <- do - cmc <- use txCoreCache - pure $ setCoreModuleCache cmc def - - -- Note [Throw out verifier proofs eagerly] - let !verifiersWithNoProof = - (fmap . fmap) (\_ -> ()) verifiers - `using` (traverse . traverse) rseq - - case payload of - Exec pm -> applyExecTng g0 coreState pm signers chash nsp - Continuation ym -> applyContinuationTng g0 coreState ym signers chash nsp where verifiers = fromMaybe [] $ _pVerifiers $ _cmdPayload cmd @@ -921,7 +751,7 @@ runGenesis -> Interpreter p -> TransactionM logger p (CommandResult [TxLogJson]) runGenesis cmd nsp interp = case payload of - Exec pm -> -- TODO: make it work for the core + Exec pm -> applyExec 0 interp pm signers verifiersWithNoProof chash nsp Continuation ym -> applyContinuation 0 interp ym signers chash nsp @@ -935,20 +765,6 @@ runGenesis cmd nsp interp = case payload of chash = toUntypedHash $ _cmdHash cmd payload = _pPayload $ _cmdPayload cmd -runGenesisCore - :: (Logger logger) - => Command (Payload PublicMeta ParsedCode) - -> NamespacePolicy - -> PCore.EvalState PCore.CoreBuiltin PCore.SpanInfo - -> TransactionM logger p () -runGenesisCore cmd nsp coreState = case payload of - Exec pm -> void $ applyExecTng' 0 coreState pm signers chash nsp - Continuation _ -> error "runGenesisCore Continuation not supported" - where - signers = _pSigners $ _cmdPayload cmd - chash = toUntypedHash $ _cmdHash cmd - payload = _pPayload $ _cmdPayload cmd - -- | Execute an 'ExecMsg' and Return the result with module cache -- applyExec @@ -976,96 +792,6 @@ applyExec initialGas interp em senderSigs verifiers hsh nsp = do return $ CommandResult rk _erTxId (PactResult (Right lastResult)) _erGas (Just logs) _erExec Nothing _erEvents -mkCommandResultFromCoreResult - :: (Logger logger) - => PCore.EvalResult a - -> TransactionM logger p (CommandResult [TxLogJson]) -mkCommandResultFromCoreResult PCore.EvalResult{..} = do - !logs <- use txLogs - !rk <- view txRequestKey - - let convertPactValue pv = J.decodeStrict $ PCore.encodeStable pv - - let !lastResult = last _erOutput - - let - toModuleName m = - ModuleName - { _mnName = PCore._mnName m - , _mnNamespace = coerce <$> PCore._mnNamespace m - } - toQualifiedName qn = - QualifiedName - { _qnQual = toModuleName $ PCore._qnModName qn - , _qnName = PCore._qnName qn - , _qnInfo = Info Nothing - } - toPactContinuation dpc = - PactContinuation - { _pcDef = QName $ toQualifiedName $ PCore._pcName dpc - , _pcArgs = catMaybes $ convertPactValue <$> PCore._pcArgs dpc - } - toYield y = - Yield - { _yData = ObjectMap $ Map.fromList $ map (\(f,s) -> (coerce f, fromJust $ convertPactValue s)) $ Map.toList $ PCore._yData y - , _yProvenance = PCore._yProvenance y <&> \p -> Provenance - { _pTargetChainId = coerce $ PCore._pTargetChainId p - , _pModuleHash = coerce $ PCore._pModuleHash p - } - , _ySourceChain = coerce <$> PCore._ySourceChain y - } - toNested dpe = - NestedPactExec - { _npeStepCount = PCore._peStepCount dpe - , _npeYield = toYield <$> PCore._peYield dpe - , _npeExecuted = Nothing - , _npeStep = PCore._peStep dpe - , _npePactId = coerce $ PCore._peDefPactId dpe - , _npeContinuation = toPactContinuation $ PCore._peContinuation dpe - , _npeNested = Map.fromList $ map (\(f, s) -> (coerce f, toNested s)) $ Map.toList $ PCore._peNestedDefPactExec dpe - } - toPactExec dpe = - PactExec - { _peStepCount = PCore._peStepCount dpe - , _peYield = toYield <$> PCore._peYield dpe - , _peExecuted = Nothing - , _peStep = PCore._peStep dpe - , _pePactId = coerce $ PCore._peDefPactId dpe - , _peContinuation = toPactContinuation $ PCore._peContinuation dpe - , _peStepHasRollback = PCore._peStepHasRollback dpe - , _peNested = Map.fromList $ map (\(f, s) -> (coerce f, toNested s)) $ Map.toList $ PCore._peNestedDefPactExec dpe - } - toValResult = \case - PCore.InterpretValue v _ -> fromJust $ convertPactValue v - _ -> undefined - toPactEvent e = - PactEvent - { _eventName = PCore._peName e - , _eventParams = catMaybes $ convertPactValue <$> PCore._peArgs e - , _eventModule = toModuleName $ PCore._peModule e - , _eventModuleHash = coerce $ PCore._peModuleHash e - } - - return $ CommandResult rk (coerce _erTxId) (PactResult (Right $ toValResult lastResult)) - (case _erGas of { PCore.Gas g -> Gas $ fromIntegral g }) - (Just logs) (toPactExec <$> _erExec) Nothing (map toPactEvent _erEvents) - -applyExecTng - :: (Logger logger) - => Gas - -> PCore.EvalState PCore.CoreBuiltin PCore.SpanInfo - -> ExecMsg ParsedCode - -> [Signer] - -> Hash - -> NamespacePolicy - -> TransactionM logger p PCore.CommandResult -- (Either (PCore.PactError PCore.SpanInfo) (PCore.EvalResult [PCore.TopLevel PCore.SpanInfo])) -applyExecTng initialGas coreState em senderSigs hsh nsp = do - er <- applyExecTng' initialGas coreState em senderSigs hsh nsp - - -- return er - pure $ PCore.CommandResult $ PCore.PactResult $ PCore.PERTopLevel <$> er - -- either id mkCommandResultFromCoreResult er - -- | Variation on 'applyExec' that returns 'EvalResult' as opposed to -- wrapping it up in a JSON result. -- @@ -1104,48 +830,6 @@ applyExec' initialGas interp (ExecMsg parsedCode execData) senderSigs verifiersW return quirkedEvalResult -applyExecTng' - :: (Logger logger) - => Gas - -> PCore.EvalState PCore.CoreBuiltin PCore.SpanInfo - -> ExecMsg ParsedCode - -> [Signer] - -> Hash - -> NamespacePolicy - -> TransactionM logger p (Either (PCore.PactError PCore.SpanInfo) (PCore.EvalResult [PCore.TopLevel PCore.SpanInfo])) -applyExecTng' (Gas initialGas) coreState (ExecMsg parsedCode execData) senderSigs hsh nsp - | null (_pcExps parsedCode) = throwCmdEx "No expressions found" - | otherwise = do - - evalEnv <- mkCoreEvalEnv nsp (MsgData execData Nothing hsh senderSigs []) - - setEnvGasCore (PCore.Gas $ fromIntegral initialGas) evalEnv - - ccache <- use txCoreCache - - - er <- liftIO $! PCore.evalExec evalEnv coreState (PCore.RawCode $ _pcCode parsedCode) - case er of - Right er' -> do - -- liftIO $ print ("PCORE._erOutput", PCore._erOutput er') - - -- if we specified this transaction's gas fee manually as a "quirk", - -- here we set the result's gas fee to agree with that - quirkGasFee <- view txQuirkGasFee - let quirkedEvalResult = case quirkGasFee of - Nothing -> er' - Just (Gas fee) -> er' { PCore._erGas = PCore.Gas $ fromIntegral fee } - - txCoreCache .= (CoreModuleCache $ PCore._erLoadedModules er') - return $ Right quirkedEvalResult - Left err -> do - -- TRACE.traceShowM ("CORE.applyExec' modulecache" :: String, show $ _getCoreModuleCache ccache) - - TRACE.traceShowM ("CORE.applyExec'!!!!" :: String, show err, show $ PCore.RawCode $ _pcCode parsedCode) - -- TODO: return either an error instead of throwing an exception here - fatal $ "Pact Tng execution failed: " <> (T.pack $ show $ PCore.pretty err) - return $ Left err - enablePactEvents' :: ChainwebVersion -> V.ChainId -> BlockHeight -> [ExecutionFlag] enablePactEvents' v cid bh = [FlagDisablePactEvents | not (enablePactEvents v cid bh)] @@ -1225,32 +909,10 @@ applyContinuation initialGas interp cm senderSigs hsh nsp = do return $! CommandResult rk _erTxId (PactResult (Right (last _erOutput))) _erGas (Just logs) _erExec Nothing _erEvents -applyContinuationTng - :: (Logger logger) - => Gas - -> PCore.EvalState PCore.CoreBuiltin PCore.SpanInfo - -> ContMsg - -> [Signer] - -> Hash - -> NamespacePolicy - -> TransactionM logger p PCore.CommandResult -- (Either (PCore.PactError PCore.SpanInfo) (PCore.EvalResult [PCore.TopLevel PCore.SpanInfo])) -applyContinuationTng initialGas coreState cm senderSigs hsh nsp = do - er <- applyContinuationTng' initialGas coreState cm senderSigs hsh nsp - -- return er - -- either id mkCommandResultFromCoreResult - pure $ PCore.CommandResult $ PCore.PactResult $ PCore.PERTopLevel <$> er - - -- for_ _erLogGas $ \gl -> gasLog $ "gas logs: " <> sshow gl - - -- TODO: set tx warnings to eval warnings - -- txWarnings <>= _erWarnings setEnvGas :: Gas -> EvalEnv e -> TransactionM logger p () setEnvGas initialGas = liftIO . views eeGas (`writeIORef` gasToMilliGas initialGas) -setEnvGasCore :: PCore.Gas -> PCore.EvalEnv PCore.CoreBuiltin PCore.SpanInfo -> TransactionM logger p () -setEnvGasCore initialGas = liftIO . views PCore.eeGasRef (`writeIORef` PCore.gasToMilliGas initialGas) - -- | Execute a 'ContMsg' and return just eval result, not wrapped in a -- 'CommandResult' wrapper -- @@ -1282,50 +944,6 @@ applyContinuation' initialGas interp cm@(ContMsg pid s rb d _) senderSigs hsh ns where pactStep = Just $ PactStep s rb pid Nothing -applyContinuationTng' - :: (Logger logger) - => Gas - -> PCore.EvalState PCore.CoreBuiltin PCore.SpanInfo - -> ContMsg - -> [Signer] - -> Hash - -> NamespacePolicy - -> TransactionM logger p (Either (PCore.PactError PCore.SpanInfo) (PCore.EvalResult [PCore.TopLevel PCore.SpanInfo])) -applyContinuationTng' initialGas coreState (ContMsg pid s rb d proof) senderSigs hsh nsp = do - - evalEnv <- mkCoreEvalEnv nsp (MsgData d pactStep hsh senderSigs []) - - setEnvGasCore (PCore.Gas $ fromIntegral initialGas) evalEnv - - let - convertPactValue pv = PactConversion.fromLegacyPactValue $ - aeson (error "applyContinuationTng': failed to parseJSON pact value") id $ A.fromJSON $ _getLegacyValue pv - - coreCm = PCore.ContMsg - { PCore._cmPactId = coerce pid - , PCore._cmStep = s - , PCore._cmRollback = rb - , PCore._cmData = either (error "applyContinuationTng': failed to convert pact value") id $ convertPactValue d - , PCore._cmProof = coerce proof - } - - er <- liftIO $! PCore.evalContinuation evalEnv coreState coreCm - case er of - Right er' -> do - -- if we specified this transaction's gas fee manually as a "quirk", - -- here we set the result's gas fee to agree with that - quirkGasFee <- view txQuirkGasFee - let quirkedEvalResult = case quirkGasFee of - Nothing -> er' - Just (Gas fee) -> er' { PCore._erGas = PCore.Gas $ fromIntegral fee } - - txCoreCache .= (CoreModuleCache $ PCore._erLoadedModules er') - return $ Right $ quirkedEvalResult - err -> pure err - - where - pactStep = Just $ PactStep s rb pid Nothing - -- | Build and execute 'coin.buygas' command from miner info and user command -- info (see 'TransactionExec.applyCmd') -- @@ -1350,11 +968,10 @@ buyGas txCtx cmd (Miner mid mks) = go go = do mcache <- use txCache - cmcache <- use txCoreCache supply <- gasSupplyOf <$> view txGasLimit <*> view txGasPrice logGas <- isJust <$> view txGasLogger - let (buyGasTerm, buyGasCmd@(ExecMsg _ execData)) = + let (buyGasTerm, buyGasCmd) = -- post-chainweb 2.24, we call buy-gas directly rather than -- going through fund-tx which is a defpact. if isChainweb224Pact @@ -1365,7 +982,6 @@ buyGas txCtx cmd (Miner mid mks) = go -- of our choice. we do the same to redeem gas. interp mc = Interpreter $ \_input -> put (initState mc logGas) >> run (pure <$> eval buyGasTerm) - coreState = setCoreModuleCache cmcache $ initCoreCapabilities [core_magic_GAS] let gasCapName = QualifiedName (ModuleName "coin" Nothing) "GAS" def @@ -1377,62 +993,26 @@ buyGas txCtx cmd (Miner mid mks) = go | otherwise = signer addDebitToSigners = fmap addDebit - signersWithDebit = addDebitToSigners $ _pSigners $ _cmdPayload cmd -- no verifiers are allowed in buy gas -- quirked gas is not used either result <- locally txQuirkGasFee (const Nothing) $ - applyExec' 0 (interp mcache) buyGasCmd signersWithDebit [] bgHash managedNamespacePolicy - - usePact5 <- view txusePact5 - if usePact5 then do - evalEnv <- mkCoreEvalEnv managedNamespacePolicy (MsgData execData Nothing bgHash signersWithDebit []) - - let - t = if isChainweb224Pact - then mkBuyGasCoreTerm sender - else mkFundTxCoreTerm mid sender - - er <- liftIO $ PCore.evalTermExec evalEnv coreState t - case er of - Right er' -> do - case PCore._erExec er' of - Nothing - | isChainweb224Pact -> - return () - | otherwise -> - -- should never occur pre-chainweb 2.24: - -- would mean coin.fund-tx is not a pact - fatal "buyGas: Internal error - empty continuation before 2.24 fork" - Just pe - | isChainweb224Pact -> - fatal "buyGas: Internal error - continuation found after 2.24 fork" - | otherwise -> do - void $! txGasId .= (Just $! GasId (coerce $ PCore._peDefPactId pe)) - txCoreCache .= (CoreModuleCache $ PCore._erLoadedModules er') - Left err -> do - TRACE.traceM $ "CORE.buyGas failed!!" <> sshow err <> "\n" <> sshow t - fatal $ "buyGas: Internal error - " <> sshow err - else do - -- no verifiers are allowed in buy gas - -- quirked gas is not used either - result <- locally txQuirkGasFee (const Nothing) $ - applyExec' 0 (interp mcache) buyGasCmd - (_pSigners $ _cmdPayload cmd) [] bgHash managedNamespacePolicy - - case _erExec result of - Nothing - | isChainweb224Pact -> - return () - | otherwise -> - -- should never occur pre-chainweb 2.24: - -- would mean coin.fund-tx is not a pact - fatal "buyGas: Internal error - empty continuation before 2.24 fork" - Just pe - | isChainweb224Pact -> - fatal "buyGas: Internal error - continuation found after 2.24 fork" - | otherwise -> - void $! txGasId .= (Just $! GasId (_pePactId pe)) + applyExec' 0 (interp mcache) buyGasCmd + (addDebitToSigners $ _pSigners $ _cmdPayload cmd) [] bgHash managedNamespacePolicy + + case _erExec result of + Nothing + | isChainweb224Pact -> + return () + | otherwise -> + -- should never occur pre-chainweb 2.24: + -- would mean coin.fund-tx is not a pact + fatal "buyGas: Internal error - empty continuation before 2.24 fork" + Just pe + | isChainweb224Pact -> + fatal "buyGas: Internal error - continuation found after 2.24 fork" + | otherwise -> + void $! txGasId .= (Just $! GasId (_pePactId pe)) findPayer :: TxContext @@ -1502,19 +1082,13 @@ enrichedMsgBody cmd = case (_pPayload $ _cmdPayload cmd) of redeemGas :: (Logger logger) => TxContext -> Command (Payload PublicMeta ParsedCode) -> Miner -> TransactionM logger p [PactEvent] redeemGas txCtx cmd (Miner mid mks) = do mcache <- use txCache - cmcache <- use txCoreCache let sender = view (cmdPayload . pMeta . pmSender) cmd fee <- gasSupplyOf <$> use txGasUsed <*> view txGasPrice -- if we're past chainweb 2.24, we don't use defpacts for gas - usePact5 <- view txusePact5 - - let - coreState = setCoreModuleCache cmcache $ initCoreCapabilities [core_magic_GAS] - if guardCtx chainweb224Pact txCtx then do total <- gasSupplyOf <$> view txGasLimit <*> view txGasPrice - let (redeemGasTerm, redeemGasCmd@(ExecMsg _ execData)) = + let (redeemGasTerm, redeemGasCmd) = mkRedeemGasTerm mid mks sender total fee -- I don't recall why exactly, but we set up an interpreter -- that ignores its argument and instead executes a term @@ -1525,39 +1099,13 @@ redeemGas txCtx cmd (Miner mid mks) = do fmap List.singleton (eval redeemGasTerm) (Hash chash) = toUntypedHash (_cmdHash cmd) rgHash = Hash (chash <> "-redeemgas") - locally txQuirkGasFee (const Nothing) $ - if usePact5 then do - evalEnv <- mkCoreEvalEnv managedNamespacePolicy (MsgData execData Nothing rgHash (_pSigners $ _cmdPayload cmd) []) - - er <- liftIO $ PCore.evalTermExec evalEnv coreState $ mkRedeemGasCoreTerm mid sender - case er of - Right er' -> do - let - convertPactValue pv = J.decodeStrict $ PCore.encodeStable pv - toModuleName m = - ModuleName - { _mnName = PCore._mnName m - , _mnNamespace = coerce <$> PCore._mnNamespace m - } - toPactEvent e = - PactEvent - { _eventName = PCore._peName e - , _eventParams = catMaybes $ convertPactValue <$> PCore._peArgs e - , _eventModule = toModuleName $ PCore._peModule e - , _eventModuleHash = coerce $ PCore._peModuleHash e - } - txCoreCache .= (CoreModuleCache $ PCore._erLoadedModules er') - return $ map toPactEvent $ PCore._erEvents er' - - Left err -> do - TRACE.traceM $ "CORE.redeemGas failed!!" <> sshow err - fatal $ "redeemGas: Internal error - " <> sshow err - else _erEvents <$> - applyExec' 0 interp redeemGasCmd - (_pSigners $ _cmdPayload cmd) - [] - rgHash - managedNamespacePolicy + + locally txQuirkGasFee (const Nothing) $ _erEvents <$> + applyExec' 0 interp redeemGasCmd + (_pSigners $ _cmdPayload cmd) + [] + rgHash + managedNamespacePolicy else do GasId gid <- use txGasId >>= \case Nothing -> fatal $! "redeemGas: no gas id in scope for gas refunds" @@ -1565,15 +1113,10 @@ redeemGas txCtx cmd (Miner mid mks) = do let redeemGasCmd = ContMsg gid 1 False (toLegacyJson $ object [ "fee" A..= toJsonViaEncode fee ]) Nothing - locally txQuirkGasFee (const Nothing) $ - if usePact5 then do - r <- applyContinuationTng 0 coreState redeemGasCmd - (_pSigners $ _cmdPayload cmd) (toUntypedHash $ _cmdHash cmd) - managedNamespacePolicy - return [] - else fmap _crEvents $ applyContinuation 0 (initState mcache) redeemGasCmd - (_pSigners $ _cmdPayload cmd) (toUntypedHash $ _cmdHash cmd) - managedNamespacePolicy + fmap _crEvents $ locally txQuirkGasFee (const Nothing) $ + applyContinuation 0 (initState mcache) redeemGasCmd + (_pSigners $ _cmdPayload cmd) (toUntypedHash $ _cmdHash cmd) + managedNamespacePolicy where initState mc = initStateInterpreter @@ -1592,10 +1135,6 @@ initCapabilities :: [CapSlot SigCapability] -> EvalState initCapabilities cs = set (evalCapabilities . capStack) cs def {-# INLINABLE initCapabilities #-} -initCoreCapabilities :: [PCore.CapSlot PCore.QualifiedName PCore.PactValue] -> PCore.EvalState PCore.CoreBuiltin PCore.SpanInfo -initCoreCapabilities cs = set (PCore.esCaps . PCore.csSlots) cs def -{-# INLINABLE initCoreCapabilities #-} - initStateInterpreter :: EvalState -> Interpreter e initStateInterpreter s = Interpreter (put s >>) @@ -1606,9 +1145,9 @@ checkTooBigTx :: (Logger logger) => Gas -> GasLimit - -> TransactionM logger p (Either (CommandResult [TxLogJson]) PCore.CommandResult) - -> ((CommandResult [TxLogJson]) -> TransactionM logger p ((CommandResult [TxLogJson]))) - -> TransactionM logger p (Either (CommandResult [TxLogJson]) PCore.CommandResult) + -> TransactionM logger p (CommandResult [TxLogJson]) + -> (CommandResult [TxLogJson] -> TransactionM logger p (CommandResult [TxLogJson])) + -> TransactionM logger p (CommandResult [TxLogJson]) checkTooBigTx initialGas gasLimit next onFail | initialGas >= fromIntegral gasLimit = do @@ -1616,9 +1155,8 @@ checkTooBigTx initialGas gasLimit next onFail $ "Tx too big (" <> pretty initialGas <> "), limit " <> pretty gasLimit - Left <$> do - r <- failTxWith pe "Tx too big" - onFail r + r <- failTxWith pe "Tx too big" + onFail r | otherwise = next gasInterpreter :: Gas -> TransactionM logger db (Interpreter p) @@ -1657,7 +1195,7 @@ txSizeAccelerationFee costPerByte = total power :: Integer = 7 {-# INLINE txSizeAccelerationFee #-} --- | Set the module cache of a pact 'coreState +-- | Set the module cache of a pact 'EvalState' -- setModuleCache :: ModuleCache @@ -1670,17 +1208,6 @@ setModuleCache mcache es = c = moduleCacheToHashMap mcache {-# INLINE setModuleCache #-} -setCoreModuleCache - :: CoreModuleCache - -> PCore.EvalState PCore.CoreBuiltin PCore.SpanInfo - -> PCore.EvalState PCore.CoreBuiltin PCore.SpanInfo -setCoreModuleCache mcache es = - let allDeps = foldMap PCore.allModuleExports $ _getCoreModuleCache mcache - in set (PCore.esLoaded . PCore.loAllLoaded) allDeps $ set (PCore.esLoaded . PCore.loModules) c es - where - c = _getCoreModuleCache mcache -{-# INLINE setCoreModuleCache #-} - -- | Set tx result state -- setTxResultState :: EvalResult -> TransactionM logger db () @@ -1701,12 +1228,13 @@ mkEvalEnv nsp msg = do genv <- GasEnv <$> view (txGasLimit . to (MilliGasLimit . gasToMilliGas)) <*> view txGasPrice - <*> use txGasModel + <*> (either id (error "mkEvalEnv: pact5 impossible") <$> use txGasModel) fmap (set eeSigCapBypass txCapBypass) - $ liftIO $ setupEvalEnv (_txDbEnv tenv) Nothing (_txMode tenv) - msg (versionedNativesRefStore (_txExecutionConfig tenv)) genv - nsp (_txSpvSupport tenv) (_txPublicData tenv) (_txExecutionConfig tenv) + $ liftIO $ setupEnv tenv genv where + setupEnv tenv genv = either (\db -> setupEvalEnv db Nothing (_txMode tenv) + msg (versionedNativesRefStore (_txExecutionConfig tenv)) genv + nsp (_txSpvSupport tenv) (_txPublicData tenv) (_txExecutionConfig tenv)) (error "mkEvalEnv: pact5 impossible") (_txDbEnv tenv) txCapBypass = M.fromList [ (wizaDebit, (wizaBypass, wizaMH)) @@ -1769,106 +1297,6 @@ unsafeModuleHashFromB64Text :: Text -> ModuleHash unsafeModuleHashFromB64Text = either error ModuleHash . PU.fromText' -mkCoreEvalEnv - :: NamespacePolicy - -> MsgData - -> TransactionM logger db (PCore.EvalEnv PCore.CoreBuiltin PCore.SpanInfo) -mkCoreEvalEnv nsp MsgData{..} = do - tenv <- ask - - -- TODO: create a module to convert old pactvalues to new ones in chainweb - let - convertPactValue pv = aeson (\s -> error $ "mkCoreEvalEnv: failed to parse legacyValue " ++ s) id $ A.fromJSON $ _getLegacyValue pv - convertQualName QualifiedName{..} = PCore.QualifiedName - { PCore._qnName = _qnName - , PCore._qnModName = _qnQual & \ModuleName{..} -> - PCore.ModuleName - { PCore._mnName = _mnName - , PCore._mnNamespace = fmap coerce _mnNamespace - } - } - convertCapability SigCapability{..} = - PCore.CapToken (convertQualName _scName) (mapMaybe (either (const Nothing) Just . PactConversion.fromLegacyPactValue) _scArgs) - - convertVerifier Verifier{..} = PCore.Verifier - { PCore._verifierName = coerce _verifierName - , PCore._verifierProof = _verifierProof - , PCore._verifierCaps = map convertCapability _verifierCaps - } - - let - txMode' = case _txMode tenv of - Transactional -> PCore.Transactional - Local -> PCore.Local - - let - coreMsg = PCore.MsgData - { PCore.mdData = either (const $ PCore.PObject mempty) id $ PactConversion.fromLegacyPactValue $ convertPactValue mdData - , PCore.mdStep = mdStep <&> \PactStep{..} -> - PCore.DefPactStep - { PCore._psStep = _psStep - , PCore._psRollback = _psRollback - , PCore._psDefPactId = coerce _psPactId - , PCore._psResume = _psResume <&> \Yield{..} -> - PCore.Yield - { PCore._yData = M.fromList $ mapMaybe (\(k, v) -> fmap (coerce k,) $ either (const Nothing) Just $ PactConversion.fromLegacyPactValue v) $ M.toList $ _objectMap _yData - , PCore._yProvenance = _yProvenance <&> \Provenance{..} -> - PCore.Provenance - { PCore._pTargetChainId = coerce _pTargetChainId - , PCore._pModuleHash = let (ModuleHash h) = _pModuleHash in PCore.ModuleHash $ coerce h - } - , PCore._ySourceChain = coerce _ySourceChain - } - } - , PCore.mdHash = coerce $ mdHash - , PCore.mdSigners = mdSigners <&> \Signer{..} -> - PCore.Signer - { PCore._siScheme = _siScheme <&> \case - ED25519 -> PCore.ED25519 - WebAuthn -> PCore.WebAuthn - , PCore._siPubKey = _siPubKey - , PCore._siAddress = _siAddress - , PCore._siCapList = map convertCapability _siCapList - } - , PCore.mdVerifiers = map convertVerifier mdVerifiers - } - - let - coreNsp = case nsp of - SimpleNamespacePolicy _ -> PCore.SimpleNamespacePolicy - SmartNamespacePolicy rootUsage name -> PCore.SmartNamespacePolicy rootUsage (convertQualName name) - - let - pd = _txPublicData tenv - convertPublicMeta pm = PCore.PublicMeta - { PCore._pmChainId = coerce $ _pmChainId pm - , PCore._pmSender = _pmSender pm - , PCore._pmGasLimit = - let (GasLimit (ParsedInteger g)) = _pmGasLimit pm in PCore.Gas $ fromIntegral g - , PCore._pmGasPrice = coerce $ _pmGasPrice pm - , PCore._pmTTL = - let (TTLSeconds (ParsedInteger s)) = _pmTTL pm in PCore.TTLSeconds s - , PCore._pmCreationTime = coerce $ _pmCreationTime pm - } - cpd = PCore.PublicData - { PCore._pdPublicMeta = convertPublicMeta $ _pdPublicMeta pd - , PCore._pdBlockHeight = _pdBlockHeight pd - , PCore._pdBlockTime = _pdBlockTime pd - , PCore._pdPrevBlockHash = _pdPrevBlockHash pd - } - - gasModel <- use txGasModelCore - let - toCoreExFlag = \case - FlagDisableModuleInstall -> Just PCore.FlagDisableModuleInstall - FlagDisableHistoryInTransactionalMode -> Just PCore.FlagDisableHistoryInTransactionalMode - FlagAllowReadInLocal -> Just PCore.FlagAllowReadInLocal - FlagDisablePactEvents -> Just PCore.FlagDisablePactEvents - FlagEnforceKeyFormats -> Just PCore.FlagEnforceKeyFormats - _ -> Nothing - executionFlags = mapMaybe toCoreExFlag $ S.toList $ _ecFlags $ _txExecutionConfig tenv - liftIO $ PCore.setupEvalEnv (_txCoreDb tenv) txMode' coreMsg gasModel coreNsp PCore.noSPVSupport cpd (S.fromList executionFlags) - -- | Managed namespace policy CAF -- managedNamespacePolicy :: NamespacePolicy @@ -1889,14 +1317,6 @@ mkCoinCap c as = SigCapability fqn as fqn = QualifiedName mn c def {-# INLINE mkCoinCap #-} -mkMagicCoreCapSlot :: Text -> PCore.CapSlot PCore.QualifiedName PCore.PactValue -mkMagicCoreCapSlot c = PCore.CapSlot cap [] - where - mn = PCore.ModuleName "coin" Nothing - fqn = PCore.QualifiedName c mn - cap = PCore.CapToken fqn [] -{-# INLINE mkMagicCoreCapSlot #-} - -- | Build the 'ExecMsg' for some pact code fed to the function. The 'value' -- parameter is for any possible environmental data that needs to go into -- the 'ExecMsg'. @@ -1973,4 +1393,4 @@ logError :: (Logger logger) => Text -> TransactionM logger db () logError msg = view txLogger >>= \l -> logError_ l msg infoLog :: (Logger logger) => Text -> TransactionM logger db () -infoLog msg = view txLogger >>= \l -> logInfo_ l msg +infoLog msg = view txLogger >>= \l -> logInfo_ l msg \ No newline at end of file diff --git a/src/Chainweb/Pact/TransactionExec/Pact5.hs b/src/Chainweb/Pact/TransactionExec/Pact5.hs new file mode 100644 index 000000000..de2fbd3e3 --- /dev/null +++ b/src/Chainweb/Pact/TransactionExec/Pact5.hs @@ -0,0 +1,1105 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MultiWayIf #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TupleSections #-} +-- | +-- Module : Chainweb.Pact.TransactionExec +-- Copyright : Copyright © 2018 Kadena LLC. +-- License : (see the file LICENSE) +-- Maintainer : Mark Nichols , Emily Pillmore +-- Stability : experimental +-- +-- Pact command execution and coin-contract transaction logic for Chainweb +-- +module Chainweb.Pact.TransactionExec.Pact5 +( -- * Transaction Execution + applyCmd +, applyLocal +, applyExec +, applyExec' +, applyExec +, applyExec' +, applyContinuation +, applyContinuation' +, applyContinuation +, applyContinuation' +, runPayload + + -- * Gas Execution +, buyGas + + -- * Coinbase Execution +, applyCoinbase +, EnforceCoinbaseFailure(..) + + -- * Command Helpers +, publicMetaOf +, networkIdOf +, gasSupplyOf + + -- * Utilities +, buildExecRawCode +, mkMagicCapSlot +, initialGasOf + +) where + +import Control.DeepSeq +import Control.Lens +import Control.Monad +import Control.Monad.Catch +import Control.Monad.Reader +import Control.Monad.State.Strict +import Control.Monad.Trans.Maybe +import Control.Parallel.Strategies(using, rseq) + +import Data.Aeson hiding ((.=)) +import qualified Data.Aeson as A +import qualified Data.Aeson.Types as A +import Data.Bifunctor +import qualified Data.ByteString as B +import qualified Data.ByteString.Short as SB +import Data.Coerce (coerce) +import Data.Decimal (Decimal, roundTo) +import Data.Default (def) +import Data.Foldable (fold, for_) +import Data.IORef +import qualified Data.Map.Strict as Map +import qualified Data.HashMap.Strict as HM +import qualified Data.List as List +import qualified Data.Map.Strict as M +import Data.Maybe +import qualified Data.Set as S +import Data.Text (Text) +import qualified Data.Text as T +import qualified System.LogLevel as L + +-- internal Pact modules + +import Pact.Core.Serialise.LegacyPact () +import Pact.Core.Compile +import Pact.Core.Evaluate +import Pact.Core.Command +import Pact.Core.Capabilities +import Pact.Core.Errors +import Pact.Core.Names +import Pact.Core.Namespace +import Pact.Core.Persistence +import Pact.Core.Pretty +import Pact.Core.Gas +import Pact.Core.Hash +import Pact.Core.PactValue +import Pact.Core.Environment +import Pact.Core.Builtin +import Pact.Core.Syntax.ParseTree +import Pact.Core.DefPacts.Types +import Pact.Core.Scheme +import Pact.Core.StableEncoding +import Pact.Core.SPV +import Pact.Core.Verifiers +import Pact.Core.Info + +import qualified Pact.Parse as Pact4 +import qualified Pact.Types.Command as Pact4 +import qualified Pact.Types.RPC as Pact4 +import qualified Pact.Types.Persistence as Pact4 +import qualified Pact.Types.ChainId as Pact4 +import qualified Pact.Types.Hash as Pact4 +import qualified Pact.Types.SPV as Pact4 + +-- internal Chainweb modules +import qualified Chainweb.Pact.Transactions.CoinCoreV4Transactions as CoinCoreV4 +import qualified Chainweb.Pact.Templates.Pact4 as Pact4 + +import Chainweb.BlockHeader +import Chainweb.BlockHeight +import Chainweb.Logger +import qualified Chainweb.ChainId as Chainweb +import Chainweb.Mempool.Mempool (requestKeyToTransactionHash) +import Chainweb.Miner.Pact +import Chainweb.Pact.Service.Types +import Chainweb.Pact.Templates.Pact5 +import Chainweb.Pact.Utils +import qualified Chainweb.Pact.Conversion as PactConversion +import Chainweb.Pact.Types hiding (logError) +import Chainweb.Pact.Backend.Types +import Chainweb.Transaction +import Chainweb.VerifierPlugin +import Chainweb.Utils (encodeToByteString, sshow, tryAllSynchronous, T2(..), T4(..)) +import Chainweb.Version as V +import Chainweb.Version.Guards as V +import Chainweb.Version.Utils as V +import Pact.JSON.Encode (toJsonViaEncode) + +-- Note [Throw out verifier proofs eagerly] +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- We try to discard verifier proofs eagerly so that we don't hang onto them in +-- the liveset. This implies that we also try to discard `Command`s for the same +-- reason, because they contain the verifier proofs and other data we probably +-- don't need. + +-- -------------------------------------------------------------------------- -- + +-- | "Magic" capability 'COINBASE' used in the coin contract to +-- constrain coinbase calls. +-- +magic_COINBASE :: CapSlot QualifiedName PactValue +magic_COINBASE = mkMagicCapSlot "COINBASE" + +-- | "Magic" capability 'GAS' used in the coin contract to +-- constrain gas buy/redeem calls. +-- +magic_GAS :: CapSlot QualifiedName PactValue +magic_GAS = mkMagicCapSlot "GAS" + + +onChainErrorPrintingFor :: TxContext -> UnexpectedErrorPrinting +onChainErrorPrintingFor txCtx = + if guardCtx chainweb219Pact txCtx + then CensorsUnexpectedError + else PrintsUnexpectedError + +-- | The main entry point to executing transactions. From here, +-- 'applyCmd' assembles the command environment for a command and +-- orchestrates gas buys/redemption, and executing payloads. +-- +applyCmd + :: (Logger logger) + => ChainwebVersion + -> logger + -- ^ Pact logger + -> Maybe logger + -- ^ Pact gas logger + -> CoreDb + -- ^ Pact db environment + -> Miner + -- ^ The miner chosen to mine the block + -> GasModel CoreBuiltin + -- ^ Gas model (pact Service config) + -> TxContext + -- ^ tx metadata and parent header + -> SPVSupport + -- ^ SPV support (validates cont proofs) + -> Command (Payload PublicMeta RawCode) + -- ^ command with payload to execute + -> Gas + -- ^ initial gas used + -> ApplyCmdExecutionContext + -- ^ is this a local or send execution context? + -> IO CommandResult +applyCmd v logger gasLogger coreDb miner gasModel txCtx spv cmd initialGas callCtx = do + T2 cr st <- runTransactionM cenv txst applyBuyGas + + pure cr + where + stGasModelCore + | chainweb217Pact' = gasModel + | otherwise = freeGasModel + txst = TransactionState mempty mempty 0 Nothing (Right stGasModelCore) mempty + quirkGasFee = v ^? versionQuirks . quirkGasFees . ix requestKey + + cenv = TransactionEnv (Pact4.Transactional) (Right coreDb) logger gasLogger (ctxToPublicData txCtx) (undefined spv) nid gasPrice + requestKey (fromIntegral gasLimit) def quirkGasFee + + !requestKey = Pact4.RequestKey $ Pact4.Hash $ unHash $ unRequestKey $ cmdToRequestKey cmd + !gasPrice = undefined -- view cmdGasPrice cmd + !gasLimit = undefined -- view cmdGasLimit cmd + !nid = undefined -- networkIdOf cmd + currHeight = ctxCurrentBlockHeight txCtx + cid = ctxChainId txCtx + isModuleNameFix = enableModuleNameFix v cid currHeight + isModuleNameFix2 = enableModuleNameFix2 v cid currHeight + isPactBackCompatV16 = pactBackCompat_v16 v cid currHeight + chainweb213Pact' = guardCtx chainweb213Pact txCtx + chainweb217Pact' = guardCtx chainweb217Pact txCtx + chainweb219Pact' = guardCtx chainweb219Pact txCtx + chainweb223Pact' = guardCtx chainweb223Pact txCtx + allVerifiers = verifiersAt v cid currHeight + + redeemAllGas r = do + txGasUsed .= fromIntegral gasLimit + applyRedeem r + + applyBuyGas = + buyGas txCtx cmd miner >>= \case + Left e -> undefined + -- view txRequestKey >>= \rk -> + -- throwM $ BuyGasFailure $ GasPurchaseFailure (requestKeyToTransactionHash rk) e + Right _ -> checkTooBigTx initialGas gasLimit applyVerifiers redeemAllGas + + displayPactError e = do + r <- failTxWith e "tx failure for request key when running cmd" + redeemAllGas r + + applyVerifiers = do + if chainweb223Pact' + then do + let gasUsed = undefined -- use txGasUsed + let initGasRemaining = fromIntegral gasLimit - gasUsed + verifierResult <- liftIO $ runVerifierPlugins (ctxVersion txCtx, cid, currHeight) logger allVerifiers initGasRemaining undefined + case verifierResult of + Left err -> do + let errMsg = "Tx verifier error: " <> getVerifierError err + -- cmdResult <- -- failTxWith + -- undefined -- (PEExecutionError TxFailure def [] (pretty errMsg)) + -- errMsg + redeemAllGas undefined + Right verifierGasRemaining -> do + txGasUsed += initGasRemaining - verifierGasRemaining + applyPayload + else applyPayload + + applyPayload = do + txGasModel .= (Right gasModel) + txGasUsed .= undefined -- initialGas + + -- cr <- runPayload cmd managedNamespacePolicy + return undefined + + applyRedeem cr = undefined + -- applyRedeem cr = do + -- txGasModel .= _geGasModel freeGasEnv + -- txGasModelCore .= freeGasModel + + -- r <- catchesPactError logger (onChainErrorPrintingFor txCtx) $! redeemGas txCtx cmd miner + -- case r of + -- Left e -> + -- -- redeem gas failure is fatal (block-failing) so miner doesn't lose coins + -- fatal $ "tx failure for request key while redeeming gas: " <> sshow e + -- Right es -> do + -- logs <- use txLogs + + -- -- /local requires enriched results with metadata, while /send strips them. + -- -- when ?preflight=true is set, make sure that metadata occurs in result. + + -- let !cr' = case callCtx of + -- ApplySend -> set crLogs (Just logs) $ over crEvents (es ++) cr + -- ApplyLocal -> set crMetaData (Just $ J.toJsonViaEncode $ ctxToPublicData' txCtx) + -- $ set crLogs (Just logs) + -- $ over crEvents (es ++) cr + + -- return $ cr' + +applyCoinbase + :: (Logger logger) + => ChainwebVersion + -> logger + -- ^ Pact logger + -> CoreDb + -- ^ Pact db environment + -> Miner + -- ^ The miner chosen to mine the block + -> Pact4.ParsedDecimal + -- ^ Miner reward + -> TxContext + -- ^ tx metadata and parent header + -> EnforceCoinbaseFailure + -- ^ enforce coinbase failure or not + -> CoinbaseUsePrecompiled + -- ^ always enable precompilation + -> IO CommandResult +applyCoinbase v logger coreDb (Miner mid mks@(MinerKeys mk)) reward@(Pact4.ParsedDecimal d) txCtx + (EnforceCoinbaseFailure enfCBFailure) (CoinbaseUsePrecompiled enablePC) + | enablePC = do + let state = initCapabilities [magic_COINBASE] + (coinbaseTerm, cexec) = mkCoinbaseTerm mid mks (GasSupply reward) + go state cexec coinbaseTerm + | otherwise = do + cexec <- Pact4.mkCoinbaseCmd mid mks reward + let state = initCapabilities [magic_COINBASE] + go state cexec undefined + where + tenv = TransactionEnv Pact4.Transactional (Right coreDb) logger Nothing (ctxToPublicData txCtx) Pact4.noSPVSupport + Nothing 0.0 rk 0 def Nothing + txst = TransactionState mempty mempty 0 Nothing (Right freeGasModel) mempty + rk = Pact4.RequestKey $ Pact4.Hash $ unHash chash + parent = _tcParentHeader txCtx + + bh = ctxCurrentBlockHeight txCtx + cid = Chainweb._chainId parent + chash = Hash $ SB.toShort $ encodeToByteString $ _blockHash $ _parentHeader parent + -- NOTE: it holds that @ _pdPrevBlockHash pd == encode _blockHash@ + -- NOTE: chash includes the /quoted/ text of the parent header. + + go evState cexec@(Pact4.ExecMsg _ execData) coinbaseTerm = evalTransactionM tenv txst $! do + evalEnv <- mkEvalEnv managedNamespacePolicy (MsgData (undefined execData) Nothing chash mempty []) + cr <- liftIO $ evalTermExec evalEnv evState coinbaseTerm + + case cr of + Right er -> do + debug + $! "successful coinbase of " + <> T.take 18 (sshow d) + <> " to " + <> sshow mid + + -- upgradedModuleCache <- applyUpgrades v cid bh + + return $! CommandResult $ PactResult $ Right $ PERExpr er + + Left e + | enfCBFailure -> throwM $ CoinbaseFailure $ sshow e + | otherwise -> undefined -- (`T2` Nothing) <$> (Left <$> failTxWith (PactError EvalError (Info Nothing) [] mempty) "coinbase tx failure") + + +applyLocal + :: (Logger logger) + => logger + -- ^ Pact logger + -> Maybe logger + -- ^ Pact gas logger + -> CoreDb + -- ^ Pact db environment + -> GasModel CoreBuiltin + -- ^ Gas model (pact Service config) + -> TxContext + -- ^ tx metadata and parent header + -> SPVSupport + -- ^ SPV support (validates cont proofs) + -> Command PayloadWithText + -- ^ command with payload to execute + -> ExecutionConfig + -> IO CommandResult +applyLocal logger gasLogger coreDb gasModel txCtx spv cmdIn execConfig = + evalTransactionM tenv txst go + where + !cmd = payloadObj <$> cmdIn `using` traverse rseq + !rk = Pact4.RequestKey $ Pact4.Hash $ unHash $ unRequestKey $ cmdToRequestKey cmd + !nid = undefined -- networkIdOf cmd + !chash = _cmdHash cmd + !signers = undefined -- _pSigners $ _cmdPayload cmd + !verifiers = [] -- fromMaybe [] $ _pVerifiers $ _cmdPayload cmd + !gasPrice = undefined -- view cmdGasPrice cmd + !gasLimit = undefined -- view cmdGasLimit cmd + tenv = TransactionEnv Pact4.Local (Right coreDb) logger gasLogger (ctxToPublicData txCtx) undefined nid gasPrice + rk (fromIntegral gasLimit) undefined Nothing + txst = TransactionState mempty mempty 0 Nothing (Right gasModel) mempty + gas0 = initialGasOf (_cmdPayload cmdIn) + currHeight = ctxCurrentBlockHeight txCtx + cid = V._chainId txCtx + v = _chainwebVersion txCtx + allVerifiers = verifiersAt v cid currHeight + usePact5 = pact5 (ctxVersion txCtx) (ctxChainId txCtx) currHeight + -- Note [Throw out verifier proofs eagerly] + !verifiersWithNoProof = undefined + -- (fmap . fmap) (\_ -> ()) verifiers + -- `using` (traverse . traverse) rseq + + applyVerifiers m = do + let initGasRemaining = undefined -- fromIntegral gasLimit - gas0 + verifierResult <- liftIO $ runVerifierPlugins (v, cid, currHeight) logger allVerifiers (undefined initGasRemaining) (undefined cmd) + case verifierResult of + Left err -> do + let errMsg = "Tx verifier error: " <> getVerifierError err + undefined errMsg + -- failTxWith + -- (PactError TxFailure def [] (pretty errMsg)) + -- errMsg + Right verifierGasRemaining -> do + let gas1 = undefined -- (initGasRemaining - (undefined verifierGasRemaining)) + gas0 + applyPayload gas1 m + + applyPayload gas1 m = do + let coreState = def + cr <- case m of + Pact4.Exec em -> applyExec gas1 coreState em signers chash managedNamespacePolicy + Pact4.Continuation cm -> applyContinuation gas1 coreState undefined signers chash managedNamespacePolicy + + case _pactResult $ _crResult cr of + Left e -> do + failTx5With e "applyLocal" + pure cr + Right _ -> pure cr + + go = checkTooBigTx gas0 gasLimit (applyVerifiers undefined) return -- $ _pPayload $ _cmdPayload cmd) return + +-- -- | Apply (forking) upgrade transactions and module cache updates +-- -- at a particular blockheight. +-- -- +-- -- This is the place where we consistently /introduce/ new transactions +-- -- into the blockchain along with module cache updates. The only other +-- -- places are Pact Service startup and the +-- -- empty-module-cache-after-initial-rewind case caught in 'execTransactions' +-- -- which both hit the database. +-- -- +-- applyUpgrades +-- :: (Logger logger) +-- => ChainwebVersion +-- -> Chainweb.ChainId +-- -> BlockHeight +-- -> TransactionM logger p (Maybe CoreModuleCache) +-- applyUpgrades v cid height +-- | Just upg <- +-- v ^? versionUpgrades . onChain cid . at height . _Just = applyUpgrade upg +-- | cleanModuleCache v cid height = filterModuleCache +-- | otherwise = return Nothing +-- where +-- coinModuleName = ModuleName "coin" Nothing +-- coinCoreModuleName = ModuleName "coin" Nothing +-- installCoinModuleAdmin = set (evalCapabilities . capModuleAdmin) $ S.singleton coinModuleName +-- -- installCoreCoinModuleAdmin = set (esCaps . csModuleAdmin) $ S.singleton coinCoreModuleName + +-- filterModuleCache = do +-- mc <- use txCache +-- cmc <- use txCoreCache +-- pure $ Just $ +-- ( filterModuleCacheByKey (== coinModuleName) mc +-- , filterCoreModuleCacheByKey (== coinCoreModuleName) cmc +-- ) + +-- applyUpgrade upg = do +-- infoLog "Applying upgrade!" +-- let payloads = map (fmap payloadObj) $ _upgradeTransactions upg + +-- -- +-- -- In order to prime the module cache with all new modules for subsequent +-- -- blocks, the caches from each tx are collected and the union of all +-- -- those caches is returned. The calling code adds this new cache to the +-- -- init cache in the pact service state (_psInitCache). +-- -- + +-- let flags = flagsFor v cid (if _legacyUpgradeIsPrecocious upg then height + 1 else height) +-- caches <- local +-- (txExecutionConfig .~ ExecutionConfig flags) +-- (mapM applyTx payloads) +-- return $ Just $ bimap mconcat mconcat $ unzip $ reverse caches + +-- interp = initStateInterpreter +-- $ installCoinModuleAdmin +-- $ initCapabilities [mkMagicCapSlot "REMEDIATE"] +-- -- coreInitState = installCoreCoinModuleAdmin $ initCapabilities [mkMagicCapSlot "REMEDIATE"] + +-- applyTx tx = do +-- infoLog $ "Running upgrade tx " <> sshow (_cmdHash tx) +-- tryAllSynchronous (runGenesis tx permissiveNamespacePolicy interp) >>= \case +-- Right _ -> do +-- c <- use txCache +-- cc <- use txCoreCache +-- pure (c, cc) +-- Left e -> do +-- logError $ "Upgrade transaction failed! " <> sshow e +-- throwM e + +failTxWith + :: (Logger logger) + => PactError SpanInfo + -> Text + -> TransactionM logger p CommandResult +failTxWith err msg = do + logs <- use txLogs + gas <- view txGasLimit -- error means all gas was charged + rk <- view txRequestKey + l <- view txLogger + + -- liftIO $ logFunction l L.Info + -- (Pact4TxFailureLog rk err msg) + undefined + -- return $! CommandResult rk Nothing (PactResult (Left err)) + -- gas (Just logs) Nothing Nothing [] + +failTx5With + :: (Logger logger) + => PactError SpanInfo + -> Text + -> TransactionM logger p () +failTx5With err msg = do + logs <- use txLogs + gas <- view txGasLimit -- error means all gas was charged + rk <- view txRequestKey + l <- view txLogger + + liftIO $ logFunction l L.Info + (Pact5TxFailureLog rk err msg) + +runPayload + :: (Logger logger) + => Command (Payload PublicMeta RawCode) + -> NamespacePolicy + -> TransactionM logger p CommandResult +runPayload cmd nsp = do + g0 <- use txGasUsed + let coreState = def + + -- Note [Throw out verifier proofs eagerly] + let !verifiersWithNoProof = undefined + -- (fmap . fmap) (\_ -> ()) verifiers + -- `using` (traverse . traverse) rseq + + case payload of + Pact4.Exec pm -> applyExec (undefined g0) coreState pm signers chash nsp + Pact4.Continuation ym -> applyContinuation (undefined g0) coreState (undefined ym) signers chash nsp + + where + verifiers = undefined -- fromMaybe [] $ _pVerifiers $ _cmdPayload cmd + signers = undefined -- _pSigners $ _cmdPayload cmd + chash = undefined -- toUntypedHash $ _cmdHash cmd + payload = undefined -- _pPayload $ _cmdPayload cmd + +applyExec + :: (Logger logger) + => Gas + -> EvalState CoreBuiltin SpanInfo + -> Pact4.ExecMsg RawCode + -> [Signer QualifiedName PactValue] + -> Hash + -> NamespacePolicy + -> TransactionM logger p CommandResult +applyExec initialGas coreState em senderSigs hsh nsp = do + er <- applyExec' initialGas coreState em senderSigs hsh nsp + + -- return er + pure $ CommandResult $ PactResult $ PERTopLevel <$> er + -- either id mkCommandResultFromCoreResult er + +applyExec' + :: (Logger logger) + => Gas + -> EvalState CoreBuiltin SpanInfo + -> Pact4.ExecMsg RawCode + -> [Signer QualifiedName PactValue] + -> Hash + -> NamespacePolicy + -> TransactionM logger p (Either (PactError SpanInfo) (EvalResult [TopLevel SpanInfo])) +applyExec' (Gas initialGas) coreState (Pact4.ExecMsg rawCode execData) senderSigs hsh nsp = do + evalEnv <- mkEvalEnv nsp (MsgData (undefined execData) Nothing hsh senderSigs []) + + setEnvGas (Gas $ fromIntegral initialGas) evalEnv + + er <- liftIO $! evalExec evalEnv coreState rawCode + case er of + Right er' -> do + -- liftIO $ print ("_erOutput", _erOutput er') + + -- if we specified this transaction's gas fee manually as a "quirk", + -- here we set the result's gas fee to agree with that + quirkGasFee <- view txQuirkGasFee + let quirkedEvalResult = undefined + -- case quirkGasFee of + -- Nothing -> er' + -- Just (Gas fee) -> er' { _erGas = Gas $ fromIntegral fee } + + return $ Right quirkedEvalResult + Left err -> do + -- TODO: return either an error instead of throwing an exception here + fatal $ "Pact Tng execution failed: " <> (T.pack $ show $ pretty err) + return $ Left err + +-- | Execute a 'ContMsg' and return the command result and module cache +-- +applyContinuation + :: (Logger logger) + => Gas + -> EvalState CoreBuiltin SpanInfo + -> ContMsg + -> [Signer QualifiedName PactValue] + -> Hash + -> NamespacePolicy + -> TransactionM logger p CommandResult -- (Either (PactError SpanInfo) (EvalResult [TopLevel SpanInfo])) +applyContinuation initialGas coreState cm senderSigs hsh nsp = do + er <- applyContinuation' initialGas coreState cm senderSigs hsh nsp + -- return er + -- either id mkCommandResultFromCoreResult + pure $ CommandResult $ PactResult $ PERTopLevel <$> er + + -- for_ _erLogGas $ \gl -> gasLog $ "gas logs: " <> sshow gl + + -- TODO: set tx warnings to eval warnings + -- txWarnings <>= _erWarnings + +setEnvGas :: Gas -> EvalEnv CoreBuiltin SpanInfo -> TransactionM logger p () +setEnvGas initialGas = liftIO . views eeGasRef (`writeIORef` gasToMilliGas initialGas) + +-- | Execute a 'ContMsg' and return just eval result, not wrapped in a +-- 'CommandResult' wrapper +-- +applyContinuation' + :: (Logger logger) + => Gas + -> EvalState CoreBuiltin SpanInfo + -> ContMsg + -> [Signer QualifiedName PactValue] + -> Hash + -> NamespacePolicy + -> TransactionM logger p (Either (PactError SpanInfo) (EvalResult [TopLevel SpanInfo])) +applyContinuation' initialGas coreState (ContMsg pid s rb d proof) senderSigs hsh nsp = do + + evalEnv <- mkEvalEnv nsp (MsgData d pactStep hsh senderSigs []) + + setEnvGas (Gas $ fromIntegral $ undefined initialGas) evalEnv + + -- let + -- convertPactValue pv = PactConversion.fromLegacyPactValue $ + -- aeson (error "applyContinuation': failed to parseJSON pact value") id $ A.fromJSON $ _getLegacyValue pv + + -- coreCm = ContMsg + -- { _cmPactId = coerce pid + -- , _cmStep = s + -- , _cmRollback = rb + -- , _cmData = either (error "applyContinuation': failed to convert pact value") id $ convertPactValue d + -- , _cmProof = coerce proof + -- } + + er <- liftIO $! evalContinuation evalEnv coreState (undefined) + case er of + Right er' -> do + -- if we specified this transaction's gas fee manually as a "quirk", + -- here we set the result's gas fee to agree with that + quirkGasFee <- view txQuirkGasFee + let quirkedEvalResult = undefined + -- case quirkGasFee of + -- Nothing -> er' + -- Just (Gas fee) -> er' { _erGas = Gas $ fromIntegral fee } + + return $ Right $ quirkedEvalResult + err -> pure err + + where + pactStep = Just $ DefPactStep s rb pid Nothing + +-- | Build and execute 'coin.buygas' command from miner info and user command +-- info (see 'TransactionExec.applyCmd') +-- +-- see: 'pact/coin-contract/coin.pact#fund-tx' +-- +buyGas :: (Logger logger) => TxContext -> Command (Payload PublicMeta RawCode) -> Miner -> TransactionM logger p (Either (PactError SpanInfo) [PactEvent PactValue]) +buyGas txCtx cmd (Miner mid mks) = go + where + isChainweb224Pact = guardCtx chainweb224Pact txCtx + sender = undefined -- view (cmdPayload . pMeta . pmSender) cmd + + run input = undefined + -- (findPayer txCtx cmd) >>= \r -> case r of + -- Nothing -> input + -- Just withPayerCap -> withPayerCap input + + (Hash chash) = (_cmdHash cmd) + bgHash = Hash (chash <> "-buygas") + + go = do + supply <- undefined -- gasSupplyOf <$> view txGasLimit <*> view txGasPrice + logGas <- isJust <$> view txGasLogger + + let (buyGasTerm, buyGasCmd@(Pact4.ExecMsg _ execData)) = + -- post-chainweb 2.24, we call buy-gas directly rather than + -- going through fund-tx which is a defpact. + if isChainweb224Pact + then mkBuyGasTerm sender supply + else mkFundTxTerm mid mks sender supply + coreState = initCapabilities [magic_GAS] + + let + gasCapName = QualifiedName "GAS" (ModuleName "coin" Nothing) + signedForGas signer = + any (\sc -> _ctName sc == gasCapName) (_siCapList signer) + addDebit signer + | signedForGas signer = + signer & siCapList %~ (undefined) --debitCap sender:) + | otherwise = signer + addDebitToSigners = + fmap addDebit + signersWithDebit = addDebitToSigners $ undefined -- _pSigners $ _cmdPayload cmd + + -- no verifiers are allowed in buy gas + -- quirked gas is not used either + -- result <- + -- applyExec' 0 (interp mcache) buyGasCmd signersWithDebit [] bgHash managedNamespacePolicy + + evalEnv <- mkEvalEnv managedNamespacePolicy (MsgData (undefined execData) Nothing bgHash signersWithDebit []) + + er <- locally txQuirkGasFee (const Nothing) $ liftIO $ evalTermExec evalEnv coreState buyGasTerm + case er of + Right er' -> do + case _erExec er' of + Nothing + | isChainweb224Pact -> + return $ Right [] + | otherwise -> + -- should never occur pre-chainweb 2.24: + -- would mean coin.fund-tx is not a pact + fatal "buyGas: Internal error - empty continuation before 2.24 fork" + Just pe + | isChainweb224Pact -> + fatal "buyGas: Internal error - continuation found after 2.24 fork" + | otherwise -> do + void $! txGasId .= (Just $! GasId ( undefined $ _peDefPactId pe)) + pure $ Right [] + Left err -> do + fatal $ "buyGas: Internal error - " <> sshow err + +-- TODO: rewrite to core +-- findPayer +-- :: TxContext +-- -> Command (Payload PublicMeta RawCode) +-- -> Eval e (Maybe (Eval e [Term Name] -> Eval e [Term Name])) +-- findPayer txCtx cmd = runMaybeT $ do +-- (!m,!qn,!as) <- MaybeT findPayerCap +-- pMod <- MaybeT $ lookupModule qn m +-- capRef <- MaybeT $ return $ lookupIfaceModRef qn pMod +-- return $ runCap (getInfo qn) capRef as +-- where +-- setEnvMsgBody v e = set eeMsgBody v e + +-- findPayerCap :: Eval e (Maybe (ModuleName,QualifiedName,[PactValue])) +-- findPayerCap = preview $ eeMsgSigs . folded . folded . to sigPayerCap . _Just + +-- sigPayerCap (SigCapability q@(QualifiedName m n _) as) +-- | n == "GAS_PAYER" = Just (m,q,as) +-- sigPayerCap _ = Nothing + +-- gasPayerIface = ModuleName "gas-payer-v1" Nothing + +-- lookupIfaceModRef (QualifiedName _ n _) (ModuleData (MDModule Module{..}) refs _) +-- | gasPayerIface `elem` _mInterfaces = HM.lookup n refs +-- lookupIfaceModRef _ _ = Nothing + +-- mkApp i r as = App (TVar r i) (map (liftTerm . fromPactValue) as) i + +-- runCap i capRef as input = do +-- let msgBody = enrichedMsgBody cmd +-- enrichMsgBody | guardCtx pactBackCompat_v16 txCtx = id +-- | otherwise = setEnvMsgBody (toLegacyJson msgBody) +-- ar <- local enrichMsgBody $ do +-- (cap, capDef, args) <- appToCap $ mkApp i capRef as +-- evalCap i CapCallStack False (cap, capDef, args, i) + +-- case ar of +-- NewlyAcquired -> do +-- r <- input +-- popCapStack (const (return ())) +-- return r +-- _ -> evalError' i "Internal error, GAS_PAYER already acquired" + + +-- | Build and execute 'coin.redeem-gas' command from miner info and previous +-- command results (see 'TransactionExec.applyCmd') +-- +-- see: 'pact/coin-contract/coin.pact#fund-tx' +-- +redeemGas :: (Logger logger) => TxContext -> Command (Payload PublicMeta RawCode) -> Miner -> TransactionM logger p [PactEvent PactValue] +redeemGas txCtx cmd (Miner mid mks) = do + let sender = undefined -- cmdPayload . pMeta . pmSender) cmd + fee <- undefined -- gasSupplyOf <$> use txGasUsed <*> view txGasPrice + -- if we're past chainweb 2.24, we don't use defpacts for gas + + let + coreState = initCapabilities [magic_GAS] + + if guardCtx chainweb224Pact txCtx + then do + total <- undefined -- gasSupplyOf <$> view txGasLimit <*> view txGasPrice + let (redeemGasTerm, redeemGasCmd@(Pact4.ExecMsg _ execData)) = + mkRedeemGasTerm mid mks (undefined sender) total fee + -- I don't recall why exactly, but we set up an interpreter + -- that ignores its argument and instead executes a term + -- of our choice. we do the same to buy gas. + (Hash chash) = (_cmdHash cmd) + rgHash = Hash (chash <> "-redeemgas") + + locally txQuirkGasFee (const Nothing) $ do + evalEnv <- mkEvalEnv managedNamespacePolicy (MsgData (undefined execData) Nothing rgHash (undefined $ _cmdPayload cmd) []) + + er <- liftIO $ evalTermExec evalEnv coreState redeemGasTerm + case er of + Right er' -> return $ _erEvents er' + + Left err -> do + fatal $ "redeemGas: Internal error - " <> sshow err + else do + GasId gid <- use txGasId >>= \case + Nothing -> fatal $! "redeemGas: no gas id in scope for gas refunds" + Just g -> return g + let redeemGasCmd = + ContMsg (undefined gid) 1 False (undefined $ object [ "fee" A..= toJsonViaEncode fee ]) Nothing + + locally txQuirkGasFee (const Nothing) $ do + r <- applyContinuation (Gas 0) coreState redeemGasCmd + (undefined) -- _pSigners $ _cmdPayload cmd) + (_cmdHash cmd) + managedNamespacePolicy + return [] + +-- ---------------------------------------------------------------------------- -- +-- Utilities + +-- | Initialize a fresh eval state with magic capabilities. +-- This is the way we inject the correct guards into the environment +-- during Pact code execution +-- +initCapabilities :: [CapSlot QualifiedName PactValue] -> EvalState CoreBuiltin SpanInfo +initCapabilities cs = set (esCaps . csSlots) cs def +{-# INLINABLE initCapabilities #-} + +-- | Check whether the cost of running a tx is more than the allowed +-- gas limit and do some action depending on the outcome +-- +checkTooBigTx + :: (Logger logger) + => Gas + -> GasLimit + -> TransactionM logger p CommandResult + -> (CommandResult -> TransactionM logger p CommandResult) + -> TransactionM logger p CommandResult +checkTooBigTx initialGas gasLimit next onFail + | initialGas >= gasLimit = do + + let !pe = undefined + -- PactError GasError def [] + -- $ "Tx too big (" <> pretty initialGas <> "), limit " + -- <> pretty gasLimit + + r <- failTxWith pe "Tx too big" + onFail r + | otherwise = next + +-- | Initial gas charged for transaction size +-- ignoring the size of a continuation proof, if present +-- +initialGasOf :: PayloadWithText -> Gas +initialGasOf payload = gasFee + where + feePerByte :: Rational = 0.01 + + contProofSize = undefined + -- case _pPayload (payloadObj payload) of + -- Pact4.Continuation (ContMsg _ _ _ _ (Just (ContProof p))) -> B.length p + -- _ -> 0 + txSize = SB.length (payloadBytes payload) - contProofSize + + costPerByte = fromIntegral txSize * feePerByte + sizePenalty = txSizeAccelerationFee costPerByte + gasFee = undefined -- ceiling $ (costPerByte + sizePenalty) +{-# INLINE initialGasOf #-} + +txSizeAccelerationFee :: Rational -> Rational +txSizeAccelerationFee costPerByte = total + where + total = (costPerByte / bytePenalty) ^ power + bytePenalty = 512 + power :: Integer = 7 +{-# INLINE txSizeAccelerationFee #-} + +-- -- | Set tx result state +-- -- +-- setTxResultState :: EvalResult -> TransactionM logger db () +-- setTxResultState er = do +-- txLogs <>= _erLogs er +-- txGasUsed .= _erGas er +-- {-# INLINE setTxResultState #-} + +-- | Make an 'EvalEnv' given a tx env + state +-- +-- mkEvalEnv +-- :: NamespacePolicy +-- -> MsgData +-- -> TransactionM logger db (EvalEnv db) +-- mkEvalEnv nsp msg = do +-- tenv <- ask +-- genv <- GasEnv +-- <$> view (txGasLimit . to (MilliGasLimit . gasToMilliGas)) +-- <*> view txGasPrice +-- <*> use txGasModel +-- liftIO $ setupEvalEnv (_txDbEnv tenv) Nothing (_txMode tenv) +-- msg (versionedNativesRefStore (_txExecutionConfig tenv)) genv +-- nsp (_txSpvSupport tenv) (_txPublicData tenv) (_txExecutionConfig tenv) + +mkEvalEnv + :: NamespacePolicy + -> MsgData + -> TransactionM logger db (EvalEnv CoreBuiltin SpanInfo) +mkEvalEnv nsp MsgData{..} = do + undefined + -- tenv <- ask + + -- let + -- convertPactValue pv = aeson (\s -> error $ "mkEvalEnv: failed to parse legacyValue " ++ s) id $ A.fromJSON $ _getLegacyValue pv + -- convertQualName QualifiedName{..} = QualifiedName + -- { _qnName = _qnName + -- , _qnModName = _qnQual & \ModuleName{..} -> + -- ModuleName + -- { _mnName = _mnName + -- , _mnNamespace = fmap coerce _mnNamespace + -- } + -- } + -- convertCapability SigCapability{..} = + -- CapToken (convertQualName _scName) (mapMaybe (either (const Nothing) Just . PactConversion.fromLegacyPactValue) _scArgs) + + -- convertVerifier Verifier{..} = Verifier + -- { _verifierName = coerce _verifierName + -- , _verifierProof = _verifierProof + -- , _verifierCaps = map convertCapability _verifierCaps + -- } + + -- let + -- txMode' = case _txMode tenv of + -- Transactional -> Transactional + -- Local -> Local + + -- let + -- coreMsg = MsgData + -- { mdData = either (const $ PObject mempty) id $ PactConversion.fromLegacyPactValue $ convertPactValue mdData + -- , mdStep = mdStep <&> \PactStep{..} -> + -- DefPactStep + -- { _psStep = _psStep + -- , _psRollback = _psRollback + -- , _psDefPactId = coerce _psPactId + -- , _psResume = _psResume <&> \Yield{..} -> + -- Yield + -- { _yData = M.fromList $ mapMaybe (\(k, v) -> fmap (coerce k,) $ either (const Nothing) Just $ PactConversion.fromLegacyPactValue v) $ M.toList $ _objectMap _yData + -- , _yProvenance = _yProvenance <&> \Provenance{..} -> + -- Provenance + -- { _pTargetChainId = coerce _pTargetChainId + -- , _pModuleHash = let (ModuleHash h) = _pModuleHash in ModuleHash $ coerce h + -- } + -- , _ySourceChain = coerce _ySourceChain + -- } + -- } + -- , mdHash = coerce $ mdHash + -- , mdSigners = mdSigners <&> \Signer{..} -> + -- Signer + -- { _siScheme = _siScheme <&> \case + -- ED25519 -> ED25519 + -- WebAuthn -> WebAuthn + -- , _siPubKey = _siPubKey + -- , _siAddress = _siAddress + -- , _siCapList = map convertCapability _siCapList + -- } + -- , mdVerifiers = map convertVerifier mdVerifiers + -- } + + -- let + -- coreNsp = case nsp of + -- SimpleNamespacePolicy _ -> SimpleNamespacePolicy + -- SmartNamespacePolicy rootUsage name -> SmartNamespacePolicy rootUsage (convertQualName name) + + -- let + -- pd = _txPublicData tenv + -- convertPublicMeta pm = PublicMeta + -- { _pmChainId = coerce $ _pmChainId pm + -- , _pmSender = _pmSender pm + -- , _pmGasLimit = + -- let (GasLimit (ParsedInteger g)) = _pmGasLimit pm in Gas $ fromIntegral g + -- , _pmGasPrice = coerce $ _pmGasPrice pm + -- , _pmTTL = + -- let (TTLSeconds (ParsedInteger s)) = _pmTTL pm in TTLSeconds s + -- , _pmCreationTime = coerce $ _pmCreationTime pm + -- } + -- cpd = PublicData + -- { _pdPublicMeta = convertPublicMeta $ _pdPublicMeta pd + -- , _pdBlockHeight = _pdBlockHeight pd + -- , _pdBlockTime = _pdBlockTime pd + -- , _pdPrevBlockHash = _pdPrevBlockHash pd + -- } + + -- gasModel <- use txGasModelCore + -- let + -- toCoreExFlag = \case + -- FlagDisableModuleInstall -> Just FlagDisableModuleInstall + -- FlagDisableHistoryInTransactionalMode -> Just FlagDisableHistoryInTransactionalMode + -- FlagAllowReadInLocal -> Just FlagAllowReadInLocal + -- FlagDisablePactEvents -> Just FlagDisablePactEvents + -- FlagEnforceKeyFormats -> Just FlagEnforceKeyFormats + -- _ -> Nothing + -- executionFlags = mapMaybe toCoreExFlag $ S.toList $ _ecFlags $ _txExecutionConfig tenv + -- liftIO $ setupEvalEnv (_txCoreDb tenv) txMode' coreMsg gasModel coreNsp noSPVSupport cpd (S.fromList executionFlags) + +-- | Managed namespace policy CAF +-- +managedNamespacePolicy :: NamespacePolicy +managedNamespacePolicy = SmartNamespacePolicy False + (QualifiedName "validate" (ModuleName "ns" Nothing)) +{-# NOINLINE managedNamespacePolicy #-} + +-- | Builder for "magic" capabilities given a magic cap name +-- +mkMagicCapSlot :: Text -> CapSlot QualifiedName PactValue +mkMagicCapSlot c = CapSlot cap [] + where + mn = ModuleName "coin" Nothing + fqn = QualifiedName c mn + cap = CapToken fqn [] +{-# INLINE mkMagicCapSlot #-} + +-- | Build the 'Pact4.ExecMsg' for some pact code fed to the function. The 'value' +-- parameter is for any possible environmental data that needs to go into +-- the 'Pact4.ExecMsg'. +-- +buildExecRawCode + :: PactParserVersion + -> Maybe Value + -> Text + -> IO (Pact4.ExecMsg RawCode) +buildExecRawCode ppv value code = maybe (go Null) go value + where + go val = case parsePact ppv code of + Right !t -> pure $! Pact4.ExecMsg (RawCode "") (undefined val) + -- if we can't construct coin contract calls, this should + -- fail fast + Left err -> internalError $ "buildExecRawCode: parse failed: " <> T.pack err + +-- | Retrieve public metadata from a command +-- +publicMetaOf :: Command (Payload PublicMeta RawCode) -> PublicMeta +publicMetaOf = undefined -- _pMeta . _cmdPayload +{-# INLINE publicMetaOf #-} + +-- | Retrieve the optional Network identifier from a command +-- +networkIdOf :: Command (Payload PublicMeta RawCode) -> Maybe Pact4.NetworkId +networkIdOf = undefined -- _pNetworkId . _cmdPayload +{-# INLINE networkIdOf #-} + +-- | Calculate the gas fee (pact-generate gas cost * user-specified gas price), +-- rounding to the nearest stu. +-- +gasSupplyOf :: Gas -> GasPrice -> GasSupply +gasSupplyOf (Gas gas) gp = GasSupply (Pact4.ParsedDecimal gs) + where + gs = toCoinUnit (fromIntegral gas * gp) +{-# INLINE gasSupplyOf #-} + +-- | Round to the nearest Stu +-- +toCoinUnit :: Decimal -> Decimal +toCoinUnit = roundTo 12 +{-# INLINE toCoinUnit #-} + +gasLog :: (Logger logger) => Text -> TransactionM logger db () +gasLog m = do + l <- view txGasLogger + rk <- view txRequestKey + for_ l $ \logger -> + logInfo_ logger $ m <> ": " <> sshow rk + +-- | Log request keys at DEBUG when successful +-- +debug :: (Logger logger) => Text -> TransactionM logger db () +debug s = do + l <- view txLogger + rk <- view txRequestKey + logDebug_ l $ s <> ": " <> sshow rk + +-- | Denotes fatal failure points in the tx exec process +-- +fatal :: (Logger logger) => Text -> TransactionM logger db a +fatal e = do + l <- view txLogger + rk <- view txRequestKey + + logError_ l + $ "critical transaction failure: " + <> sshow rk <> ": " <> e + + throwM $ PactTransactionExecError (Pact4.fromUntypedHash $ Pact4.unRequestKey rk) e + +logError :: (Logger logger) => Text -> TransactionM logger db () +logError msg = view txLogger >>= \l -> logError_ l msg + +infoLog :: (Logger logger) => Text -> TransactionM logger db () +infoLog msg = view txLogger >>= \l -> logInfo_ l msg diff --git a/src/Chainweb/Pact/Types.hs b/src/Chainweb/Pact/Types.hs index 50d2355ef..b1c4b30d2 100644 --- a/src/Chainweb/Pact/Types.hs +++ b/src/Chainweb/Pact/Types.hs @@ -39,20 +39,17 @@ module Chainweb.Pact.Types -- * Transaction State , TransactionState(..) , txGasModel - , txGasModelCore , txGasLimit , txGasUsed , txGasId , txLogs , txCache - , txCoreCache , txWarnings -- * Transaction Env , TransactionEnv(..) , txMode , txDbEnv - , txCoreDb , txLogger , txGasLogger , txPublicData @@ -62,7 +59,6 @@ module Chainweb.Pact.Types , txRequestKey , txExecutionConfig , txQuirkGasFee - , txusePact5 -- * Transaction Execution Monad , TransactionM(..) @@ -331,12 +327,10 @@ data ApplyCmdExecutionContext = ApplyLocal | ApplySend -- data TransactionState = TransactionState { _txCache :: !ModuleCache - , _txCoreCache :: !CoreModuleCache , _txLogs :: ![TxLogJson] , _txGasUsed :: !Gas , _txGasId :: !(Maybe GasId) - , _txGasModel :: !GasModel - , _txGasModelCore :: !(PCore.GasModel PCore.CoreBuiltin) + , _txGasModel :: !(Either GasModel (PCore.GasModel PCore.CoreBuiltin)) , _txWarnings :: !(Set PactWarning) } makeLenses ''TransactionState @@ -345,8 +339,7 @@ makeLenses ''TransactionState -- data TransactionEnv logger db = TransactionEnv { _txMode :: !ExecutionMode - , _txDbEnv :: !(PactDbEnv db) - , _txCoreDb :: !CoreDb + , _txDbEnv :: !(Either (PactDbEnv db) CoreDb) , _txLogger :: !logger , _txGasLogger :: !(Maybe logger) , _txPublicData :: !PublicData @@ -357,7 +350,6 @@ data TransactionEnv logger db = TransactionEnv , _txGasLimit :: !Gas , _txExecutionConfig :: !ExecutionConfig , _txQuirkGasFee :: !(Maybe Gas) - , _txusePact5 :: !Bool } makeLenses ''TransactionEnv