From b874139f7744cff9df5cabbea7875ff07809a6d5 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Mon, 15 Jun 2020 16:18:56 -0400 Subject: [PATCH 01/48] initial commit --- chainweb.cabal | 2 + test/Chainweb/Test/Pact/RemotePactTest.hs | 165 ++----------------- test/Chainweb/Test/Pact/Utils.hs | 6 - test/Chainweb/Test/Rosetta.hs | 100 ++++++++++++ test/Chainweb/Test/Utils.hs | 185 +++++++++++++++++++++- 5 files changed, 294 insertions(+), 164 deletions(-) create mode 100644 test/Chainweb/Test/Rosetta.hs diff --git a/chainweb.cabal b/chainweb.cabal index 10a1c9159e..f2cf70a46a 100644 --- a/chainweb.cabal +++ b/chainweb.cabal @@ -463,6 +463,7 @@ test-suite chainweb-tests Chainweb.Test.Pact.Utils Chainweb.Test.RestAPI Chainweb.Test.RestAPI.Client_ + Chainweb.Test.Rosetta Chainweb.Test.Roundtrips Chainweb.Test.SPV Chainweb.Test.Store.CAS @@ -522,6 +523,7 @@ test-suite chainweb-tests , resource-pool >= 0.2 , resourcet >= 1.2 , retry >= 0.7 + , rosetta , scheduler >= 1.4 , semialign >= 1 , servant >= 0.16 diff --git a/test/Chainweb/Test/Pact/RemotePactTest.hs b/test/Chainweb/Test/Pact/RemotePactTest.hs index c33d862388..12baf2de21 100644 --- a/test/Chainweb/Test/Pact/RemotePactTest.hs +++ b/test/Chainweb/Test/Pact/RemotePactTest.hs @@ -32,7 +32,6 @@ module Chainweb.Test.Pact.RemotePactTest ) where import Control.Concurrent hiding (modifyMVar, newMVar, putMVar, readMVar) -import Control.Concurrent.Async import Control.Concurrent.MVar.Strict import Control.DeepSeq import Control.Lens @@ -53,23 +52,16 @@ import qualified Data.List as L import qualified Data.List.NonEmpty as NEL import qualified Data.Map.Strict as M import Data.Maybe -import Data.Streaming.Network (HostPreference) import Data.String.Conv (toS) import Data.Text (Text) import qualified Data.Text as T -import Data.Text.Encoding (encodeUtf8) import NeatInterpolation -import Network.Connection as HTTP -import Network.HTTP.Client.TLS as HTTP - import Numeric.Natural import Servant.Client -import System.IO.Extra -import System.LogLevel import Test.Tasty import Test.Tasty.HUnit @@ -92,21 +84,12 @@ import Pact.Types.Term import Chainweb.BlockHeight import Chainweb.ChainId -import Chainweb.Chainweb -import Chainweb.Chainweb.ChainResources -import Chainweb.Chainweb.PeerResources import Chainweb.Cut.CutHashes import Chainweb.CutDB.RestAPI.Client import Chainweb.Graph -import Chainweb.HostAddress -import Chainweb.Logger import Chainweb.Mempool.Mempool -import Chainweb.Miner.Config -import Chainweb.Miner.Pact (noMiner) -import Chainweb.NodeId import Chainweb.Pact.RestAPI.Client import Chainweb.Pact.Service.Types -import Chainweb.Test.P2P.Peer.BootstrapConfig import Chainweb.Test.Pact.Utils import Chainweb.Test.Utils import Chainweb.Time @@ -115,8 +98,6 @@ import Chainweb.Version import Data.CAS.RocksDB -import P2P.Node.Configuration -import P2P.Peer -- -------------------------------------------------------------------------- -- -- Global Settings @@ -151,7 +132,7 @@ gp = 0.1 -- tests :: RocksDb -> ScheduledTest tests rdb = testGroupSch "Chainweb.Test.Pact.RemotePactTest" - [ withNodes rdb nNodes $ \net -> + [ withNodes v "remotePactTest-" rdb nNodes $ \net -> withMVarResource 0 $ \iomvar -> withTime $ \iot -> testGroup "remote pact tests" @@ -189,14 +170,14 @@ tests rdb = testGroupSch "Chainweb.Test.Pact.RemotePactTest" -- awaitNetworkHeight :: IO ChainwebNetwork -> CutHeight -> IO () awaitNetworkHeight nio h = do - cenv <- _getClientEnv <$> nio + cenv <- _runClientEnv <$> nio ch <- awaitCutHeight cenv h debug $ "cut height: " <> sshow (_cutHashesHeight ch) responseGolden :: IO ChainwebNetwork -> IO RequestKeys -> TestTree responseGolden networkIO rksIO = golden "remote-golden" $ do rks <- rksIO - cenv <- _getClientEnv <$> networkIO + cenv <- _runClientEnv <$> networkIO PollResponses theMap <- polling cid cenv rks ExpectPactResult let values = mapMaybe (\rk -> _crResult <$> HashMap.lookup rk theMap) (NEL.toList $ _rkRequestKeys rks) @@ -204,7 +185,7 @@ responseGolden networkIO rksIO = golden "remote-golden" $ do localTest :: IO (Time Micros) -> IO ChainwebNetwork -> IO () localTest iot nio = do - cenv <- fmap _getClientEnv nio + cenv <- fmap _runClientEnv nio mv <- newMVar 0 SubmitBatch batch <- testBatch iot mv gp let cmd = head $ toList batch @@ -215,7 +196,7 @@ localTest iot nio = do localChainDataTest :: IO (Time Micros) -> IO ChainwebNetwork -> IO () localChainDataTest iot nio = do - cenv <- fmap _getClientEnv nio + cenv <- fmap _runClientEnv nio mv <- newMVar (0 :: Int) SubmitBatch batch <- localTestBatch iot mv let cmd = head $ toList batch @@ -250,7 +231,7 @@ localChainDataTest iot nio = do pollingBadlistTest :: IO ChainwebNetwork -> TestTree pollingBadlistTest nio = testCase "/poll reports badlisted txs" $ do - cenv <- fmap _getClientEnv nio + cenv <- fmap _runClientEnv nio let rks = RequestKeys $ NEL.fromList [pactDeadBeef] sid <- liftIO $ mkChainId v maxBound (0 :: Int) void $ polling sid cenv rks ExpectPactError @@ -260,7 +241,7 @@ sendValidationTest :: IO (Time Micros) -> IO ChainwebNetwork -> TestTree sendValidationTest iot nio = testCaseSteps "/send reports validation failure" $ \step -> do step "check sending poisoned TTL batch" - cenv <- fmap _getClientEnv nio + cenv <- fmap _runClientEnv nio mv <- newMVar 0 SubmitBatch batch1 <- testBatch' iot 10_000 mv gp SubmitBatch batch2 <- testBatch' (return $ Time $ TimeSpan 0) 2 mv gp @@ -318,7 +299,7 @@ expectSendFailure expectErr act = tryAllSynchronous act >>= \case spvTest :: IO (Time Micros) -> IO ChainwebNetwork -> TestTree spvTest iot nio = testCaseSteps "spv client tests" $ \step -> do - cenv <- fmap _getClientEnv nio + cenv <- fmap _runClientEnv nio batch <- mkTxBatch sid <- mkChainId v maxBound (1 :: Int) r <- flip runClientM cenv $ do @@ -369,7 +350,7 @@ spvTest iot nio = testCaseSteps "spv client tests" $ \step -> do txTooBigGasTest :: IO (Time Micros) -> IO ChainwebNetwork -> TestTree txTooBigGasTest iot nio = testCaseSteps "transaction size gas tests" $ \step -> do - cenv <- fmap _getClientEnv nio + cenv <- fmap _runClientEnv nio sid <- mkChainId v maxBound (0 :: Int) let runSend batch expectation = flip runClientM cenv $ do @@ -437,7 +418,7 @@ caplistTest iot nio = testCaseSteps "caplist TRANSFER + FUND_TX test" $ \step -> let testCaseStep = void . liftIO . step - cenv <- fmap _getClientEnv nio + cenv <- fmap _runClientEnv nio sid <- liftIO $ mkChainId v maxBound (0 :: Int) r <- flip runClientM cenv $ do @@ -508,7 +489,7 @@ allocationTest iot nio = testCaseSteps "genesis allocation tests" $ \step -> do let testCaseStep = void . liftIO . step - cenv <- fmap _getClientEnv nio + cenv <- fmap _runClientEnv nio sid <- liftIO $ mkChainId v maxBound (0 :: Int) step "positive allocation test: allocation00 release" @@ -680,19 +661,13 @@ withRequestKeys iot ioNonce networkIO f = withResource mkKeys (\_ -> return ()) where mkKeys :: IO RequestKeys mkKeys = do - cenv <- _getClientEnv <$> networkIO + cenv <- _runClientEnv <$> networkIO mNonce <- ioNonce testSend iot mNonce cenv testSend :: IO (Time Micros) -> MVar Int -> ClientEnv -> IO RequestKeys testSend iot mNonce env = testBatch iot mNonce gp >>= sending cid env -getClientEnv :: BaseUrl -> IO ClientEnv -getClientEnv url = do - let mgrSettings = HTTP.mkManagerSettings (HTTP.TLSSettingsSimple True False False) Nothing - mgr <- HTTP.newTlsManagerWith mgrSettings - return $ mkClientEnv mgr url - awaitCutHeight :: ClientEnv -> CutHeight @@ -875,122 +850,6 @@ testBatch iot mnonce = testBatch' iot ttl mnonce -- test node(s), config, etc. for this test -------------------------------------------------------------------------------- -newtype ChainwebNetwork = ChainwebNetwork { _getClientEnv :: ClientEnv } - -withNodes - :: RocksDb - -> Natural - -> (IO ChainwebNetwork -> TestTree) - -> TestTree -withNodes rdb n f = withResource start - (cancel . fst) - (f . fmap (ChainwebNetwork . snd)) - where - start :: IO (Async (), ClientEnv) - start = do - peerInfoVar <- newEmptyMVar - a <- async $ runTestNodes rdb Quiet v n peerInfoVar - i <- readMVar peerInfoVar - cwEnv <- getClientEnv $ getCwBaseUrl $ _hostAddressPort $ _peerAddr i - return (a, cwEnv) - - getCwBaseUrl :: Port -> BaseUrl - getCwBaseUrl p = BaseUrl - { baseUrlScheme = Https - , baseUrlHost = "127.0.0.1" - , baseUrlPort = fromIntegral p - , baseUrlPath = "" - } - -runTestNodes - :: RocksDb - -> LogLevel - -> ChainwebVersion - -> Natural - -> MVar PeerInfo - -> IO () -runTestNodes rdb loglevel ver n portMVar = - forConcurrently_ [0 .. int n - 1] $ \i -> do - threadDelay (1000 * int i) - let baseConf = config ver n (NodeId i) - conf <- if - | i == 0 -> - return $ bootstrapConfig baseConf - | otherwise -> - setBootstrapPeerInfo <$> readMVar portMVar <*> pure baseConf - node rdb loglevel portMVar conf - -node :: RocksDb -> LogLevel -> MVar PeerInfo -> ChainwebConfiguration -> IO () -node rdb loglevel peerInfoVar conf = do - rocksDb <- testRocksDb ("remotePactTest-" <> encodeUtf8 (toText nid)) rdb - System.IO.Extra.withTempDir $ \dir -> withChainweb conf logger rocksDb (Just dir) False $ \cw -> do - - -- If this is the bootstrap node we extract the port number and publish via an MVar. - when (nid == NodeId 0) $ do - let bootStrapInfo = view (chainwebPeer . peerResPeer . peerInfo) cw - putMVar peerInfoVar bootStrapInfo - - poisonDeadBeef cw - runChainweb cw `finally` do - logFunctionText logger Info "write sample data" - logFunctionText logger Info "shutdown node" - return () - where - nid = _configNodeId conf - logger :: GenericLogger - logger = addLabel ("node", toText nid) $ genericLogger loglevel print - - poisonDeadBeef cw = mapM_ poison crs - where - crs = map snd $ HashMap.toList $ view chainwebChains cw - poison cr = mempoolAddToBadList (view chainResMempool cr) deadbeef - -deadbeef :: TransactionHash -deadbeef = TransactionHash "deadbeefdeadbeefdeadbeefdeadbeef" - pactDeadBeef :: RequestKey pactDeadBeef = let (TransactionHash b) = deadbeef in RequestKey $ Hash $ SB.fromShort b - -host :: Hostname -host = unsafeHostnameFromText "::1" - -interface :: HostPreference -interface = "::1" - -config - :: ChainwebVersion - -> Natural - -> NodeId - -> ChainwebConfiguration -config ver n nid = defaultChainwebConfiguration ver - & set configNodeId nid - & set (configP2p . p2pConfigPeer . peerConfigHost) host - & set (configP2p . p2pConfigPeer . peerConfigInterface) interface - & set (configP2p . p2pConfigKnownPeers) mempty - & set (configP2p . p2pConfigIgnoreBootstrapNodes) True - & set (configP2p . p2pConfigMaxPeerCount) (n * 2) - & set (configP2p . p2pConfigMaxSessionCount) 4 - & set (configP2p . p2pConfigSessionTimeout) 60 - & set (configMining . miningInNode) miner - & set configReintroTxs True - & set (configTransactionIndex . enableConfigEnabled) True - & set (configBlockGasLimit) 1_000_000 - where - miner = NodeMiningConfig - { _nodeMiningEnabled = True - , _nodeMiner = noMiner - , _nodeTestMiners = MinerCount n } - -bootstrapConfig :: ChainwebConfiguration -> ChainwebConfiguration -bootstrapConfig conf = conf - & set (configP2p . p2pConfigPeer) peerConfig - & set (configP2p . p2pConfigKnownPeers) [] - where - peerConfig = head (bootstrapPeerConfig $ _configChainwebVersion conf) - & set peerConfigPort 0 - & set peerConfigHost host - -setBootstrapPeerInfo :: PeerInfo -> ChainwebConfiguration -> ChainwebConfiguration -setBootstrapPeerInfo = - over (configP2p . p2pConfigKnownPeers) . (:) diff --git a/test/Chainweb/Test/Pact/Utils.hs b/test/Chainweb/Test/Pact/Utils.hs index 9f67b6edd9..97ad621f30 100644 --- a/test/Chainweb/Test/Pact/Utils.hs +++ b/test/Chainweb/Test/Pact/Utils.hs @@ -523,12 +523,6 @@ withPactCtxSQLite v bhdbIO pdbIO config f = (_,s) <- ios testPactCtxSQLite v cid bhdb pdb s config -withMVarResource :: a -> (IO (MVar a) -> TestTree) -> TestTree -withMVarResource value = withResource (newMVar value) mempty - -withTime :: (IO (Time Micros) -> TestTree) -> TestTree -withTime = withResource getCurrentTimeIntegral mempty - toTxCreationTime :: Integral a => Time a -> TxCreationTime toTxCreationTime (Time timespan) = TxCreationTime $ fromIntegral $ timeSpanToSeconds timespan diff --git a/test/Chainweb/Test/Rosetta.hs b/test/Chainweb/Test/Rosetta.hs new file mode 100644 index 0000000000..afe402a9ad --- /dev/null +++ b/test/Chainweb/Test/Rosetta.hs @@ -0,0 +1,100 @@ +{-# LANGUAGE OverloadedStrings #-} +module Chainweb.Test.Rosetta where + + +import GHC.Natural + +import Test.Tasty +import Test.Tasty.HUnit + +import Chainweb.Graph +import Chainweb.Time (Time(..), Micros(..)) +import Chainweb.Version +import Chainweb.Test.Utils + +import Data.CAS.RocksDB + +import Rosetta + +-- -------------------------------------------------------------------------- -- +-- Global Settings + +v :: ChainwebVersion +v = FastTimedCPM petersonChainGraph + +nodes:: Natural +nodes = 1 + +type RosettaTest = IO (Time Micros) -> IO ChainwebNetwork -> TestTree + +nid :: NetworkId +nid = NetworkId + { _networkId_blockchain = undefined + , _networkId_network = "fastTimedCPM" + , _networkId_subNetworkId = undefined + } + +aid :: AccountId +aid = AccountId + { _accountId_address = "sender00" + , _accountId_subAccount = Nothing + , _accountId_metadata = undefined + } + +-- -------------------------------------------------------------------------- -- +-- Test Tree + +tests :: RocksDb -> ScheduledTest +tests rdb = testGroupSch "Chainweb.Test.Rosetta" go + where + go = return $ + withNodes v "rosettaRemoteTests-" rdb nodes $ \nio -> + withTime $ \tio -> tgrp nio tio + + tgrp nio tio + = testGroup "Rosetta API tests" + $ fmap (\test -> test tio nio) tests_ + + tests_ = + [ accountBalanceTests + , blockTransactionTests + , blockTests + , constructionMetadataTests + , constructionSubmitTests + , mempoolTransactionTests + , networkListTests + , networkOptionsTests + , networkStatusTests + ] + + +accountBalanceTests :: RosettaTest +accountBalanceTests _tio _nio = testCaseSteps "Account Balance Lookup" $ \ _step -> do + _cenv <- _runClientEnv <$> _nio + return () + where + _req = AccountBalanceReq nid aid Nothing + +blockTransactionTests :: RosettaTest +blockTransactionTests _tio _nio = undefined + +blockTests :: RosettaTest +blockTests _tio _nio = undefined + +constructionMetadataTests :: RosettaTest +constructionMetadataTests _tio _nio = undefined + +constructionSubmitTests :: RosettaTest +constructionSubmitTests _tio _nio = undefined + +mempoolTransactionTests :: RosettaTest +mempoolTransactionTests _tio _nio = undefined + +networkListTests :: RosettaTest +networkListTests _tio _nio = undefined + +networkOptionsTests :: RosettaTest +networkOptionsTests _tio _nio = undefined + +networkStatusTests :: RosettaTest +networkStatusTests _tio _nio = undefined diff --git a/test/Chainweb/Test/Utils.hs b/test/Chainweb/Test/Utils.hs index 190e764c25..f45750f519 100644 --- a/test/Chainweb/Test/Utils.hs +++ b/test/Chainweb/Test/Utils.hs @@ -1,6 +1,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiWayIf #-} +{-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RankNTypes #-} @@ -103,13 +104,28 @@ module Chainweb.Test.Utils -- * Misc , genEnum + +-- * Multi-node testing utils +, ChainwebNetwork(..) +, withNodes +, runTestNodes +, node +, deadbeef +, mkConfig +, bootstrapConfig +, setBootstrapPeerInfo +, defaultHost +, defaultInterface +, withTime +, withMVarResource ) where import Control.Concurrent import Control.Concurrent.Async import Control.Exception (bracket) -import Control.Lens (deep, filtered, toListOf) -import Control.Monad.Catch (MonadThrow) +import Control.Lens +import Control.Monad +import Control.Monad.Catch (MonadThrow, finally) import Control.Monad.IO.Class import qualified Data.ByteString.Lazy as BL @@ -120,13 +136,17 @@ import Data.Bytes.Put import qualified Data.ByteString as B import Data.Coerce (coerce) import Data.Foldable +import qualified Data.HashMap.Strict as HashMap import Data.List (sortOn,isInfixOf) import qualified Data.Text as T +import qualified Data.Text.Encoding as T import Data.Tree import qualified Data.Tree.Lens as LT import Data.Word (Word64) +import qualified Network.Connection as HTTP import qualified Network.HTTP.Client as HTTP +import qualified Network.HTTP.Client.TLS as HTTP import Network.Socket (close) import qualified Network.Wai as W import qualified Network.Wai.Handler.Warp as W @@ -138,7 +158,9 @@ import Servant.Client (BaseUrl(..), ClientEnv, Scheme(..), mkClientEnv) import System.Directory import System.Environment (withArgs) +import qualified System.IO.Extra as Extra import System.IO.Temp +import System.LogLevel import System.Random (randomIO) import Test.QuickCheck.Property (Property, Testable, (===)) @@ -162,18 +184,25 @@ import Chainweb.BlockHeaderDB.Internal import Chainweb.BlockHeight import Chainweb.BlockWeight import Chainweb.ChainId +import Chainweb.Chainweb +import Chainweb.Chainweb.ChainResources import Chainweb.Chainweb.MinerResources (MiningCoordination) +import Chainweb.Chainweb.PeerResources import Chainweb.Crypto.MerkleLog hiding (header) import Chainweb.CutDB import Chainweb.Difficulty (targetToDifficulty) import Chainweb.Graph -import Chainweb.Logger (Logger, GenericLogger) -import Chainweb.Mempool.Mempool (MempoolBackend(..)) +import Chainweb.HostAddress +import Chainweb.Logger +import Chainweb.Mempool.Mempool (MempoolBackend(..), TransactionHash(..)) +import Chainweb.Miner.Config +import Chainweb.Miner.Pact +import Chainweb.NodeId import Chainweb.Payload.PayloadStore import Chainweb.RestAPI import Chainweb.RestAPI.NetworkID import Chainweb.Test.P2P.Peer.BootstrapConfig - (bootstrapCertificate, bootstrapKey) + (bootstrapCertificate, bootstrapKey, bootstrapPeerConfig) import Chainweb.Test.Utils.BlockHeader import Chainweb.Time import Chainweb.TreeDB @@ -186,6 +215,8 @@ import Data.CAS.RocksDB import Network.X509.SelfSigned import qualified P2P.Node.PeerDB as P2P +import P2P.Node.Configuration +import P2P.Peer -- -------------------------------------------------------------------------- -- -- Misc @@ -849,3 +880,147 @@ runSchedRocks test = withTempRocksDb "chainweb-tests" $ \rdb -> runSched (test r -- > matchTest "myTest" $ runSched tests matchTest :: String -> IO a -> IO a matchTest pat = withArgs ["-p",pat] + +-- ------------------------------------------------------------------------ -- +-- Multi-node network utils + +withNodes + :: ChainwebVersion + -> B.ByteString + -> RocksDb + -> Natural + -> (IO ChainwebNetwork -> TestTree) + -> TestTree +withNodes v label rdb n f = withResource start + (cancel . fst) + (f . fmap (ChainwebNetwork . snd)) + where + start :: IO (Async (), ClientEnv) + start = do + peerInfoVar <- newEmptyMVar + a <- async $ runTestNodes label rdb Quiet v n peerInfoVar + i <- readMVar peerInfoVar + cwEnv <- getClientEnv $ getCwBaseUrl $ _hostAddressPort $ _peerAddr i + return (a, cwEnv) + + getCwBaseUrl :: Port -> BaseUrl + getCwBaseUrl p = BaseUrl + { baseUrlScheme = Https + , baseUrlHost = "127.0.0.1" + , baseUrlPort = fromIntegral p + , baseUrlPath = "" + } + +runTestNodes + :: B.ByteString + -> RocksDb + -> LogLevel + -> ChainwebVersion + -> Natural + -> MVar PeerInfo + -> IO () +runTestNodes label rdb loglevel ver n portMVar = + forConcurrently_ [0 .. int n - 1] $ \i -> do + threadDelay (1000 * int i) + let baseConf = mkConfig defaultHost defaultInterface ver n (NodeId i) + conf <- if + | i == 0 -> + return $ bootstrapConfig defaultHost baseConf + | otherwise -> + setBootstrapPeerInfo <$> readMVar portMVar <*> pure baseConf + node label rdb loglevel portMVar conf + +node + :: B.ByteString + -> RocksDb + -> LogLevel + -> MVar PeerInfo + -> ChainwebConfiguration + -> IO () +node label rdb loglevel peerInfoVar conf = do + rocksDb <- testRocksDb (label <> T.encodeUtf8 (toText nid)) rdb + Extra.withTempDir $ \dir -> withChainweb conf logger rocksDb (Just dir) False $ \cw -> do + + -- If this is the bootstrap node we extract the port number and publish via an MVar. + when (nid == NodeId 0) $ do + let bootStrapInfo = view (chainwebPeer . peerResPeer . peerInfo) cw + putMVar peerInfoVar bootStrapInfo + + poisonDeadBeef cw + runChainweb cw `finally` do + logFunctionText logger Info "write sample data" + logFunctionText logger Info "shutdown node" + return () + where + nid = _configNodeId conf + logger :: GenericLogger + logger = addLabel ("node", toText nid) $ genericLogger loglevel print + + poisonDeadBeef cw = mapM_ poison crs + where + crs = map snd $ HashMap.toList $ view chainwebChains cw + poison cr = mempoolAddToBadList (view chainResMempool cr) deadbeef + +deadbeef :: TransactionHash +deadbeef = TransactionHash "deadbeefdeadbeefdeadbeefdeadbeef" + +mkConfig + :: Hostname + -> W.HostPreference + -> ChainwebVersion + -> Natural + -> NodeId + -> ChainwebConfiguration +mkConfig host interface ver n nid = defaultChainwebConfiguration ver + & set configNodeId nid + & set (configP2p . p2pConfigPeer . peerConfigHost) host + & set (configP2p . p2pConfigPeer . peerConfigInterface) interface + & set (configP2p . p2pConfigKnownPeers) mempty + & set (configP2p . p2pConfigIgnoreBootstrapNodes) True + & set (configP2p . p2pConfigMaxPeerCount) (n * 2) + & set (configP2p . p2pConfigMaxSessionCount) 4 + & set (configP2p . p2pConfigSessionTimeout) 60 + & set (configMining . miningInNode) miner + & set configReintroTxs True + & set (configTransactionIndex . enableConfigEnabled) True + & set (configBlockGasLimit) 1_000_000 + where + miner = NodeMiningConfig + { _nodeMiningEnabled = True + , _nodeMiner = noMiner + , _nodeTestMiners = MinerCount n } + +bootstrapConfig :: Hostname -> ChainwebConfiguration -> ChainwebConfiguration +bootstrapConfig host conf = conf + & set (configP2p . p2pConfigPeer) peerConfig + & set (configP2p . p2pConfigKnownPeers) [] + where + peerConfig = head (bootstrapPeerConfig $ _configChainwebVersion conf) + & set peerConfigPort 0 + & set peerConfigHost host + +setBootstrapPeerInfo :: PeerInfo -> ChainwebConfiguration -> ChainwebConfiguration +setBootstrapPeerInfo = + over (configP2p . p2pConfigKnownPeers) . (:) + + +defaultHost :: Hostname +defaultHost = unsafeHostnameFromText "::1" + +defaultInterface :: W.HostPreference +defaultInterface = "::1" + +newtype ChainwebNetwork = ChainwebNetwork { _runClientEnv :: ClientEnv } + +getClientEnv :: BaseUrl -> IO ClientEnv +getClientEnv url = flip mkClientEnv url <$> HTTP.newTlsManagerWith mgrSettings + where + mgrSettings = HTTP.mkManagerSettings + (HTTP.TLSSettingsSimple True False False) + Nothing + +withMVarResource :: a -> (IO (MVar a) -> TestTree) -> TestTree +withMVarResource value = withResource (newMVar value) mempty + +withTime :: (IO (Time Micros) -> TestTree) -> TestTree +withTime = withResource getCurrentTimeIntegral mempty From 090986e2ef7cd6d1ef6e0a234f208d963f1e27b1 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Mon, 15 Jun 2020 18:26:37 -0400 Subject: [PATCH 02/48] fix exports --- chainweb.cabal | 3 ++- test/Chainweb/Test/MultiNode.hs | 17 ++--------------- test/Chainweb/Test/Utils.hs | 1 + 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/chainweb.cabal b/chainweb.cabal index 67740650c3..4807fb35b0 100644 --- a/chainweb.cabal +++ b/chainweb.cabal @@ -655,6 +655,7 @@ executable cwtool , chainweb-storage >= 0.1 , clock >= 0.7 , configuration-tools >= 0.5 + , connection >=0.2 , containers >= 0.5 , cryptonite >= 0.25 , deepseq >= 1.4 @@ -664,6 +665,7 @@ executable cwtool , file-embed , errors >= 2.3 , exceptions >= 0.8 + , extra >= 1.6 , file-embed >= 0.0 , formatting >= 6.3 , http-client >= 0.5 @@ -737,7 +739,6 @@ benchmark bench , deepseq >= 1.4 , directory >= 1.3 , exceptions >= 0.8 - , extra >= 1.6 , file-embed >= 0.0 , lens >= 4.16 , loglevel >= 0.1 diff --git a/test/Chainweb/Test/MultiNode.hs b/test/Chainweb/Test/MultiNode.hs index 6f609361db..d07335a886 100644 --- a/test/Chainweb/Test/MultiNode.hs +++ b/test/Chainweb/Test/MultiNode.hs @@ -42,7 +42,7 @@ import Control.Concurrent import Control.Concurrent.Async import Control.DeepSeq import Control.Exception -import Control.Lens (over, set, view) +import Control.Lens (set, view) import Control.Monad import Data.Aeson @@ -86,7 +86,7 @@ import Chainweb.Miner.Config import Chainweb.Miner.Pact import Chainweb.NodeId import Chainweb.Test.P2P.Peer.BootstrapConfig -import Chainweb.Test.Utils +import Chainweb.Test.Utils hiding (bootstrapConfig, node) import Chainweb.Time (Seconds(..)) import Chainweb.Utils import Chainweb.Version @@ -177,19 +177,6 @@ config v n nid = defaultChainwebConfiguration v , _throttlingLocalRate = 10_000 -- per 10 seconds } --- | Set the bootstrap node port of a 'ChainwebConfiguration' --- -setBootstrapPeerInfo - :: PeerInfo - -- ^ Peer info of bootstrap node - -> ChainwebConfiguration - -> ChainwebConfiguration -setBootstrapPeerInfo - = over (configP2p . p2pConfigKnownPeers) . (:) - -- The the port of the bootstrap node. Normally this is hard-coded. - -- But in test-suites that may run concurrently we want to use a port - -- that is assigned by the OS. - -- | Configure a bootstrap node -- bootstrapConfig diff --git a/test/Chainweb/Test/Utils.hs b/test/Chainweb/Test/Utils.hs index f45750f519..6c029a9736 100644 --- a/test/Chainweb/Test/Utils.hs +++ b/test/Chainweb/Test/Utils.hs @@ -138,6 +138,7 @@ import Data.Coerce (coerce) import Data.Foldable import qualified Data.HashMap.Strict as HashMap import Data.List (sortOn,isInfixOf) +-- import Data.Streaming.Network (HostPreference) import qualified Data.Text as T import qualified Data.Text.Encoding as T import Data.Tree From fda98c0647c1b84d0b323abf55b02619975e0109 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Wed, 17 Jun 2020 18:59:12 -0400 Subject: [PATCH 03/48] boilerplate extravaganza --- chainweb.cabal | 1 + src/Chainweb/Rosetta/RestAPI.hs | 223 ++++++++++++++++++----- src/Chainweb/Rosetta/RestAPI/Client.hs | 235 +++++++++++++++++++++++++ test/Chainweb/Test/Rosetta.hs | 214 +++++++++++++++++++++- 4 files changed, 624 insertions(+), 49 deletions(-) create mode 100644 src/Chainweb/Rosetta/RestAPI/Client.hs diff --git a/chainweb.cabal b/chainweb.cabal index 675958b01b..c414981f79 100644 --- a/chainweb.cabal +++ b/chainweb.cabal @@ -208,6 +208,7 @@ library , Chainweb.RestAPI.Orphans , Chainweb.RestAPI.Utils , Chainweb.Rosetta.RestAPI + , Chainweb.Rosetta.RestAPI.Client , Chainweb.Rosetta.RestAPI.Server , Chainweb.SPV , Chainweb.SPV.CreateProof diff --git a/src/Chainweb/Rosetta/RestAPI.hs b/src/Chainweb/Rosetta/RestAPI.hs index 2b59cda6f9..6e6e0e6a05 100644 --- a/src/Chainweb/Rosetta/RestAPI.hs +++ b/src/Chainweb/Rosetta/RestAPI.hs @@ -1,6 +1,7 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} @@ -14,8 +15,29 @@ -- module Chainweb.Rosetta.RestAPI ( -- * Endpoints - RosettaApi_ - , RosettaApi + RosettaApi + , rosettaApi + -- * Standalone APIs for client derivation + , RosettaAccountBalanceApi + , rosettaAccountBalanceApi + , RosettaBlockTransactionApi + , rosettaBlockTransactionApi + , RosettaBlockApi + , rosettaBlockApi + , RosettaConstructionMetadataApi + , rosettaConstructionMetadataApi + , RosettaConstructionSubmitApi + , rosettaConstructionSubmitApi + , RosettaMempoolTransactionApi + , rosettaMempoolTransactionApi + , RosettaMempoolApi + , rosettaMempoolApi + , RosettaNetworkListApi + , rosettaNetworkListApi + , RosettaNetworkOptionsApi + , rosettaNetworkOptionsApi + , RosettaNetworkStatusApi + , rosettaNetworkStatusApi -- * Errors , RosettaFailure(..) , rosettaError @@ -25,7 +47,6 @@ module Chainweb.Rosetta.RestAPI import Control.Error.Util import Control.Monad (when) -import Control.Monad.Except (throwError) import Control.Monad.Trans.Except (ExceptT) import Data.Aeson (encode) @@ -33,8 +54,7 @@ import qualified Data.Text as T import Rosetta -import Servant.API -import Servant.Server +import Servant import Text.Read (readMaybe) @@ -46,45 +66,165 @@ import Chainweb.Version --- -type RosettaApi_ = - -- Accounts -- - "rosetta" :> "account" :> "balance" - :> ReqBody '[JSON] AccountBalanceReq - :> Post '[JSON] AccountBalanceResp - -- Blocks -- - :<|> "rosetta" :> "block" :> "transaction" - :> ReqBody '[JSON] BlockTransactionReq - :> Post '[JSON] BlockTransactionResp - :<|> "rosetta" :> "block" - :> ReqBody '[JSON] BlockReq - :> Post '[JSON] BlockResp - -- Construction -- - :<|> "rosetta" :> "construction" :> "metadata" - :> ReqBody '[JSON] ConstructionMetadataReq - :> Post '[JSON] ConstructionMetadataResp - :<|> "rosetta" :> "construction" :> "submit" - :> ReqBody '[JSON] ConstructionSubmitReq - :> Post '[JSON] ConstructionSubmitResp - -- Mempool -- - :<|> "rosetta" :> "mempool" :> "transaction" - :> ReqBody '[JSON] MempoolTransactionReq - :> Post '[JSON] MempoolTransactionResp - :<|> "rosetta" :> "mempool" - :> ReqBody '[JSON] MempoolReq - :> Post '[JSON] MempoolResp - -- Network -- - :<|> "rosetta" :> "network" :> "list" - :> ReqBody '[JSON] MetadataReq - :> Post '[JSON] NetworkListResp - :<|> "rosetta" :> "network" :> "options" - :> ReqBody '[JSON] NetworkReq - :> Post '[JSON] NetworkOptionsResp - :<|> "rosetta" :> "network" :> "status" - :> ReqBody '[JSON] NetworkReq - :> Post '[JSON] NetworkStatusResp +-- ------------------------------------------------------------------ -- +-- Rosetta Api type RosettaApi (v :: ChainwebVersionT) = 'ChainwebEndpoint v :> Reassoc RosettaApi_ +type RosettaApi_ = "rosetta" :> + ( -- Accounts -- + RosettaAccountBalanceApi_ + -- Blocks -- + :<|> RosettaBlockTransactionApi_ + :<|> RosettaBlockApi_ + -- Construction -- + :<|> RosettaConstructionMetadataApi_ + :<|> RosettaConstructionSubmitApi_ + -- Mempool -- + :<|> RosettaMempoolTransactionApi_ + :<|> RosettaMempoolApi_ + -- Network -- + :<|> RosettaNetworkListApi_ + :<|> RosettaNetworkOptionsApi_ + :<|> RosettaNetworkStatusApi_ + ) + +rosettaApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaApi v) +rosettaApi = Proxy + +-- ------------------------------------------------------------------ -- +-- Standalone Endpoints + Witnesses + +type RosettaApiEndpoint (v :: ChainwebVersionT) api + = 'ChainwebEndpoint v + :> "rosetta" + :> api + +type RosettaAccountBalanceApi v = RosettaApiEndpoint v RosettaAccountBalanceApi_ +type RosettaBlockTransactionApi v = RosettaApiEndpoint v RosettaBlockTransactionApi_ +type RosettaBlockApi v = RosettaApiEndpoint v RosettaBlockApi_ +type RosettaConstructionSubmitApi v = RosettaApiEndpoint v RosettaConstructionSubmitApi_ +type RosettaConstructionMetadataApi v = RosettaApiEndpoint v RosettaConstructionMetadataApi_ +type RosettaMempoolTransactionApi v = RosettaApiEndpoint v RosettaMempoolTransactionApi_ +type RosettaMempoolApi v = RosettaApiEndpoint v RosettaMempoolApi_ +type RosettaNetworkListApi v = RosettaApiEndpoint v RosettaNetworkListApi_ +type RosettaNetworkOptionsApi v = RosettaApiEndpoint v RosettaNetworkOptionsApi_ +type RosettaNetworkStatusApi v = RosettaApiEndpoint v RosettaNetworkStatusApi_ + +type RosettaAccountBalanceApi_ + = "account" + :> "balance" + :> ReqBody '[JSON] AccountBalanceReq + :> Post '[JSON] AccountBalanceResp + +type RosettaBlockTransactionApi_ + = "block" + :> "transaction" + :> ReqBody '[JSON] BlockTransactionReq + :> Post '[JSON] BlockTransactionResp + +type RosettaBlockApi_ + = "block" + :> ReqBody '[JSON] BlockReq + :> Post '[JSON] BlockResp + +type RosettaConstructionMetadataApi_ + = "construction" + :> "metadata" + :> ReqBody '[JSON] ConstructionMetadataReq + :> Post '[JSON] ConstructionMetadataResp + +type RosettaConstructionSubmitApi_ + = "construction" + :> "submit" + :> ReqBody '[JSON] ConstructionSubmitReq + :> Post '[JSON] ConstructionSubmitResp + +type RosettaMempoolTransactionApi_ + = "mempool" + :> "transaction" + :> ReqBody '[JSON] MempoolTransactionReq + :> Post '[JSON] MempoolTransactionResp + +type RosettaMempoolApi_ + = "mempool" + :> ReqBody '[JSON] MempoolReq + :> Post '[JSON] MempoolResp + +type RosettaNetworkListApi_ + = "network" + :> "list" + :> ReqBody '[JSON] MetadataReq + :> Post '[JSON] NetworkListResp + + +type RosettaNetworkOptionsApi_ + = "network" + :> "options" + :> ReqBody '[JSON] NetworkReq + :> Post '[JSON] NetworkOptionsResp + +type RosettaNetworkStatusApi_ + = "network" + :> "status" + :> ReqBody '[JSON] NetworkReq + :> Post '[JSON] NetworkStatusResp + +rosettaAccountBalanceApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaAccountBalanceApi v) +rosettaAccountBalanceApi = Proxy + +rosettaBlockTransactionApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaBlockTransactionApi v) +rosettaBlockTransactionApi = Proxy + +rosettaBlockApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaBlockApi v) +rosettaBlockApi = Proxy + +rosettaConstructionMetadataApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaConstructionMetadataApi v) +rosettaConstructionMetadataApi = Proxy + +rosettaConstructionSubmitApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaConstructionSubmitApi v) +rosettaConstructionSubmitApi = Proxy + +rosettaMempoolTransactionApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaMempoolTransactionApi v) +rosettaMempoolTransactionApi = Proxy + +rosettaMempoolApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaMempoolApi v) +rosettaMempoolApi = Proxy + +rosettaNetworkListApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaNetworkListApi v) +rosettaNetworkListApi = Proxy + +rosettaNetworkOptionsApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaNetworkOptionsApi v) +rosettaNetworkOptionsApi = Proxy + +rosettaNetworkStatusApi + :: forall (v :: ChainwebVersionT) + . Proxy (RosettaNetworkStatusApi v) +rosettaNetworkStatusApi = Proxy + +-- ------------------------------------------------------------------ -- +-- Rosetta Exceptions + -- TODO: Investigate if Rosetta Erros can be dynamic data RosettaFailure = RosettaChainUnspecified @@ -129,4 +269,3 @@ readChainIdText :: ChainwebVersion -> T.Text -> Maybe ChainId readChainIdText v c = do cid <- readMaybe @Word (T.unpack c) mkChainId v maxBound cid - diff --git a/src/Chainweb/Rosetta/RestAPI/Client.hs b/src/Chainweb/Rosetta/RestAPI/Client.hs new file mode 100644 index 0000000000..b744c8681b --- /dev/null +++ b/src/Chainweb/Rosetta/RestAPI/Client.hs @@ -0,0 +1,235 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE RankNTypes #-} +-- | +-- Module: Chainweb.Rosetta.RestAPI.Client +-- Copyright: Copyright © 2018 - 2020 Kadena LLC. +-- License: MIT +-- Maintainer: Emily Pillmore +-- Stability: experimental +-- +-- This module defines the client API for the Chainweb Rosetta +-- integration. +-- +module Chainweb.Rosetta.RestAPI.Client +( -- * AccounT Endpoints + rosettaAccountBalanceApiClient + -- * Block Endpoints +, rosettaBlockTransactionApiClient +, rosettaBlockApiClient + -- * Construction Endpoints +, rosettaConstructionMetadataApiClient +, rosettaConstructionSubmitApiClient + -- * Mempool Endpoints +, rosettaMempoolApiClient +, rosettaMempoolTransactionApiClient + -- * Network Endpoints +, rosettaNetworkListApiClient +, rosettaNetworkOptionsApiClient +, rosettaNetworkStatusApiClient +) +where + + +import Rosetta + +import Servant.Client + +-- internal chainweb modules + +import Chainweb.ChainId +import Chainweb.Rosetta.RestAPI +import Chainweb.Version + + +-- -------------------------------------------------------------------------- -- +-- Accounts Endpoints + +rosettaAccountBalanceApiClient_ + :: forall (v :: ChainwebVersionT) + . KnownChainwebVersionSymbol v + => AccountBalanceReq + -- ^ Contains a network id, account id, and a partial block identifier + -- which is not populated. + -> ClientM AccountBalanceResp +rosettaAccountBalanceApiClient_ = client (rosettaAccountBalanceApi @v) + +rosettaAccountBalanceApiClient + :: ChainwebVersion + -> AccountBalanceReq + -- ^ Contains a network id, account id, and a partial block identifier + -- which is not populated. + -> ClientM AccountBalanceResp +rosettaAccountBalanceApiClient + (FromSingChainwebVersion (SChainwebVersion :: Sing v)) + = rosettaAccountBalanceApiClient_ @v + +-- -------------------------------------------------------------------------- -- +-- Block Endpoints + +rosettaBlockTransactionApiClient_ + :: forall (v :: ChainwebVersionT) + . KnownChainwebVersionSymbol v + => BlockTransactionReq + -- ^ Contains a network id, a block id, and a transaction id + -> ClientM BlockTransactionResp +rosettaBlockTransactionApiClient_ = client (rosettaBlockTransactionApi @v) + +rosettaBlockTransactionApiClient + :: ChainwebVersion + -> BlockTransactionReq + -- ^ Contains a network id, a block id, and a transaction id + -> ClientM BlockTransactionResp +rosettaBlockTransactionApiClient + (FromSingChainwebVersion (SChainwebVersion :: Sing v)) + = rosettaBlockTransactionApiClient_ @v + +rosettaBlockApiClient_ + :: forall (v :: ChainwebVersionT) + . KnownChainwebVersionSymbol v + => BlockReq + -- ^ Contains a network id and a partial block id + -> ClientM BlockResp +rosettaBlockApiClient_ = client (rosettaBlockApi @v) + +rosettaBlockApiClient + :: ChainwebVersion + -> BlockReq + -- ^ Contains a network id and a partial block id + -> ClientM BlockResp +rosettaBlockApiClient + (FromSingChainwebVersion (SChainwebVersion :: Sing v)) + = rosettaBlockApiClient_ @v + +-- -------------------------------------------------------------------------- -- +-- Construction Endpoints + +rosettaConstructionMetadataApiClient_ + :: forall (v :: ChainwebVersionT) + . KnownChainwebVersionSymbol v + => ConstructionMetadataReq + -- ^ contains a network id and a metadata object which specifies the + -- metadata to return. + -> ClientM ConstructionMetadataResp +rosettaConstructionMetadataApiClient_ = client (rosettaConstructionMetadataApi @v) + +rosettaConstructionMetadataApiClient + :: ChainwebVersion + -> ConstructionMetadataReq + -- ^ contains a network id and a metadata object which specifies the + -- metadata to return. + -> ClientM ConstructionMetadataResp +rosettaConstructionMetadataApiClient + (FromSingChainwebVersion (SChainwebVersion :: Sing v)) + = rosettaConstructionMetadataApiClient_ @v + +rosettaConstructionSubmitApiClient_ + :: forall (v :: ChainwebVersionT) + . KnownChainwebVersionSymbol v + => ConstructionSubmitReq + -- ^ Contains a network id and a signed transaction + -> ClientM ConstructionSubmitResp +rosettaConstructionSubmitApiClient_ = client (rosettaConstructionSubmitApi @v) + +rosettaConstructionSubmitApiClient + :: ChainwebVersion + -> ConstructionSubmitReq + -- ^ Contains a network id and a signed transaction + -> ClientM ConstructionSubmitResp +rosettaConstructionSubmitApiClient + (FromSingChainwebVersion (SChainwebVersion :: Sing v)) + = rosettaConstructionSubmitApiClient_ @v + +-- -------------------------------------------------------------------------- -- +-- Mempool Endpoints + +rosettaMempoolTransactionApiClient_ + :: forall (v :: ChainwebVersionT) + . KnownChainwebVersionSymbol v + => MempoolTransactionReq + -- ^ Contains a network id and a transaction id + -> ClientM MempoolTransactionResp +rosettaMempoolTransactionApiClient_ = client (rosettaMempoolTransactionApi @v) + +rosettaMempoolTransactionApiClient + :: ChainwebVersion + -> MempoolTransactionReq + -- ^ Contains a network id and a transaction id + -> ClientM MempoolTransactionResp +rosettaMempoolTransactionApiClient + (FromSingChainwebVersion (SChainwebVersion :: Sing v)) + = rosettaMempoolTransactionApiClient_ @v + +rosettaMempoolApiClient_ + :: forall (v :: ChainwebVersionT) + . KnownChainwebVersionSymbol v + => MempoolReq + -- ^ contains a network id + -> ClientM MempoolResp +rosettaMempoolApiClient_ = client (rosettaMempoolApi @v) + +rosettaMempoolApiClient + :: ChainwebVersion + -> MempoolReq + -- ^ contains a network id + -> ClientM MempoolResp +rosettaMempoolApiClient + (FromSingChainwebVersion (SChainwebVersion :: Sing v)) + = rosettaMempoolApiClient_ @v + +-- -------------------------------------------------------------------------- -- +-- Network Endpoints + +rosettaNetworkListApiClient_ + :: forall (v :: ChainwebVersionT) + . KnownChainwebVersionSymbol v + => MetadataReq + -- ^ Contains an optional object with metadata + -> ClientM NetworkListResp +rosettaNetworkListApiClient_ = client (rosettaNetworkListApi @v) + +rosettaNetworkListApiClient + :: ChainwebVersion + -> MetadataReq + -- ^ Contains an optional object with metadata + -> ClientM NetworkListResp +rosettaNetworkListApiClient + (FromSingChainwebVersion (SChainwebVersion :: Sing v)) + = rosettaNetworkListApiClient_ @v + +rosettaNetworkOptionsApiClient_ + :: forall (v :: ChainwebVersionT) + . KnownChainwebVersionSymbol v + => NetworkReq + -- ^ Contains a network identifier and optional object with metadata + -> ClientM NetworkOptionsResp +rosettaNetworkOptionsApiClient_ = client (rosettaNetworkOptionsApi @v) + +rosettaNetworkOptionsApiClient + :: ChainwebVersion + -> NetworkReq + -- ^ Contains a network identifier and optional object with metadata + -> ClientM NetworkOptionsResp +rosettaNetworkOptionsApiClient + (FromSingChainwebVersion (SChainwebVersion :: Sing v)) + = rosettaNetworkOptionsApiClient_ @v + +rosettaNetworkStatusApiClient_ + :: forall (v :: ChainwebVersionT) + . KnownChainwebVersionSymbol v + => NetworkReq + -- ^ Contains a network identifier and optional object with metadata + -> ClientM NetworkStatusResp +rosettaNetworkStatusApiClient_ = client (rosettaNetworkStatusApi @v) + +rosettaNetworkStatusApiClient + :: ChainwebVersion + -> NetworkReq + -- ^ Contains a network identifier and optional object with metadata + -> ClientM NetworkStatusResp +rosettaNetworkStatusApiClient + (FromSingChainwebVersion (SChainwebVersion :: Sing v)) + = rosettaNetworkStatusApiClient_ @v diff --git a/test/Chainweb/Test/Rosetta.hs b/test/Chainweb/Test/Rosetta.hs index afe402a9ad..c5c0d422a1 100644 --- a/test/Chainweb/Test/Rosetta.hs +++ b/test/Chainweb/Test/Rosetta.hs @@ -8,9 +8,10 @@ import Test.Tasty import Test.Tasty.HUnit import Chainweb.Graph +import Chainweb.Rosetta.RestAPI.Client +import Chainweb.Test.Utils import Chainweb.Time (Time(..), Micros(..)) import Chainweb.Version -import Chainweb.Test.Utils import Data.CAS.RocksDB @@ -25,7 +26,23 @@ v = FastTimedCPM petersonChainGraph nodes:: Natural nodes = 1 -type RosettaTest = IO (Time Micros) -> IO ChainwebNetwork -> TestTree +type RosettaTest = IO Time Micros -> IO ChainwebNetwork -> TestTree + +data RosettaTestException + = AccountBalanceFailure String + | BlockTransactionFailure String + | BlockFailure String + | ConstructionMetadataFailure String + | ConstructionSubmitFailure String + | MempoolTransactionFailure String + | MempoolFailure String + | NetworkListFailure String + | NetworkOptionsFailure String + | NetworkStatusFailure String + deriving Show + +instance Exception RosettaTestException + nid :: NetworkId nid = NetworkId @@ -49,9 +66,9 @@ tests rdb = testGroupSch "Chainweb.Test.Rosetta" go where go = return $ withNodes v "rosettaRemoteTests-" rdb nodes $ \nio -> - withTime $ \tio -> tgrp nio tio + withTime $ \tio -> tgroup nio tio - tgrp nio tio + tgroup nio tio = testGroup "Rosetta API tests" $ fmap (\test -> test tio nio) tests_ @@ -69,11 +86,11 @@ tests rdb = testGroupSch "Chainweb.Test.Rosetta" go accountBalanceTests :: RosettaTest -accountBalanceTests _tio _nio = testCaseSteps "Account Balance Lookup" $ \ _step -> do - _cenv <- _runClientEnv <$> _nio +accountBalanceTests _tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> do + ccenv <- _runClientEnv <$> _nio return () where - _req = AccountBalanceReq nid aid Nothing + req = AccountBalanceReq nid aid Nothing blockTransactionTests :: RosettaTest blockTransactionTests _tio _nio = undefined @@ -98,3 +115,186 @@ networkOptionsTests _tio _nio = undefined networkStatusTests :: RosettaTest networkStatusTests _tio _nio = undefined + +-- ------------------------------------------------------------------ -- +-- Rosetta api w/ retry + +accountBalance + :: ClientEnv + -> AccountBalanceReq + -> IO AccountBalanceResp +accountBalance cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting account balance for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaAccountBalanceApiClient v cmd) cenv >>= \case + Left e -> throwM $ AccountBalanceFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + AccountBalanceFailure _ -> return True + _ -> return False + +blockTransaction + :: ClientEnv + -> BlockTransactionReq + -> IO BlockTransactionResp +blockTransaction cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting block transaction for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaBlockTransactionApiClient v cmd) cenv >>= \case + Left e -> throwM $ BlockTransactionFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + BlockTransactionFailure _ -> return True + _ -> return False + +block + :: ClientEnv + -> BlockReq + -> IO BlockResp +block cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting block for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaBlockApiClient v cmd) cenv >>= \case + Left e -> throwM $ BlockFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + BlockFailure _ -> return True + _ -> return False + +constructionMetadata + :: ClientEnv + -> ConstructionMetadataReq + -> IO ConstructionMetadataResp +constructionMetadata cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting construction metadata for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaConstructionMetadataApiClient v cmd) cenv >>= \case + Left e -> throwM $ ConstructionMetadataFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + ConstructionMetadataFailure _ -> return True + _ -> return False + +constructionSubmit + :: ClientEnv + -> ConstructionSubmitReq + -> IO ConstructionSubmitResp +constructionSubmit cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting construction submit for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaConstructionSubmitApiClient v cmd) cenv >>= \case + Left e -> throwM $ ConstructionSubmitFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + ConstructionSubmitFailure _ -> return True + _ -> return False + +mempoolTransaction + :: ClientEnv + -> MempoolTransactionReq + -> IO MempoolTransactionResp +mempoolTransaction cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting mempool transaction for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaMempoolTransactionApiClient v cmd) cenv >>= \case + Left e -> throwM $ MempoolTransactionFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + MempoolTransactionFailure _ -> return True + _ -> return False + +mempool + :: ClientEnv + -> MempoolReq + -> IO MempoolResp +mempool cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting mempool for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaMempoolTransctionApiClient v cmd) cenv >>= \case + Left e -> throwM $ MempoolFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + MempoolFailure _ -> return True + _ -> return False + +networkList + :: ClientEnv + -> NetworkListReq + -> IO NetworkListResp +networkList cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting network list for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaNetworkListApiClient v cmd) cenv >>= \case + Left e -> throwM $ NetworkListFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + NetworkListFailure _ -> return True + _ -> return False + +networkOptions + :: ClientEnv + -> NetworkOptionsReq + -> IO NetworkOptionsResp +networkOptions cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting network options for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaNetworkOptionsApiClient v cmd) cenv >>= \case + Left e -> throwM $ NetworkOptionsFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + NetworkOptionsFailure _ -> return True + _ -> return False + +networkStatus + :: ClientEnv + -> NetworkStatusReq + -> IO NetworkStatusResp +networkStatus cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting network status for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaNetworkStatusApiClient v cmd) cenv >>= \case + Left e -> throwM $ NetworkStatusFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + NetworkStatusFailure _ -> return True + _ -> return False From c13b9ba52d0324a2633fc2eef70cae3530361a43 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Wed, 17 Jun 2020 23:09:46 -0400 Subject: [PATCH 04/48] she compiles --- cabal.project | 2 +- dep/kpkgs/github.json | 4 +-- stack.yaml | 2 +- test/Chainweb/Test/Rosetta.hs | 58 ++++++++++++++++++++++++++--------- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/cabal.project b/cabal.project index 7ad8ebd8eb..a4a23751be 100644 --- a/cabal.project +++ b/cabal.project @@ -26,7 +26,7 @@ source-repository-package source-repository-package type: git location: https://github.com/kadena-io/rosetta.git - tag: d20b0012c6f5e1d28843b89a4edd5ea652ade0c3 + tag: 1ccb68d7aec0414f494fb06f591214e7cf845627 package vault documentation: false diff --git a/dep/kpkgs/github.json b/dep/kpkgs/github.json index 185d2680fc..f0c994f7ec 100644 --- a/dep/kpkgs/github.json +++ b/dep/kpkgs/github.json @@ -3,6 +3,6 @@ "repo": "kpkgs", "branch": "master", "private": false, - "rev": "83fa7c35e9f16c0696b683e3e28cc7915689513a", - "sha256": "1yzidbhdbp0xr5rvfqgypk6zkz9cn5zlzlzh6fhb6hdgmlb672nh" + "rev": "89f9f7496c449e5c4a69e2e07eeff33ad5280250", + "sha256": "080swlsz2b6782yx0i8ixynsyj776y9qgi6rs5m7rcr983q8ng57" } diff --git a/stack.yaml b/stack.yaml index fc5cf48e2d..e15c771ceb 100644 --- a/stack.yaml +++ b/stack.yaml @@ -41,4 +41,4 @@ extra-deps: - github: kadena-io/chainweb-storage commit: 07e7eb7596c7105aee42dbdb6edd10e3f23c0d7e - github: kadena-io/rosetta - commit: d20b0012c6f5e1d28843b89a4edd5ea652ade0c3 + commit: 1ccb68d7aec0414f494fb06f591214e7cf845627 diff --git a/test/Chainweb/Test/Rosetta.hs b/test/Chainweb/Test/Rosetta.hs index c5c0d422a1..513bb47872 100644 --- a/test/Chainweb/Test/Rosetta.hs +++ b/test/Chainweb/Test/Rosetta.hs @@ -1,9 +1,20 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} -module Chainweb.Test.Rosetta where +module Chainweb.Test.Rosetta +( tests +) where +import Control.Lens +import Control.Monad.Catch +import Control.Retry + import GHC.Natural +import Servant.Client + import Test.Tasty import Test.Tasty.HUnit @@ -20,13 +31,30 @@ import Rosetta -- -------------------------------------------------------------------------- -- -- Global Settings + +debug :: String -> IO () +#if DEBUG_TEST +debug = putStrLn +#else +debug = const $ return () +#endif + +testRetryPolicy :: RetryPolicy +testRetryPolicy = stepped <> limitRetries 150 + where + stepped = retryPolicy $ \rs -> case rsIterNumber rs of + 0 -> Just 20_000 + 1 -> Just 50_000 + 2 -> Just 100_000 + _ -> Just 250_000 + v :: ChainwebVersion v = FastTimedCPM petersonChainGraph nodes:: Natural nodes = 1 -type RosettaTest = IO Time Micros -> IO ChainwebNetwork -> TestTree +type RosettaTest = IO (Time Micros) -> IO ChainwebNetwork -> TestTree data RosettaTestException = AccountBalanceFailure String @@ -129,7 +157,7 @@ accountBalance cenv req = $ "requesting account balance for " <> (take 18 $ show req) <> " [" <> show (view rsIterNumberL s) <> "]" - runClientM (rosettaAccountBalanceApiClient v cmd) cenv >>= \case + runClientM (rosettaAccountBalanceApiClient v req) cenv >>= \case Left e -> throwM $ AccountBalanceFailure (show e) Right t -> return t where @@ -147,7 +175,7 @@ blockTransaction cenv req = $ "requesting block transaction for " <> (take 18 $ show req) <> " [" <> show (view rsIterNumberL s) <> "]" - runClientM (rosettaBlockTransactionApiClient v cmd) cenv >>= \case + runClientM (rosettaBlockTransactionApiClient v req) cenv >>= \case Left e -> throwM $ BlockTransactionFailure (show e) Right t -> return t where @@ -165,7 +193,7 @@ block cenv req = $ "requesting block for " <> (take 18 $ show req) <> " [" <> show (view rsIterNumberL s) <> "]" - runClientM (rosettaBlockApiClient v cmd) cenv >>= \case + runClientM (rosettaBlockApiClient v req) cenv >>= \case Left e -> throwM $ BlockFailure (show e) Right t -> return t where @@ -183,7 +211,7 @@ constructionMetadata cenv req = $ "requesting construction metadata for " <> (take 18 $ show req) <> " [" <> show (view rsIterNumberL s) <> "]" - runClientM (rosettaConstructionMetadataApiClient v cmd) cenv >>= \case + runClientM (rosettaConstructionMetadataApiClient v req) cenv >>= \case Left e -> throwM $ ConstructionMetadataFailure (show e) Right t -> return t where @@ -201,7 +229,7 @@ constructionSubmit cenv req = $ "requesting construction submit for " <> (take 18 $ show req) <> " [" <> show (view rsIterNumberL s) <> "]" - runClientM (rosettaConstructionSubmitApiClient v cmd) cenv >>= \case + runClientM (rosettaConstructionSubmitApiClient v req) cenv >>= \case Left e -> throwM $ ConstructionSubmitFailure (show e) Right t -> return t where @@ -219,7 +247,7 @@ mempoolTransaction cenv req = $ "requesting mempool transaction for " <> (take 18 $ show req) <> " [" <> show (view rsIterNumberL s) <> "]" - runClientM (rosettaMempoolTransactionApiClient v cmd) cenv >>= \case + runClientM (rosettaMempoolTransactionApiClient v req) cenv >>= \case Left e -> throwM $ MempoolTransactionFailure (show e) Right t -> return t where @@ -237,7 +265,7 @@ mempool cenv req = $ "requesting mempool for " <> (take 18 $ show req) <> " [" <> show (view rsIterNumberL s) <> "]" - runClientM (rosettaMempoolTransctionApiClient v cmd) cenv >>= \case + runClientM (rosettaMempoolApiClient v req) cenv >>= \case Left e -> throwM $ MempoolFailure (show e) Right t -> return t where @@ -247,7 +275,7 @@ mempool cenv req = networkList :: ClientEnv - -> NetworkListReq + -> MetadataReq -> IO NetworkListResp networkList cenv req = recovering testRetryPolicy [h] $ \s -> do @@ -255,7 +283,7 @@ networkList cenv req = $ "requesting network list for " <> (take 18 $ show req) <> " [" <> show (view rsIterNumberL s) <> "]" - runClientM (rosettaNetworkListApiClient v cmd) cenv >>= \case + runClientM (rosettaNetworkListApiClient v req) cenv >>= \case Left e -> throwM $ NetworkListFailure (show e) Right t -> return t where @@ -265,7 +293,7 @@ networkList cenv req = networkOptions :: ClientEnv - -> NetworkOptionsReq + -> NetworkReq -> IO NetworkOptionsResp networkOptions cenv req = recovering testRetryPolicy [h] $ \s -> do @@ -273,7 +301,7 @@ networkOptions cenv req = $ "requesting network options for " <> (take 18 $ show req) <> " [" <> show (view rsIterNumberL s) <> "]" - runClientM (rosettaNetworkOptionsApiClient v cmd) cenv >>= \case + runClientM (rosettaNetworkOptionsApiClient v req) cenv >>= \case Left e -> throwM $ NetworkOptionsFailure (show e) Right t -> return t where @@ -283,7 +311,7 @@ networkOptions cenv req = networkStatus :: ClientEnv - -> NetworkStatusReq + -> NetworkReq -> IO NetworkStatusResp networkStatus cenv req = recovering testRetryPolicy [h] $ \s -> do @@ -291,7 +319,7 @@ networkStatus cenv req = $ "requesting network status for " <> (take 18 $ show req) <> " [" <> show (view rsIterNumberL s) <> "]" - runClientM (rosettaNetworkStatusApiClient v cmd) cenv >>= \case + runClientM (rosettaNetworkStatusApiClient v req) cenv >>= \case Left e -> throwM $ NetworkStatusFailure (show e) Right t -> return t where From 955791a15b0c08b08885a4d0d7f9711b8cd6ac05 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 18 Jun 2020 15:58:12 -0400 Subject: [PATCH 05/48] merge maseter --- chainweb.cabal | 3 +- test/Chainweb/Test/Pact/RemotePactTest.hs | 2 +- test/Chainweb/Test/Rosetta.hs | 342 +--------------------- test/Chainweb/Test/Rosetta/RestAPI.hs | 328 +++++++++++++++++++++ 4 files changed, 336 insertions(+), 339 deletions(-) create mode 100644 test/Chainweb/Test/Rosetta/RestAPI.hs diff --git a/chainweb.cabal b/chainweb.cabal index 4fa25eef90..6220613754 100644 --- a/chainweb.cabal +++ b/chainweb.cabal @@ -85,7 +85,7 @@ common debugging-flags common warning-flags ghc-options: -Wall - -Werror + -- -Werror -Wcompat -Wpartial-fields -Wincomplete-record-updates @@ -467,6 +467,7 @@ test-suite chainweb-tests Chainweb.Test.RestAPI Chainweb.Test.RestAPI.Client_ Chainweb.Test.Rosetta + Chainweb.Test.Rosetta.RestAPI Chainweb.Test.Roundtrips Chainweb.Test.SPV Chainweb.Test.Store.CAS diff --git a/test/Chainweb/Test/Pact/RemotePactTest.hs b/test/Chainweb/Test/Pact/RemotePactTest.hs index ee312d06d6..3c417b85c1 100644 --- a/test/Chainweb/Test/Pact/RemotePactTest.hs +++ b/test/Chainweb/Test/Pact/RemotePactTest.hs @@ -199,7 +199,7 @@ localTest iot nio = do localContTest :: IO (Time Micros) -> IO ChainwebNetwork -> TestTree localContTest iot nio = testCaseSteps "local continuation test" $ \step -> do - cenv <- _getClientEnv <$> nio + cenv <- _runClientEnv <$> nio let sid = unsafeChainId 0 step "execute /send with initial pact continuation tx" diff --git a/test/Chainweb/Test/Rosetta.hs b/test/Chainweb/Test/Rosetta.hs index 0db4ee9e40..db8749f5da 100644 --- a/test/Chainweb/Test/Rosetta.hs +++ b/test/Chainweb/Test/Rosetta.hs @@ -1,334 +1,3 @@ -<<<<<<< HEAD -{-# LANGUAGE CPP #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE NumericUnderscores #-} -{-# LANGUAGE OverloadedStrings #-} -module Chainweb.Test.Rosetta -( tests -) where - - -import Control.Lens -import Control.Monad.Catch -import Control.Retry - -import GHC.Natural - -import Servant.Client - -import Test.Tasty -import Test.Tasty.HUnit - -import Chainweb.Graph -import Chainweb.Rosetta.RestAPI.Client -import Chainweb.Test.Utils -import Chainweb.Time (Time(..), Micros(..)) -import Chainweb.Version - -import Data.CAS.RocksDB - -import Rosetta - --- -------------------------------------------------------------------------- -- --- Global Settings - - -debug :: String -> IO () -#if DEBUG_TEST -debug = putStrLn -#else -debug = const $ return () -#endif - -testRetryPolicy :: RetryPolicy -testRetryPolicy = stepped <> limitRetries 150 - where - stepped = retryPolicy $ \rs -> case rsIterNumber rs of - 0 -> Just 20_000 - 1 -> Just 50_000 - 2 -> Just 100_000 - _ -> Just 250_000 - -v :: ChainwebVersion -v = FastTimedCPM petersonChainGraph - -nodes:: Natural -nodes = 1 - -type RosettaTest = IO (Time Micros) -> IO ChainwebNetwork -> TestTree - -data RosettaTestException - = AccountBalanceFailure String - | BlockTransactionFailure String - | BlockFailure String - | ConstructionMetadataFailure String - | ConstructionSubmitFailure String - | MempoolTransactionFailure String - | MempoolFailure String - | NetworkListFailure String - | NetworkOptionsFailure String - | NetworkStatusFailure String - deriving Show - -instance Exception RosettaTestException - - -nid :: NetworkId -nid = NetworkId - { _networkId_blockchain = undefined - , _networkId_network = "fastTimedCPM" - , _networkId_subNetworkId = undefined - } - -aid :: AccountId -aid = AccountId - { _accountId_address = "sender00" - , _accountId_subAccount = Nothing - , _accountId_metadata = undefined - } - --- -------------------------------------------------------------------------- -- --- Test Tree - -tests :: RocksDb -> ScheduledTest -tests rdb = testGroupSch "Chainweb.Test.Rosetta" go - where - go = return $ - withNodes v "rosettaRemoteTests-" rdb nodes $ \nio -> - withTime $ \tio -> tgroup nio tio - - tgroup nio tio - = testGroup "Rosetta API tests" - $ fmap (\test -> test tio nio) tests_ - - tests_ = - [ accountBalanceTests - , blockTransactionTests - , blockTests - , constructionMetadataTests - , constructionSubmitTests - , mempoolTransactionTests - , networkListTests - , networkOptionsTests - , networkStatusTests - ] - - -accountBalanceTests :: RosettaTest -accountBalanceTests _tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> do - ccenv <- _runClientEnv <$> _nio - return () - where - req = AccountBalanceReq nid aid Nothing - -blockTransactionTests :: RosettaTest -blockTransactionTests _tio _nio = undefined - -blockTests :: RosettaTest -blockTests _tio _nio = undefined - -constructionMetadataTests :: RosettaTest -constructionMetadataTests _tio _nio = undefined - -constructionSubmitTests :: RosettaTest -constructionSubmitTests _tio _nio = undefined - -mempoolTransactionTests :: RosettaTest -mempoolTransactionTests _tio _nio = undefined - -networkListTests :: RosettaTest -networkListTests _tio _nio = undefined - -networkOptionsTests :: RosettaTest -networkOptionsTests _tio _nio = undefined - -networkStatusTests :: RosettaTest -networkStatusTests _tio _nio = undefined - --- ------------------------------------------------------------------ -- --- Rosetta api w/ retry - -accountBalance - :: ClientEnv - -> AccountBalanceReq - -> IO AccountBalanceResp -accountBalance cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting account balance for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaAccountBalanceApiClient v req) cenv >>= \case - Left e -> throwM $ AccountBalanceFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - AccountBalanceFailure _ -> return True - _ -> return False - -blockTransaction - :: ClientEnv - -> BlockTransactionReq - -> IO BlockTransactionResp -blockTransaction cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting block transaction for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaBlockTransactionApiClient v req) cenv >>= \case - Left e -> throwM $ BlockTransactionFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - BlockTransactionFailure _ -> return True - _ -> return False - -block - :: ClientEnv - -> BlockReq - -> IO BlockResp -block cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting block for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaBlockApiClient v req) cenv >>= \case - Left e -> throwM $ BlockFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - BlockFailure _ -> return True - _ -> return False - -constructionMetadata - :: ClientEnv - -> ConstructionMetadataReq - -> IO ConstructionMetadataResp -constructionMetadata cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting construction metadata for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaConstructionMetadataApiClient v req) cenv >>= \case - Left e -> throwM $ ConstructionMetadataFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - ConstructionMetadataFailure _ -> return True - _ -> return False - -constructionSubmit - :: ClientEnv - -> ConstructionSubmitReq - -> IO ConstructionSubmitResp -constructionSubmit cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting construction submit for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaConstructionSubmitApiClient v req) cenv >>= \case - Left e -> throwM $ ConstructionSubmitFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - ConstructionSubmitFailure _ -> return True - _ -> return False - -mempoolTransaction - :: ClientEnv - -> MempoolTransactionReq - -> IO MempoolTransactionResp -mempoolTransaction cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting mempool transaction for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaMempoolTransactionApiClient v req) cenv >>= \case - Left e -> throwM $ MempoolTransactionFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - MempoolTransactionFailure _ -> return True - _ -> return False - -mempool - :: ClientEnv - -> MempoolReq - -> IO MempoolResp -mempool cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting mempool for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaMempoolApiClient v req) cenv >>= \case - Left e -> throwM $ MempoolFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - MempoolFailure _ -> return True - _ -> return False - -networkList - :: ClientEnv - -> MetadataReq - -> IO NetworkListResp -networkList cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting network list for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaNetworkListApiClient v req) cenv >>= \case - Left e -> throwM $ NetworkListFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - NetworkListFailure _ -> return True - _ -> return False - -networkOptions - :: ClientEnv - -> NetworkReq - -> IO NetworkOptionsResp -networkOptions cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting network options for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaNetworkOptionsApiClient v req) cenv >>= \case - Left e -> throwM $ NetworkOptionsFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - NetworkOptionsFailure _ -> return True - _ -> return False - -networkStatus - :: ClientEnv - -> NetworkReq - -> IO NetworkStatusResp -networkStatus cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting network status for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaNetworkStatusApiClient v req) cenv >>= \case - Left e -> throwM $ NetworkStatusFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - NetworkStatusFailure _ -> return True - _ -> return False -||||||| merged common ancestors -======= {-# LANGUAGE OverloadedStrings #-} -- | @@ -403,7 +72,7 @@ matchNonGenesisBlockTransactionsToLogs = do -- Coinbase Tx expected1 = mockRosettaTx "ReqKey1" [ op CoinbaseReward 1 "miner1" 2.0 0] - + -- Successful, non-coin contract tx expected2 = mockRosettaTx "ReqKey2" [ op FundTx 2 "sender1" 10.0 0 @@ -438,7 +107,7 @@ matchFailedCoinbaseBlockTransactionsToLogs = do -- Coinbase Tx expected1 = mockRosettaTx "ReqKey1" [] - + -- Successful, non-coin contract tx expected2 = mockRosettaTx "ReqKey2" [ op FundTx 2 "sender1" 10.0 0 @@ -466,7 +135,7 @@ matchNonGenesisSingleTransactionsToLogs = do Right missingRk' <- pure missingRk assertEqual "request key not present" missingRk' expectedMissing - + where run :: T.Text -> Either String (Maybe Transaction) run t = nonGenesisTransaction logs initial rest (textToRk t) @@ -478,7 +147,7 @@ matchNonGenesisSingleTransactionsToLogs = do -- Coinbase Tx expectedRk1 = Just $ mockRosettaTx "ReqKey1" [ op CoinbaseReward 1 "miner1" 2.0 0] - + -- Successful, non-coin contract tx expectedRk2 = Just $ mockRosettaTx "ReqKey2" [ op FundTx 2 "sender1" 10.0 0 @@ -545,7 +214,7 @@ checkValidateNetwork = do where run :: (ChainwebVersion, NetworkId) -> Either RosettaFailure T.Text run (v,net) = runExceptT (validateNetwork v net) >>= either Left (pure . chainIdToText) - + validNetId = (Development, NetworkId { _networkId_blockchain = "kadena" , _networkId_network = "development" @@ -695,4 +364,3 @@ mockRosettaTx mrk ops = textToRk :: T.Text -> RequestKey textToRk = RequestKey . Hash . T.encodeUtf8 ->>>>>>> master diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs new file mode 100644 index 0000000000..8786905f12 --- /dev/null +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -0,0 +1,328 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NumericUnderscores #-} +{-# LANGUAGE OverloadedStrings #-} +module Chainweb.Test.Rosetta.RestAPI +( tests +) where + + +import Control.Lens +import Control.Monad.Catch +import Control.Retry + +import GHC.Natural + +import Servant.Client + +import Test.Tasty +import Test.Tasty.HUnit + +import Chainweb.Graph +import Chainweb.Rosetta.RestAPI.Client +import Chainweb.Test.Utils +import Chainweb.Time (Time(..), Micros(..)) +import Chainweb.Version + +import Data.CAS.RocksDB + +import Rosetta + + +-- -------------------------------------------------------------------------- -- +-- Global Settings + +debug :: String -> IO () +#if DEBUG_TEST +debug = putStrLn +#else +debug = const $ return () +#endif + +testRetryPolicy :: RetryPolicy +testRetryPolicy = stepped <> limitRetries 150 + where + stepped = retryPolicy $ \rs -> case rsIterNumber rs of + 0 -> Just 20_000 + 1 -> Just 50_000 + 2 -> Just 100_000 + _ -> Just 250_000 + +v :: ChainwebVersion +v = FastTimedCPM petersonChainGraph + +nodes:: Natural +nodes = 1 + +type RosettaTest = IO (Time Micros) -> IO ChainwebNetwork -> TestTree + +data RosettaTestException + = AccountBalanceFailure String + | BlockTransactionFailure String + | BlockFailure String + | ConstructionMetadataFailure String + | ConstructionSubmitFailure String + | MempoolTransactionFailure String + | MempoolFailure String + | NetworkListFailure String + | NetworkOptionsFailure String + | NetworkStatusFailure String + deriving Show + +instance Exception RosettaTestException + + +nid :: NetworkId +nid = NetworkId + { _networkId_blockchain = undefined + , _networkId_network = "fastTimedCPM" + , _networkId_subNetworkId = undefined + } + +aid :: AccountId +aid = AccountId + { _accountId_address = "sender00" + , _accountId_subAccount = Nothing + , _accountId_metadata = undefined + } + +-- -------------------------------------------------------------------------- -- +-- Test Tree + +tests :: RocksDb -> ScheduledTest +tests rdb = testGroupSch "Chainweb.Test.Rosetta" go + where + go = return $ + withNodes v "rosettaRemoteTests-" rdb nodes $ \nio -> + withTime $ \tio -> tgroup nio tio + + tgroup nio tio + = testGroup "Rosetta API tests" + $ fmap (\test -> test tio nio) tests_ + + tests_ = + [ accountBalanceTests + , blockTransactionTests + , blockTests + , constructionMetadataTests + , constructionSubmitTests + , mempoolTransactionTests + , networkListTests + , networkOptionsTests + , networkStatusTests + ] + + +accountBalanceTests :: RosettaTest +accountBalanceTests _tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> do + ccenv <- _runClientEnv <$> _nio + return () + where + req = AccountBalanceReq nid aid Nothing + +blockTransactionTests :: RosettaTest +blockTransactionTests _tio _nio = undefined + +blockTests :: RosettaTest +blockTests _tio _nio = undefined + +constructionMetadataTests :: RosettaTest +constructionMetadataTests _tio _nio = undefined + +constructionSubmitTests :: RosettaTest +constructionSubmitTests _tio _nio = undefined + +mempoolTransactionTests :: RosettaTest +mempoolTransactionTests _tio _nio = undefined + +networkListTests :: RosettaTest +networkListTests _tio _nio = undefined + +networkOptionsTests :: RosettaTest +networkOptionsTests _tio _nio = undefined + +networkStatusTests :: RosettaTest +networkStatusTests _tio _nio = undefined + +-- ------------------------------------------------------------------ -- +-- Rosetta api w/ retry + +accountBalance + :: ClientEnv + -> AccountBalanceReq + -> IO AccountBalanceResp +accountBalance cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting account balance for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaAccountBalanceApiClient v req) cenv >>= \case + Left e -> throwM $ AccountBalanceFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + AccountBalanceFailure _ -> return True + _ -> return False + +blockTransaction + :: ClientEnv + -> BlockTransactionReq + -> IO BlockTransactionResp +blockTransaction cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting block transaction for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaBlockTransactionApiClient v req) cenv >>= \case + Left e -> throwM $ BlockTransactionFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + BlockTransactionFailure _ -> return True + _ -> return False + +block + :: ClientEnv + -> BlockReq + -> IO BlockResp +block cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting block for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaBlockApiClient v req) cenv >>= \case + Left e -> throwM $ BlockFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + BlockFailure _ -> return True + _ -> return False + +constructionMetadata + :: ClientEnv + -> ConstructionMetadataReq + -> IO ConstructionMetadataResp +constructionMetadata cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting construction metadata for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaConstructionMetadataApiClient v req) cenv >>= \case + Left e -> throwM $ ConstructionMetadataFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + ConstructionMetadataFailure _ -> return True + _ -> return False + +constructionSubmit + :: ClientEnv + -> ConstructionSubmitReq + -> IO ConstructionSubmitResp +constructionSubmit cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting construction submit for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaConstructionSubmitApiClient v req) cenv >>= \case + Left e -> throwM $ ConstructionSubmitFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + ConstructionSubmitFailure _ -> return True + _ -> return False + +mempoolTransaction + :: ClientEnv + -> MempoolTransactionReq + -> IO MempoolTransactionResp +mempoolTransaction cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting mempool transaction for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaMempoolTransactionApiClient v req) cenv >>= \case + Left e -> throwM $ MempoolTransactionFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + MempoolTransactionFailure _ -> return True + _ -> return False + +mempool + :: ClientEnv + -> MempoolReq + -> IO MempoolResp +mempool cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting mempool for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaMempoolApiClient v req) cenv >>= \case + Left e -> throwM $ MempoolFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + MempoolFailure _ -> return True + _ -> return False + +networkList + :: ClientEnv + -> MetadataReq + -> IO NetworkListResp +networkList cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting network list for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaNetworkListApiClient v req) cenv >>= \case + Left e -> throwM $ NetworkListFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + NetworkListFailure _ -> return True + _ -> return False + +networkOptions + :: ClientEnv + -> NetworkReq + -> IO NetworkOptionsResp +networkOptions cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting network options for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaNetworkOptionsApiClient v req) cenv >>= \case + Left e -> throwM $ NetworkOptionsFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + NetworkOptionsFailure _ -> return True + _ -> return False + +networkStatus + :: ClientEnv + -> NetworkReq + -> IO NetworkStatusResp +networkStatus cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting network status for " <> (take 18 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaNetworkStatusApiClient v req) cenv >>= \case + Left e -> throwM $ NetworkStatusFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + NetworkStatusFailure _ -> return True + _ -> return False From ffd88414387d2c22b6e8253c4f727e0739f56e86 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 18 Jun 2020 16:23:51 -0400 Subject: [PATCH 06/48] prep --- test/Chainweb/Test/Rosetta/RestAPI.hs | 113 +++++++++++++++----------- test/ChainwebTests.hs | 2 + 2 files changed, 68 insertions(+), 47 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 8786905f12..39c998dbfb 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -11,6 +11,8 @@ import Control.Lens import Control.Monad.Catch import Control.Retry +import Data.Aeson hiding ((.=)) + import GHC.Natural import Servant.Client @@ -54,43 +56,11 @@ v = FastTimedCPM petersonChainGraph nodes:: Natural nodes = 1 -type RosettaTest = IO (Time Micros) -> IO ChainwebNetwork -> TestTree - -data RosettaTestException - = AccountBalanceFailure String - | BlockTransactionFailure String - | BlockFailure String - | ConstructionMetadataFailure String - | ConstructionSubmitFailure String - | MempoolTransactionFailure String - | MempoolFailure String - | NetworkListFailure String - | NetworkOptionsFailure String - | NetworkStatusFailure String - deriving Show - -instance Exception RosettaTestException - - -nid :: NetworkId -nid = NetworkId - { _networkId_blockchain = undefined - , _networkId_network = "fastTimedCPM" - , _networkId_subNetworkId = undefined - } - -aid :: AccountId -aid = AccountId - { _accountId_address = "sender00" - , _accountId_subAccount = Nothing - , _accountId_metadata = undefined - } - -- -------------------------------------------------------------------------- -- -- Test Tree -tests :: RocksDb -> ScheduledTest -tests rdb = testGroupSch "Chainweb.Test.Rosetta" go +tests :: RocksDb -> TestTree +tests rdb = testGroup "Chainweb.Test.Rosetta" go where go = return $ withNodes v "rosettaRemoteTests-" rdb nodes $ \nio -> @@ -107,6 +77,7 @@ tests rdb = testGroupSch "Chainweb.Test.Rosetta" go , constructionMetadataTests , constructionSubmitTests , mempoolTransactionTests + , mempoolTests , networkListTests , networkOptionsTests , networkStatusTests @@ -114,35 +85,48 @@ tests rdb = testGroupSch "Chainweb.Test.Rosetta" go accountBalanceTests :: RosettaTest -accountBalanceTests _tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> do - ccenv <- _runClientEnv <$> _nio - return () - where - req = AccountBalanceReq nid aid Nothing +accountBalanceTests _tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> return () -- do + -- cenv <- _runClientEnv <$> _nio + -- r <- accountBalance cenv req + -- print r + -- where + -- req = AccountBalanceReq nid aid Nothing blockTransactionTests :: RosettaTest -blockTransactionTests _tio _nio = undefined +blockTransactionTests _tio _nio = + testCaseSteps "Block Transaction Tests" $ \step -> return () blockTests :: RosettaTest -blockTests _tio _nio = undefined +blockTests _tio _nio = + testCaseSteps "Block Tests" $ \step -> return () constructionMetadataTests :: RosettaTest -constructionMetadataTests _tio _nio = undefined +constructionMetadataTests _tio _nio = + testCaseSteps "Construction Metadata Tests" $ \step -> return () constructionSubmitTests :: RosettaTest -constructionSubmitTests _tio _nio = undefined +constructionSubmitTests _tio _nio = + testCaseSteps "Construction Submit Tests" $ \step -> return () mempoolTransactionTests :: RosettaTest -mempoolTransactionTests _tio _nio = undefined +mempoolTransactionTests _tio _nio = + testCaseSteps "Mempool Transaction Tests" $ \step -> return () + +mempoolTests :: RosettaTest +mempoolTests _tio _nio = + testCaseSteps "Mempool Tests" $ \step -> return () networkListTests :: RosettaTest -networkListTests _tio _nio = undefined +networkListTests _tio _nio = + testCaseSteps "Network List Tests" $ \step -> return () networkOptionsTests :: RosettaTest -networkOptionsTests _tio _nio = undefined +networkOptionsTests _tio _nio = + testCaseSteps "Network Options Tests" $ \step -> return () networkStatusTests :: RosettaTest -networkStatusTests _tio _nio = undefined +networkStatusTests _tio _nio = testCaseSteps "Network Status Tests" $ \step -> + return () -- ------------------------------------------------------------------ -- -- Rosetta api w/ retry @@ -326,3 +310,38 @@ networkStatus cenv req = h _ = Handler $ \case NetworkStatusFailure _ -> return True _ -> return False + +-- ------------------------------------------------------------------ -- +-- Test Data + +type RosettaTest = IO (Time Micros) -> IO ChainwebNetwork -> TestTree + +data RosettaTestException + = AccountBalanceFailure String + | BlockTransactionFailure String + | BlockFailure String + | ConstructionMetadataFailure String + | ConstructionSubmitFailure String + | MempoolTransactionFailure String + | MempoolFailure String + | NetworkListFailure String + | NetworkOptionsFailure String + | NetworkStatusFailure String + deriving Show + +instance Exception RosettaTestException + + +nid :: NetworkId +nid = NetworkId + { _networkId_blockchain = "kadena" + , _networkId_network = "fastTimedCPM-peterson" + , _networkId_subNetworkId = Nothing + } + +aid :: AccountId +aid = AccountId + { _accountId_address = "sender00" + , _accountId_subAccount = Nothing + , _accountId_metadata = Nothing + } diff --git a/test/ChainwebTests.hs b/test/ChainwebTests.hs index bca41bc478..9b2303ccfa 100644 --- a/test/ChainwebTests.hs +++ b/test/ChainwebTests.hs @@ -46,6 +46,7 @@ import qualified Chainweb.Test.Pact.TransactionTests import qualified Chainweb.Test.Pact.TTL import qualified Chainweb.Test.RestAPI import qualified Chainweb.Test.Rosetta +import qualified Chainweb.Test.Rosetta.RestAPI import qualified Chainweb.Test.Roundtrips import qualified Chainweb.Test.SPV import qualified Chainweb.Test.Store.CAS.FS @@ -107,6 +108,7 @@ suite rdb = , Chainweb.Test.Store.CAS.FS.tests , Chainweb.Test.Roundtrips.tests , Chainweb.Test.Rosetta.tests + , Chainweb.Test.Rosetta.RestAPI.tests rdb , Chainweb.Test.RestAPI.tests rdb , Chainweb.Test.SPV.tests rdb , Chainweb.Test.Pact.SPV.tests From 6ac6d7df087274e61feda85b8583c840df22a5b2 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 18 Jun 2020 16:48:31 -0400 Subject: [PATCH 07/48] remove multinode code dupe --- test/Chainweb/Test/MultiNode.hs | 79 +++------------------------------ test/Chainweb/Test/Utils.hs | 30 ++++++------- 2 files changed, 21 insertions(+), 88 deletions(-) diff --git a/test/Chainweb/Test/MultiNode.hs b/test/Chainweb/Test/MultiNode.hs index d07335a886..b8f5c2e99e 100644 --- a/test/Chainweb/Test/MultiNode.hs +++ b/test/Chainweb/Test/MultiNode.hs @@ -50,7 +50,6 @@ import Data.Foldable import qualified Data.HashMap.Strict as HM import qualified Data.HashSet as HS import qualified Data.List as L -import Data.Streaming.Network (HostPreference) import qualified Data.Text as T import qualified Data.Text.Encoding as T #if DEBUG_MULTINODE_TEST @@ -80,13 +79,9 @@ import Chainweb.Chainweb.PeerResources import Chainweb.Cut import Chainweb.CutDB import Chainweb.Graph -import Chainweb.HostAddress import Chainweb.Logger -import Chainweb.Miner.Config -import Chainweb.Miner.Pact import Chainweb.NodeId -import Chainweb.Test.P2P.Peer.BootstrapConfig -import Chainweb.Test.Utils hiding (bootstrapConfig, node) +import Chainweb.Test.Utils import Chainweb.Time (Seconds(..)) import Chainweb.Utils import Chainweb.Version @@ -112,64 +107,22 @@ import P2P.Peer -- similulate a full-scale chain in a miniaturized settings. -- -host :: Hostname -host = unsafeHostnameFromText "::1" - -interface :: HostPreference -interface = "::1" - -- | Test Configuration for a scaled down Test chainweb. -- -config +multiConfig :: ChainwebVersion -> Natural -- ^ number of nodes -> NodeId -- ^ NodeId -> ChainwebConfiguration -config v n nid = defaultChainwebConfiguration v - & set configNodeId nid - -- Set the node id. - - & set (configP2p . p2pConfigPeer . peerConfigHost) host - & set (configP2p . p2pConfigPeer . peerConfigInterface) interface - -- Only listen on the loopback device. On Mac OS X this prevents the - -- firewall dialog form poping up. - - & set (configP2p . p2pConfigKnownPeers) mempty - & set (configP2p . p2pConfigIgnoreBootstrapNodes) True - -- The bootstrap peer info is set later after the bootstrap nodes - -- has started and got its port assigned. - - & set (configP2p . p2pConfigMaxPeerCount) (n * 2) - -- We make room for all test peers in peer db. - - & set (configP2p . p2pConfigMaxSessionCount) 4 - -- We set this to a low number in order to keep the network sparse (or - -- at last no being a clique) and to also limit the number of - -- port allocations - +multiConfig v n nid = config v n nid & set (configP2p . p2pConfigSessionTimeout) 20 -- Use short sessions to cover session timeouts and setup logic in the -- test. - - & set (configMining . miningInNode) miner - - & set configReintroTxs True - -- enable transaction re-introduction - - & set (configTransactionIndex . enableConfigEnabled) True - -- enable transaction index - & set configThrottling throttling -- throttling is effectively disabled to not slow down the test nodes where - miner = NodeMiningConfig - { _nodeMiningEnabled = True - , _nodeMiner = noMiner - , _nodeTestMiners = MinerCount n - } - throttling = defaultThrottlingConfig { _throttlingRate = 10_000 -- per second , _throttlingMiningRate = 10_000 -- per second @@ -177,28 +130,10 @@ config v n nid = defaultChainwebConfiguration v , _throttlingLocalRate = 10_000 -- per 10 seconds } --- | Configure a bootstrap node --- -bootstrapConfig - :: ChainwebConfiguration - -> ChainwebConfiguration -bootstrapConfig conf = conf - & set (configP2p . p2pConfigPeer) peerConfig - & set (configP2p . p2pConfigKnownPeers) [] - where - peerConfig = (head $ bootstrapPeerConfig $ _configChainwebVersion conf) - & set peerConfigPort 0 - -- Normally, the port of bootstrap nodes is hard-coded. But in - -- test-suites that may run concurrently we want to use a port that is - -- assigned by the OS. - - & set peerConfigHost host - & set peerConfigInterface interface - -- -------------------------------------------------------------------------- -- -- Minimal Node Setup that logs conensus state to the given mvar -node +multiNode :: LogLevel -> (T.Text -> IO ()) -> MVar ConsensusState @@ -206,7 +141,7 @@ node -> ChainwebConfiguration -> RocksDb -> IO () -node loglevel write stateVar bootstrapPeerInfoVar conf rdb = do +multiNode loglevel write stateVar bootstrapPeerInfoVar conf rdb = do withChainweb conf logger nodeRocksDb Nothing False $ \cw -> do -- If this is the bootstrap node we extract the port number and @@ -262,14 +197,14 @@ runNodes loglevel write stateVar v n = forConcurrently_ [0 .. int n - 1] $ \i -> do threadDelay (500_000 * int i) - let baseConf = config v n (NodeId i) + let baseConf = multiConfig v n (NodeId i) conf <- if | i == 0 -> return $ bootstrapConfig baseConf | otherwise -> setBootstrapPeerInfo <$> readMVar bootstrapPortVar <*> pure baseConf - node loglevel write stateVar bootstrapPortVar conf rdb + multiNode loglevel write stateVar bootstrapPortVar conf rdb runNodesForSeconds :: LogLevel diff --git a/test/Chainweb/Test/Utils.hs b/test/Chainweb/Test/Utils.hs index 6c029a9736..9bf2ac3853 100644 --- a/test/Chainweb/Test/Utils.hs +++ b/test/Chainweb/Test/Utils.hs @@ -111,11 +111,11 @@ module Chainweb.Test.Utils , runTestNodes , node , deadbeef -, mkConfig +, config , bootstrapConfig , setBootstrapPeerInfo -, defaultHost -, defaultInterface +, host +, interface , withTime , withMVarResource ) where @@ -923,10 +923,10 @@ runTestNodes runTestNodes label rdb loglevel ver n portMVar = forConcurrently_ [0 .. int n - 1] $ \i -> do threadDelay (1000 * int i) - let baseConf = mkConfig defaultHost defaultInterface ver n (NodeId i) + let baseConf = config ver n (NodeId i) conf <- if | i == 0 -> - return $ bootstrapConfig defaultHost baseConf + return $ bootstrapConfig baseConf | otherwise -> setBootstrapPeerInfo <$> readMVar portMVar <*> pure baseConf node label rdb loglevel portMVar conf @@ -965,14 +965,12 @@ node label rdb loglevel peerInfoVar conf = do deadbeef :: TransactionHash deadbeef = TransactionHash "deadbeefdeadbeefdeadbeefdeadbeef" -mkConfig - :: Hostname - -> W.HostPreference - -> ChainwebVersion +config + :: ChainwebVersion -> Natural -> NodeId -> ChainwebConfiguration -mkConfig host interface ver n nid = defaultChainwebConfiguration ver +config ver n nid = defaultChainwebConfiguration ver & set configNodeId nid & set (configP2p . p2pConfigPeer . peerConfigHost) host & set (configP2p . p2pConfigPeer . peerConfigInterface) interface @@ -991,8 +989,8 @@ mkConfig host interface ver n nid = defaultChainwebConfiguration ver , _nodeMiner = noMiner , _nodeTestMiners = MinerCount n } -bootstrapConfig :: Hostname -> ChainwebConfiguration -> ChainwebConfiguration -bootstrapConfig host conf = conf +bootstrapConfig :: ChainwebConfiguration -> ChainwebConfiguration +bootstrapConfig conf = conf & set (configP2p . p2pConfigPeer) peerConfig & set (configP2p . p2pConfigKnownPeers) [] where @@ -1005,11 +1003,11 @@ setBootstrapPeerInfo = over (configP2p . p2pConfigKnownPeers) . (:) -defaultHost :: Hostname -defaultHost = unsafeHostnameFromText "::1" +host :: Hostname +host = unsafeHostnameFromText "::1" -defaultInterface :: W.HostPreference -defaultInterface = "::1" +interface :: W.HostPreference +interface = "::1" newtype ChainwebNetwork = ChainwebNetwork { _runClientEnv :: ClientEnv } From cd8213acab843b7750e6ad6953190ee66ad1e814 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 18 Jun 2020 16:58:58 -0400 Subject: [PATCH 08/48] put back extra dep --- chainweb.cabal | 1 + 1 file changed, 1 insertion(+) diff --git a/chainweb.cabal b/chainweb.cabal index 6220613754..ba1ef009a6 100644 --- a/chainweb.cabal +++ b/chainweb.cabal @@ -742,6 +742,7 @@ benchmark bench , deepseq >= 1.4 , directory >= 1.3 , exceptions >= 0.8 + , extra >= 1.6 , file-embed >= 0.0 , lens >= 4.16 , loglevel >= 0.1 From 0ef716961a9846287d5dad2d69206f476123fac6 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 18 Jun 2020 18:21:15 -0400 Subject: [PATCH 09/48] partition out common code --- chainweb.cabal | 1 + test/Chainweb/Test/Pact/RemotePactTest.hs | 154 +------- test/Chainweb/Test/Pact/Utils.hs | 8 +- test/Chainweb/Test/RestAPI/Utils.hs | 421 ++++++++++++++++++++++ test/Chainweb/Test/Rosetta/RestAPI.hs | 247 +------------ test/Chainweb/Test/Utils.hs | 3 +- 6 files changed, 444 insertions(+), 390 deletions(-) create mode 100644 test/Chainweb/Test/RestAPI/Utils.hs diff --git a/chainweb.cabal b/chainweb.cabal index ba1ef009a6..4fc59662b5 100644 --- a/chainweb.cabal +++ b/chainweb.cabal @@ -466,6 +466,7 @@ test-suite chainweb-tests Chainweb.Test.Pact.Utils Chainweb.Test.RestAPI Chainweb.Test.RestAPI.Client_ + Chainweb.Test.RestAPI.Utils Chainweb.Test.Rosetta Chainweb.Test.Rosetta.RestAPI Chainweb.Test.Roundtrips diff --git a/test/Chainweb/Test/Pact/RemotePactTest.hs b/test/Chainweb/Test/Pact/RemotePactTest.hs index 3c417b85c1..6b422bb667 100644 --- a/test/Chainweb/Test/Pact/RemotePactTest.hs +++ b/test/Chainweb/Test/Pact/RemotePactTest.hs @@ -45,7 +45,6 @@ import Data.Aeson.Lens hiding (values) import qualified Data.ByteString.Short as SB import Data.Decimal import Data.Default (def) -import Data.Either import Data.Foldable (toList) import qualified Data.HashMap.Strict as HashMap import qualified Data.List as L @@ -92,6 +91,7 @@ import Chainweb.Mempool.Mempool import Chainweb.Pact.RestAPI.Client import Chainweb.Pact.Service.Types import Chainweb.Test.Pact.Utils +import Chainweb.Test.RestAPI.Utils import Chainweb.Test.Utils import Chainweb.Time import Chainweb.Utils hiding (check) @@ -103,13 +103,6 @@ import Data.CAS.RocksDB -- -------------------------------------------------------------------------- -- -- Global Settings -debug :: String -> IO () -#if DEBUG_TEST -debug = putStrLn -#else -debug = const $ return () -#endif - nNodes :: Natural nNodes = 1 @@ -675,18 +668,6 @@ data PactTransaction = PactTransaction , _pactData :: Maybe A.Value } deriving (Eq, Show) - -data PactTestFailure - = PollingFailure String - | SendFailure String - | LocalFailure String - | SpvFailure String - | SlowChain String - deriving Show - -instance Exception PactTestFailure - - mkSingletonBatch :: IO (Time Micros) -> SimpleKeyPair @@ -744,139 +725,6 @@ awaitCutHeight cenv i = do <> " [" <> show (view rsIterNumberL s) <> "]" return True --- | Calls to /local via the pact local api client with retry --- -local - :: ChainId - -> ClientEnv - -> Command Text - -> IO (CommandResult Hash) -local sid cenv cmd = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting local cmd for " <> (take 19 $ show cmd) - <> " [" <> show (view rsIterNumberL s) <> "]" - - -- send a single spv request and return the result - -- - runClientM (pactLocalApiClient v sid cmd) cenv >>= \case - Left e -> throwM $ LocalFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - LocalFailure _ -> return True - _ -> return False - -localTestToRetry - :: ChainId - -> ClientEnv - -> Command Text - -> (CommandResult Hash -> Bool) - -> IO (CommandResult Hash) -localTestToRetry sid cenv cmd test = retrying testRetryPolicy check (\_ -> go) - where - go = local sid cenv cmd - check _ cr = return $ not $ test cr - --- | Request an SPV proof using exponential retry logic --- -spv - :: ChainId - -> ClientEnv - -> SpvRequest - -> IO TransactionOutputProofB64 -spv sid cenv r = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting spv proof for " <> show r - <> " [" <> show (view rsIterNumberL s) <> "]" - - -- send a single spv request and return the result - -- - runClientM (pactSpvApiClient v sid r) cenv >>= \case - Left e -> throwM $ SpvFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - SpvFailure _ -> return True - _ -> return False - --- | Backoff up to a constant 250ms, limiting to ~40s --- (actually saw a test have to wait > 22s) -testRetryPolicy :: RetryPolicy -testRetryPolicy = stepped <> limitRetries 150 - where - stepped = retryPolicy $ \rs -> case rsIterNumber rs of - 0 -> Just 20_000 - 1 -> Just 50_000 - 2 -> Just 100_000 - _ -> Just 250_000 - --- | Send a batch with retry logic waiting for success. -sending - :: ChainId - -> ClientEnv - -> SubmitBatch - -> IO RequestKeys -sending sid cenv batch = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "sending requestkeys " <> show (_cmdHash <$> toList ss) - <> " [" <> show (view rsIterNumberL s) <> "]" - - -- Send and return naively - -- - runClientM (pactSendApiClient v sid batch) cenv >>= \case - Left e -> throwM $ SendFailure (show e) - Right rs -> return rs - - where - ss = _sbCmds batch - - h _ = Handler $ \case - SendFailure _ -> return True - _ -> return False - --- | Poll with retry using an exponential backoff --- -data PollingExpectation = ExpectPactError | ExpectPactResult - -polling - :: ChainId - -> ClientEnv - -> RequestKeys - -> PollingExpectation - -> IO PollResponses -polling sid cenv rks pollingExpectation = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "polling for requestkeys " <> show (toList rs) - <> " [" <> show (view rsIterNumberL s) <> "]" - - -- Run the poll cmd loop and check responses - -- by making sure results are successful and request keys - -- are sane - - runClientM (pactPollApiClient v sid $ Poll rs) cenv >>= \case - Left e -> throwM $ PollingFailure (show e) - Right r@(PollResponses mp) -> - if all (go mp) (toList rs) - then return r - else throwM $ PollingFailure $ T.unpack $ "polling check failed: " <> encodeToText r - where - h _ = Handler $ \case - PollingFailure _ -> return True - _ -> return False - - rs = _rkRequestKeys rks - - validate (PactResult a) = case pollingExpectation of - ExpectPactResult -> isRight a - ExpectPactError -> isLeft a - - go m rk = case m ^. at rk of - Just cr -> _crReqKey cr == rk && validate (_crResult cr) - Nothing -> False testBatch'' :: Pact.ChainId -> IO (Time Micros) -> Integer -> MVar Int -> GasPrice -> IO SubmitBatch testBatch'' chain iot ttl mnonce gp' = modifyMVar mnonce $ \(!nn) -> do diff --git a/test/Chainweb/Test/Pact/Utils.hs b/test/Chainweb/Test/Pact/Utils.hs index abb5111823..67a6498b97 100644 --- a/test/Chainweb/Test/Pact/Utils.hs +++ b/test/Chainweb/Test/Pact/Utils.hs @@ -413,7 +413,7 @@ testPactCtxSQLite -> SQLiteEnv -> PactServiceConfig -> IO (TestPactCtx cas,PactDbEnv') -testPactCtxSQLite v cid bhdb pdb sqlenv config = do +testPactCtxSQLite v cid bhdb pdb sqlenv conf = do (dbSt,cpe) <- initRelationalCheckpointer' initialBlockState sqlenv logger v cid let rs = readRewards ph = ParentHeader $ genesisBlockHeader v cid @@ -433,11 +433,11 @@ testPactCtxSQLite v cid bhdb pdb sqlenv config = do , _psBlockHeaderDb = bhdb , _psGasModel = constGasModel 0 , _psMinerRewards = rs - , _psReorgLimit = fromIntegral $ _pactReorgLimit config + , _psReorgLimit = fromIntegral $ _pactReorgLimit conf , _psOnFatalError = defaultOnFatalError mempty , _psVersion = v - , _psValidateHashesOnReplay = _pactRevalidate config - , _psAllowReadsInLocal = _pactAllowReadsInLocal config + , _psValidateHashesOnReplay = _pactRevalidate conf + , _psAllowReadsInLocal = _pactAllowReadsInLocal conf } diff --git a/test/Chainweb/Test/RestAPI/Utils.hs b/test/Chainweb/Test/RestAPI/Utils.hs new file mode 100644 index 0000000000..b81257f75f --- /dev/null +++ b/test/Chainweb/Test/RestAPI/Utils.hs @@ -0,0 +1,421 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NumericUnderscores #-} +{-# LANGUAGE OverloadedStrings #-} +module Chainweb.Test.RestAPI.Utils +( -- * Retry Policy + testRetryPolicy + -- * Debugging +, debug + -- * Pact client DSL +, PactTestFailure(..) +, PollingExpectation(..) +, local +, localTestToRetry +, spv +, sending +, polling + -- * Rosetta client DSL +, RosettaTestException(..) +, accountBalance +, blockTransaction +, block +, constructionMetadata +, constructionSubmit +, mempoolTransaction +, mempool +, networkOptions +, networkList +, networkStatus +) where + + +import Control.Lens +import Control.Monad.Catch +import Control.Retry + +import Data.Either +import Data.Foldable (toList) +import Data.Text (Text) +import qualified Data.Text as T + +import Rosetta + +import Servant.Client + +-- internal chainweb modules + +import Chainweb.ChainId +import Chainweb.Graph +import Chainweb.Pact.RestAPI.Client +import Chainweb.Pact.Service.Types +import Chainweb.Rosetta.RestAPI.Client +import Chainweb.Utils +import Chainweb.Version + +-- internal pact modules + +import Pact.Types.API +import Pact.Types.Command +import Pact.Types.Hash + +-- ------------------------------------------------------------------ -- +-- Defaults + +debug :: String -> IO () +#if DEBUG_TEST +debug = putStrLn +#else +debug = const $ return () +#endif + +v :: ChainwebVersion +v = FastTimedCPM petersonChainGraph + +-- | Backoff up to a constant 250ms, limiting to ~40s +-- (actually saw a test have to wait > 22s) +testRetryPolicy :: RetryPolicy +testRetryPolicy = stepped <> limitRetries 150 + where + stepped = retryPolicy $ \rs -> case rsIterNumber rs of + 0 -> Just 20_000 + 1 -> Just 50_000 + 2 -> Just 100_000 + _ -> Just 250_000 + +-- ------------------------------------------------------------------ -- +-- Pact api client utils w/ retry + + +data PactTestFailure + = PollingFailure String + | SendFailure String + | LocalFailure String + | SpvFailure String + | SlowChain String + deriving Show + +instance Exception PactTestFailure + +-- | Calls to /local via the pact local api client with retry +-- +local + :: ChainId + -> ClientEnv + -> Command Text + -> IO (CommandResult Hash) +local sid cenv cmd = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting local cmd for " <> (take 19 $ show cmd) + <> " [" <> show (view rsIterNumberL s) <> "]" + + -- send a single spv request and return the result + -- + runClientM (pactLocalApiClient v sid cmd) cenv >>= \case + Left e -> throwM $ LocalFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + LocalFailure _ -> return True + _ -> return False + +localTestToRetry + :: ChainId + -> ClientEnv + -> Command Text + -> (CommandResult Hash -> Bool) + -> IO (CommandResult Hash) +localTestToRetry sid cenv cmd test = retrying testRetryPolicy check_ (\_ -> go) + where + go = local sid cenv cmd + check_ _ cr = return $ not $ test cr + +-- | Request an SPV proof using exponential retry logic +-- +spv + :: ChainId + -> ClientEnv + -> SpvRequest + -> IO TransactionOutputProofB64 +spv sid cenv r = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting spv proof for " <> show r + <> " [" <> show (view rsIterNumberL s) <> "]" + + -- send a single spv request and return the result + -- + runClientM (pactSpvApiClient v sid r) cenv >>= \case + Left e -> throwM $ SpvFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + SpvFailure _ -> return True + _ -> return False + +-- | Send a batch with retry logic waiting for success. +sending + :: ChainId + -> ClientEnv + -> SubmitBatch + -> IO RequestKeys +sending sid cenv batch = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "sending requestkeys " <> show (_cmdHash <$> toList ss) + <> " [" <> show (view rsIterNumberL s) <> "]" + + -- Send and return naively + -- + runClientM (pactSendApiClient v sid batch) cenv >>= \case + Left e -> throwM $ SendFailure (show e) + Right rs -> return rs + + where + ss = _sbCmds batch + + h _ = Handler $ \case + SendFailure _ -> return True + _ -> return False + +-- | Poll with retry using an exponential backoff +-- +data PollingExpectation = ExpectPactError | ExpectPactResult + +polling + :: ChainId + -> ClientEnv + -> RequestKeys + -> PollingExpectation + -> IO PollResponses +polling sid cenv rks pollingExpectation = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "polling for requestkeys " <> show (toList rs) + <> " [" <> show (view rsIterNumberL s) <> "]" + + -- Run the poll cmd loop and check responses + -- by making sure results are successful and request keys + -- are sane + + runClientM (pactPollApiClient v sid $ Poll rs) cenv >>= \case + Left e -> throwM $ PollingFailure (show e) + Right r@(PollResponses mp) -> + if all (go mp) (toList rs) + then return r + else throwM $ PollingFailure $ T.unpack $ "polling check failed: " <> encodeToText r + where + h _ = Handler $ \case + PollingFailure _ -> return True + _ -> return False + + rs = _rkRequestKeys rks + + validate (PactResult a) = case pollingExpectation of + ExpectPactResult -> isRight a + ExpectPactError -> isLeft a + + go m rk = case m ^. at rk of + Just cr -> _crReqKey cr == rk && validate (_crResult cr) + Nothing -> False + + +-- ------------------------------------------------------------------ -- +-- Rosetta api client utils w/ retry + +data RosettaTestException + = AccountBalanceFailure String + | BlockTransactionFailure String + | BlockFailure String + | ConstructionMetadataFailure String + | ConstructionSubmitFailure String + | MempoolTransactionFailure String + | MempoolFailure String + | NetworkListFailure String + | NetworkOptionsFailure String + | NetworkStatusFailure String + deriving Show + +instance Exception RosettaTestException + +accountBalance + :: ClientEnv + -> AccountBalanceReq + -> IO AccountBalanceResp +accountBalance cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting account balance for " <> (take 10 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaAccountBalanceApiClient v req) cenv >>= \case + Left e -> throwM $ AccountBalanceFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + AccountBalanceFailure _ -> return True + _ -> return False + +blockTransaction + :: ClientEnv + -> BlockTransactionReq + -> IO BlockTransactionResp +blockTransaction cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting block transaction for " <> (take 10 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaBlockTransactionApiClient v req) cenv >>= \case + Left e -> throwM $ BlockTransactionFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + BlockTransactionFailure _ -> return True + _ -> return False + +block + :: ClientEnv + -> BlockReq + -> IO BlockResp +block cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting block for " <> (take 10 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaBlockApiClient v req) cenv >>= \case + Left e -> throwM $ BlockFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + BlockFailure _ -> return True + _ -> return False + +constructionMetadata + :: ClientEnv + -> ConstructionMetadataReq + -> IO ConstructionMetadataResp +constructionMetadata cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting construction metadata for " <> (take 10 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaConstructionMetadataApiClient v req) cenv >>= \case + Left e -> throwM $ ConstructionMetadataFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + ConstructionMetadataFailure _ -> return True + _ -> return False + +constructionSubmit + :: ClientEnv + -> ConstructionSubmitReq + -> IO ConstructionSubmitResp +constructionSubmit cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting construction submit for " <> (take 10 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaConstructionSubmitApiClient v req) cenv >>= \case + Left e -> throwM $ ConstructionSubmitFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + ConstructionSubmitFailure _ -> return True + _ -> return False + +mempoolTransaction + :: ClientEnv + -> MempoolTransactionReq + -> IO MempoolTransactionResp +mempoolTransaction cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting mempool transaction for " <> (take 10 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaMempoolTransactionApiClient v req) cenv >>= \case + Left e -> throwM $ MempoolTransactionFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + MempoolTransactionFailure _ -> return True + _ -> return False + +mempool + :: ClientEnv + -> MempoolReq + -> IO MempoolResp +mempool cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting mempool for " <> (take 10 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaMempoolApiClient v req) cenv >>= \case + Left e -> throwM $ MempoolFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + MempoolFailure _ -> return True + _ -> return False + +networkList + :: ClientEnv + -> MetadataReq + -> IO NetworkListResp +networkList cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting network list for " <> (take 10 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaNetworkListApiClient v req) cenv >>= \case + Left e -> throwM $ NetworkListFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + NetworkListFailure _ -> return True + _ -> return False + +networkOptions + :: ClientEnv + -> NetworkReq + -> IO NetworkOptionsResp +networkOptions cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting network options for " <> (take 10 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaNetworkOptionsApiClient v req) cenv >>= \case + Left e -> throwM $ NetworkOptionsFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + NetworkOptionsFailure _ -> return True + _ -> return False + +networkStatus + :: ClientEnv + -> NetworkReq + -> IO NetworkStatusResp +networkStatus cenv req = + recovering testRetryPolicy [h] $ \s -> do + debug + $ "requesting network status for " <> (take 10 $ show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaNetworkStatusApiClient v req) cenv >>= \case + Left e -> throwM $ NetworkStatusFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + NetworkStatusFailure _ -> return True + _ -> return False diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 39c998dbfb..ed170338c6 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} @@ -7,21 +6,13 @@ module Chainweb.Test.Rosetta.RestAPI ) where -import Control.Lens -import Control.Monad.Catch -import Control.Retry - -import Data.Aeson hiding ((.=)) - import GHC.Natural -import Servant.Client - import Test.Tasty import Test.Tasty.HUnit import Chainweb.Graph -import Chainweb.Rosetta.RestAPI.Client +import Chainweb.Test.RestAPI.Utils import Chainweb.Test.Utils import Chainweb.Time (Time(..), Micros(..)) import Chainweb.Version @@ -34,22 +25,6 @@ import Rosetta -- -------------------------------------------------------------------------- -- -- Global Settings -debug :: String -> IO () -#if DEBUG_TEST -debug = putStrLn -#else -debug = const $ return () -#endif - -testRetryPolicy :: RetryPolicy -testRetryPolicy = stepped <> limitRetries 150 - where - stepped = retryPolicy $ \rs -> case rsIterNumber rs of - 0 -> Just 20_000 - 1 -> Just 50_000 - 2 -> Just 100_000 - _ -> Just 250_000 - v :: ChainwebVersion v = FastTimedCPM petersonChainGraph @@ -60,7 +35,7 @@ nodes = 1 -- Test Tree tests :: RocksDb -> TestTree -tests rdb = testGroup "Chainweb.Test.Rosetta" go +tests rdb = testGroup "Chainweb.Test.Rosetta.RestAPI" go where go = return $ withNodes v "rosettaRemoteTests-" rdb nodes $ \nio -> @@ -85,12 +60,13 @@ tests rdb = testGroup "Chainweb.Test.Rosetta" go accountBalanceTests :: RosettaTest -accountBalanceTests _tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> return () -- do - -- cenv <- _runClientEnv <$> _nio - -- r <- accountBalance cenv req - -- print r - -- where - -- req = AccountBalanceReq nid aid Nothing +accountBalanceTests _tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> do + step "check initial balance" + cenv <- _runClientEnv <$> _nio + r <- accountBalance cenv req + print r + where + req = AccountBalanceReq nid aid Nothing blockTransactionTests :: RosettaTest blockTransactionTests _tio _nio = @@ -128,215 +104,22 @@ networkStatusTests :: RosettaTest networkStatusTests _tio _nio = testCaseSteps "Network Status Tests" $ \step -> return () --- ------------------------------------------------------------------ -- --- Rosetta api w/ retry - -accountBalance - :: ClientEnv - -> AccountBalanceReq - -> IO AccountBalanceResp -accountBalance cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting account balance for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaAccountBalanceApiClient v req) cenv >>= \case - Left e -> throwM $ AccountBalanceFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - AccountBalanceFailure _ -> return True - _ -> return False - -blockTransaction - :: ClientEnv - -> BlockTransactionReq - -> IO BlockTransactionResp -blockTransaction cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting block transaction for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaBlockTransactionApiClient v req) cenv >>= \case - Left e -> throwM $ BlockTransactionFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - BlockTransactionFailure _ -> return True - _ -> return False - -block - :: ClientEnv - -> BlockReq - -> IO BlockResp -block cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting block for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaBlockApiClient v req) cenv >>= \case - Left e -> throwM $ BlockFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - BlockFailure _ -> return True - _ -> return False - -constructionMetadata - :: ClientEnv - -> ConstructionMetadataReq - -> IO ConstructionMetadataResp -constructionMetadata cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting construction metadata for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaConstructionMetadataApiClient v req) cenv >>= \case - Left e -> throwM $ ConstructionMetadataFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - ConstructionMetadataFailure _ -> return True - _ -> return False - -constructionSubmit - :: ClientEnv - -> ConstructionSubmitReq - -> IO ConstructionSubmitResp -constructionSubmit cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting construction submit for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaConstructionSubmitApiClient v req) cenv >>= \case - Left e -> throwM $ ConstructionSubmitFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - ConstructionSubmitFailure _ -> return True - _ -> return False - -mempoolTransaction - :: ClientEnv - -> MempoolTransactionReq - -> IO MempoolTransactionResp -mempoolTransaction cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting mempool transaction for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaMempoolTransactionApiClient v req) cenv >>= \case - Left e -> throwM $ MempoolTransactionFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - MempoolTransactionFailure _ -> return True - _ -> return False - -mempool - :: ClientEnv - -> MempoolReq - -> IO MempoolResp -mempool cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting mempool for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaMempoolApiClient v req) cenv >>= \case - Left e -> throwM $ MempoolFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - MempoolFailure _ -> return True - _ -> return False - -networkList - :: ClientEnv - -> MetadataReq - -> IO NetworkListResp -networkList cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting network list for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaNetworkListApiClient v req) cenv >>= \case - Left e -> throwM $ NetworkListFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - NetworkListFailure _ -> return True - _ -> return False - -networkOptions - :: ClientEnv - -> NetworkReq - -> IO NetworkOptionsResp -networkOptions cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting network options for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaNetworkOptionsApiClient v req) cenv >>= \case - Left e -> throwM $ NetworkOptionsFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - NetworkOptionsFailure _ -> return True - _ -> return False - -networkStatus - :: ClientEnv - -> NetworkReq - -> IO NetworkStatusResp -networkStatus cenv req = - recovering testRetryPolicy [h] $ \s -> do - debug - $ "requesting network status for " <> (take 18 $ show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaNetworkStatusApiClient v req) cenv >>= \case - Left e -> throwM $ NetworkStatusFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - NetworkStatusFailure _ -> return True - _ -> return False - -- ------------------------------------------------------------------ -- -- Test Data type RosettaTest = IO (Time Micros) -> IO ChainwebNetwork -> TestTree -data RosettaTestException - = AccountBalanceFailure String - | BlockTransactionFailure String - | BlockFailure String - | ConstructionMetadataFailure String - | ConstructionSubmitFailure String - | MempoolTransactionFailure String - | MempoolFailure String - | NetworkListFailure String - | NetworkOptionsFailure String - | NetworkStatusFailure String - deriving Show - -instance Exception RosettaTestException - +snid :: SubNetworkId +snid = SubNetworkId + { _subNetworkId_metadata = Nothing + , _subNetworkId_network = "0" + } nid :: NetworkId nid = NetworkId { _networkId_blockchain = "kadena" , _networkId_network = "fastTimedCPM-peterson" - , _networkId_subNetworkId = Nothing + , _networkId_subNetworkId = Just snid } aid :: AccountId diff --git a/test/Chainweb/Test/Utils.hs b/test/Chainweb/Test/Utils.hs index 9bf2ac3853..eb1a3c2841 100644 --- a/test/Chainweb/Test/Utils.hs +++ b/test/Chainweb/Test/Utils.hs @@ -982,7 +982,8 @@ config ver n nid = defaultChainwebConfiguration ver & set (configMining . miningInNode) miner & set configReintroTxs True & set (configTransactionIndex . enableConfigEnabled) True - & set (configBlockGasLimit) 1_000_000 + & set configBlockGasLimit 1_000_000 + & set configRosetta True where miner = NodeMiningConfig { _nodeMiningEnabled = True From dde28f2746d9afedbb2b1a13dd445876ea3b3730 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 18 Jun 2020 19:17:41 -0400 Subject: [PATCH 10/48] first batch of tests work --- test/Chainweb/Test/Pact/Utils.hs | 47 +++++++++----------- test/Chainweb/Test/Rosetta/RestAPI.hs | 64 +++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/test/Chainweb/Test/Pact/Utils.hs b/test/Chainweb/Test/Pact/Utils.hs index 67a6498b97..7aae5d5bae 100644 --- a/test/Chainweb/Test/Pact/Utils.hs +++ b/test/Chainweb/Test/Pact/Utils.hs @@ -38,7 +38,7 @@ module Chainweb.Test.Pact.Utils -- * Command builder , defaultCmd , mkCmd -, buildCmd +, buildRawCmd , buildCwCmd , buildTextCmd , mkExec' @@ -105,6 +105,7 @@ import Control.Monad import Control.Monad.Catch import Data.Aeson (Value(..), object, (.=)) +import Data.ByteString (ByteString) import Data.CAS.HashMap hiding (toList) import Data.CAS.RocksDB import Data.Decimal @@ -331,33 +332,30 @@ mkCmd nonce rpc = defaultCmd , _cbNonce = nonce } --- | Main builder command. -buildCmd :: CmdBuilder -> IO (Command (Payload PublicMeta ParsedCode)) -buildCmd CmdBuilder{..} = do - akps <- mapM toApiKp _cbSigners - kps <- mkKeyPairs akps - cmd <- mkCommand kps pm _cbNonce nid _cbRPC - case verifyCommand cmd of - ProcSucc r -> return r +-- | Build parsed + verified Pact command +-- +buildCwCmd :: CmdBuilder -> IO ChainwebTransaction +buildCwCmd cmd = buildRawCmd cmd >>= \c -> case verifyCommand c of + ProcSucc r -> return $ fmap mkPayloadWithText r ProcFail e -> throwM $ userError $ "buildCmd failed: " ++ e - where - nid = fmap (P.NetworkId . sshow) _cbNetworkId - cid = fromString $ show (chainIdInt _cbChainId :: Int) - pm = PublicMeta cid _cbSender _cbGasLimit _cbGasPrice _cbTTL _cbCreationTime --- | Main builder command. +-- | Build unparsed, unverified command +-- buildTextCmd :: CmdBuilder -> IO (Command Text) -buildTextCmd CmdBuilder{..} = do - akps <- mapM toApiKp _cbSigners - kps <- mkKeyPairs akps - cmd <- mkCommand kps pm _cbNonce nid _cbRPC - return $ T.decodeUtf8 <$> cmd +buildTextCmd = fmap (fmap T.decodeUtf8) . buildRawCmd + +-- | Build a raw bytestring command +-- +buildRawCmd :: CmdBuilder -> IO (Command ByteString) +buildRawCmd CmdBuilder{..} = do + akps <- mapM toApiKp _cbSigners + kps <- mkKeyPairs akps + mkCommand kps pm _cbNonce nid _cbRPC where nid = fmap (P.NetworkId . sshow) _cbNetworkId cid = fromString $ show (chainIdInt _cbChainId :: Int) pm = PublicMeta cid _cbSender _cbGasLimit _cbGasPrice _cbTTL _cbCreationTime - dieL :: MonadThrow m => [Char] -> Either [Char] a -> m a dieL msg = either (\s -> throwM $ userError $ msg ++ ": " ++ s) return @@ -368,11 +366,6 @@ toApiKp (CmdSigner Signer{..} privKey) = do return $! ApiKeyPair (PrivBS sk) (Just (PubBS pk)) _siAddress _siScheme (Just _siCapList) --- | 'buildCmd' variant for 'ChainwebTransaction' -buildCwCmd :: CmdBuilder -> IO ChainwebTransaction -buildCwCmd = fmap (fmap mkPayloadWithText) . buildCmd - - -- ----------------------------------------------------------------------- -- -- Service creation utilities @@ -524,7 +517,7 @@ withPactCtxSQLite -> PactServiceConfig -> (WithPactCtxSQLite cas -> TestTree) -> TestTree -withPactCtxSQLite v bhdbIO pdbIO config f = +withPactCtxSQLite v bhdbIO pdbIO conf f = withResource initializeSQLite freeSQLiteResource $ \io -> @@ -538,7 +531,7 @@ withPactCtxSQLite v bhdbIO pdbIO config f = bhdb <- bhdbIO pdb <- pdbIO (_,s) <- ios - testPactCtxSQLite v cid bhdb pdb s config + testPactCtxSQLite v cid bhdb pdb s conf toTxCreationTime :: Integral a => Time a -> TxCreationTime toTxCreationTime (Time timespan) = TxCreationTime $ fromIntegral $ timeSpanToSeconds timespan diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index ed170338c6..e9aab06671 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -6,15 +6,30 @@ module Chainweb.Test.Rosetta.RestAPI ) where + +import Control.Lens + +import Data.Functor (void) +import qualified Data.List.NonEmpty as NEL +import Data.Text (Text) + import GHC.Natural import Test.Tasty import Test.Tasty.HUnit +-- internal pact modules + +import Pact.Types.API + +-- internal chainweb modules + import Chainweb.Graph +import Chainweb.Test.Pact.Utils import Chainweb.Test.RestAPI.Utils import Chainweb.Test.Utils import Chainweb.Time (Time(..), Micros(..)) +import Chainweb.Utils import Chainweb.Version import Data.CAS.RocksDB @@ -31,6 +46,9 @@ v = FastTimedCPM petersonChainGraph nodes:: Natural nodes = 1 +cid :: ChainId +cid = unsafeChainId 0 + -- -------------------------------------------------------------------------- -- -- Test Tree @@ -60,14 +78,31 @@ tests rdb = testGroup "Chainweb.Test.Rosetta.RestAPI" go accountBalanceTests :: RosettaTest -accountBalanceTests _tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> do +accountBalanceTests tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> do step "check initial balance" cenv <- _runClientEnv <$> _nio - r <- accountBalance cenv req - print r + b0 <- accountBalance cenv req + checkBalance b0 "100000000000000000000" + + step "send 1 token to sender0 from sender01" + batch <- transferOne tio + rks <- sending cid cenv batch + void $ polling cid cenv rks ExpectPactResult + + step "check post-transfer balance" + b1 <- accountBalance cenv req + checkBalance b1 "99999998945300000000" where req = AccountBalanceReq nid aid Nothing + checkBalance bal b1 = do + let a = head $ _accountBalanceResp_balances bal + b0 = _amount_value a + curr = _amount_currency a + + b1 @=? b0 + curr @=? kda + blockTransactionTests :: RosettaTest blockTransactionTests _tio _nio = testCaseSteps "Block Transaction Tests" $ \step -> return () @@ -109,6 +144,9 @@ networkStatusTests _tio _nio = testCaseSteps "Network Status Tests" $ \step -> type RosettaTest = IO (Time Micros) -> IO ChainwebNetwork -> TestTree +kda :: Currency +kda = Currency "KDA" 12 Nothing + snid :: SubNetworkId snid = SubNetworkId { _subNetworkId_metadata = Nothing @@ -128,3 +166,23 @@ aid = AccountId , _accountId_subAccount = Nothing , _accountId_metadata = Nothing } + +-- ------------------------------------------------------------------ -- +-- Test Pact Cmds + +transferOne :: IO (Time Micros) -> IO SubmitBatch +transferOne tio = do + t <- toTxCreationTime <$> tio + c <- buildTextCmd + $ set cbSigners + [ mkSigner' sender00 + [ mkTransferCap "sender00" "sender01" 1.0 + , mkGasCap + ] + ] + $ set cbCreationTime t + $ set cbNetworkId (Just v) + $ mkCmd ("nonce-transfer-" <> sshow t) + $ mkExec' "(coin.transfer \"sender00\" \"sender01\" 1.0)" + + return $ SubmitBatch (pure c) From 74ea49ae4a827c7647610e95bb8f5f128ce085f0 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 18 Jun 2020 20:50:00 -0400 Subject: [PATCH 11/48] account balance --- chainweb.cabal | 2 +- src/Chainweb/Rosetta/Internal.hs | 5 ++-- src/Chainweb/Rosetta/RestAPI/Server.hs | 4 +-- src/Chainweb/Rosetta/{Util.hs => Utils.hs} | 2 +- test/Chainweb/Test/Rosetta.hs | 2 +- test/Chainweb/Test/Rosetta/RestAPI.hs | 33 +++++++++++++--------- 6 files changed, 26 insertions(+), 22 deletions(-) rename src/Chainweb/Rosetta/{Util.hs => Utils.hs} (99%) diff --git a/chainweb.cabal b/chainweb.cabal index 4fc59662b5..0a625b6b74 100644 --- a/chainweb.cabal +++ b/chainweb.cabal @@ -211,7 +211,7 @@ library , Chainweb.Rosetta.RestAPI , Chainweb.Rosetta.RestAPI.Client , Chainweb.Rosetta.RestAPI.Server - , Chainweb.Rosetta.Util + , Chainweb.Rosetta.Utils , Chainweb.SPV , Chainweb.SPV.CreateProof , Chainweb.SPV.VerifyProof diff --git a/src/Chainweb/Rosetta/Internal.hs b/src/Chainweb/Rosetta/Internal.hs index 09732b76ce..9951b47bb3 100644 --- a/src/Chainweb/Rosetta/Internal.hs +++ b/src/Chainweb/Rosetta/Internal.hs @@ -50,13 +50,12 @@ import Chainweb.Pact.Service.Types (Domain'(..), BlockTxHistory(..)) import Chainweb.Payload hiding (Transaction(..)) import Chainweb.Payload.PayloadStore import Chainweb.Rosetta.RestAPI +import Chainweb.Rosetta.Utils import Chainweb.TreeDB (seekAncestor) import Chainweb.Utils import Chainweb.Version import Chainweb.WebPactExecutionService (PactExecutionService(..)) -import Chainweb.Rosetta.Util - --- -------------------------------------------------------------------------------- @@ -399,7 +398,7 @@ singleRemediation logs initial target = overwriteError RosettaMismatchTxLogs) work where - logsList = M.toAscList logs + logsList = M.toAscList logs work = do TxAccumulator restLogs initTx <- nonGenesisCoinbaseLog logsList initial if (_crReqKey initial == target) diff --git a/src/Chainweb/Rosetta/RestAPI/Server.hs b/src/Chainweb/Rosetta/RestAPI/Server.hs index b89c1b7961..e32ee65720 100644 --- a/src/Chainweb/Rosetta/RestAPI/Server.hs +++ b/src/Chainweb/Rosetta/RestAPI/Server.hs @@ -57,7 +57,7 @@ import qualified Chainweb.RestAPI.NetworkID as ChainwebNetId import Chainweb.RestAPI.Utils import Chainweb.Rosetta.Internal import Chainweb.Rosetta.RestAPI -import Chainweb.Rosetta.Util +import Chainweb.Rosetta.Utils import Chainweb.Transaction (ChainwebTransaction) import Chainweb.Utils import Chainweb.Utils.Paging @@ -154,7 +154,7 @@ blockH blockH v cutDb ps crs (BlockReq net (PartialBlockId bheight bhash)) = runExceptT work >>= either throwRosetta pure where - + block :: BlockHeader -> [Transaction] -> Block block bh txs = Block { _block_blockId = blockId bh diff --git a/src/Chainweb/Rosetta/Util.hs b/src/Chainweb/Rosetta/Utils.hs similarity index 99% rename from src/Chainweb/Rosetta/Util.hs rename to src/Chainweb/Rosetta/Utils.hs index daf8a068c0..13e7eac2d2 100644 --- a/src/Chainweb/Rosetta/Util.hs +++ b/src/Chainweb/Rosetta/Utils.hs @@ -12,7 +12,7 @@ -- Stability: experimental -- -- -module Chainweb.Rosetta.Util where +module Chainweb.Rosetta.Utils where import Data.Aeson import Data.Decimal diff --git a/test/Chainweb/Test/Rosetta.hs b/test/Chainweb/Test/Rosetta.hs index db8749f5da..eedf3569b6 100644 --- a/test/Chainweb/Test/Rosetta.hs +++ b/test/Chainweb/Test/Rosetta.hs @@ -38,7 +38,7 @@ import Test.Tasty.HUnit import Chainweb.Rosetta.Internal import Chainweb.Rosetta.RestAPI -import Chainweb.Rosetta.Util +import Chainweb.Rosetta.Utils import Chainweb.Version --- diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index e9aab06671..1c2b139981 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -9,6 +9,7 @@ module Chainweb.Test.Rosetta.RestAPI import Control.Lens +import qualified Data.Aeson as A import Data.Functor (void) import qualified Data.List.NonEmpty as NEL import Data.Text (Text) @@ -25,6 +26,7 @@ import Pact.Types.API -- internal chainweb modules import Chainweb.Graph +import Chainweb.Rosetta.Utils import Chainweb.Test.Pact.Utils import Chainweb.Test.RestAPI.Utils import Chainweb.Test.Utils @@ -46,8 +48,11 @@ v = FastTimedCPM petersonChainGraph nodes:: Natural nodes = 1 -cid :: ChainId -cid = unsafeChainId 0 +sid :: ChainId +sid = unsafeChainId 0 + +tid :: ChainId +tid = unsafeChainId 1 -- -------------------------------------------------------------------------- -- -- Test Tree @@ -81,24 +86,24 @@ accountBalanceTests :: RosettaTest accountBalanceTests tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> do step "check initial balance" cenv <- _runClientEnv <$> _nio - b0 <- accountBalance cenv req - checkBalance b0 "100000000000000000000" + resp0 <- accountBalance cenv req + checkBalance resp0 100000000.000 - step "send 1 token to sender0 from sender01" - batch <- transferOne tio - rks <- sending cid cenv batch - void $ polling cid cenv rks ExpectPactResult + step "send 1.0 tokens to sender00 from sender01" + batch0 <- transferOne tio + rks <- sending sid cenv batch0 + void $ polling sid cenv rks ExpectPactResult step "check post-transfer balance" - b1 <- accountBalance cenv req - checkBalance b1 "99999998945300000000" + resp1 <- accountBalance cenv req + checkBalance resp1 99999998.9453 where req = AccountBalanceReq nid aid Nothing - checkBalance bal b1 = do - let a = head $ _accountBalanceResp_balances bal - b0 = _amount_value a - curr = _amount_currency a + checkBalance resp bal1 = do + let b0 = head $ _accountBalanceResp_balances resp + b1 = kdaToRosettaAmount bal1 + curr = _amount_currency b0 b1 @=? b0 curr @=? kda From 42d91079378bcbec9feeb371228c23fbe43a2ade Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 18 Jun 2020 20:51:38 -0400 Subject: [PATCH 12/48] remove target chain --- test/Chainweb/Test/Rosetta/RestAPI.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 1c2b139981..3492c03593 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -51,9 +51,6 @@ nodes = 1 sid :: ChainId sid = unsafeChainId 0 -tid :: ChainId -tid = unsafeChainId 1 - -- -------------------------------------------------------------------------- -- -- Test Tree From 74124fd658128bc12df84915199b53e139a28470 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 18 Jun 2020 20:51:52 -0400 Subject: [PATCH 13/48] remove target chain --- test/Chainweb/Test/Rosetta/RestAPI.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 3492c03593..f84399fcff 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -88,8 +88,8 @@ accountBalanceTests tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> step "send 1.0 tokens to sender00 from sender01" batch0 <- transferOne tio - rks <- sending sid cenv batch0 - void $ polling sid cenv rks ExpectPactResult + rks <- sending cid cenv batch0 + void $ polling cid cenv rks ExpectPactResult step "check post-transfer balance" resp1 <- accountBalance cenv req From e94ddf819e0bfe0e068da93a2cc1ec1b502865d9 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 18 Jun 2020 21:34:04 -0400 Subject: [PATCH 14/48] remove chainweb network --- test/Chainweb/Test/Pact/RemotePactTest.hs | 50 +++++++++++------------ test/Chainweb/Test/Rosetta/RestAPI.hs | 43 +++++++++---------- test/Chainweb/Test/Utils.hs | 7 +--- 3 files changed, 49 insertions(+), 51 deletions(-) diff --git a/test/Chainweb/Test/Pact/RemotePactTest.hs b/test/Chainweb/Test/Pact/RemotePactTest.hs index 6b422bb667..1773a97ca8 100644 --- a/test/Chainweb/Test/Pact/RemotePactTest.hs +++ b/test/Chainweb/Test/Pact/RemotePactTest.hs @@ -28,7 +28,7 @@ module Chainweb.Test.Pact.RemotePactTest , polling , sending , PollingExpectation(..) -, ChainwebNetwork(..) +, ClientEnv(..) ) where import Control.Concurrent hiding (modifyMVar, newMVar, putMVar, readMVar) @@ -164,24 +164,24 @@ tests rdb = testGroupSch "Chainweb.Test.Pact.RemotePactTest" -- about 10 seconds. Once initialization is complete even large numbers of empty -- blocks were mined almost instantaneously. -- -awaitNetworkHeight :: IO ChainwebNetwork -> CutHeight -> IO () +awaitNetworkHeight :: IO ClientEnv -> CutHeight -> IO () awaitNetworkHeight nio h = do - cenv <- _runClientEnv <$> nio + cenv <- nio ch <- awaitCutHeight cenv h debug $ "cut height: " <> sshow (_cutHashesHeight ch) -responseGolden :: IO ChainwebNetwork -> IO RequestKeys -> TestTree +responseGolden :: IO ClientEnv -> IO RequestKeys -> TestTree responseGolden networkIO rksIO = golden "remote-golden" $ do rks <- rksIO - cenv <- _runClientEnv <$> networkIO + cenv <- networkIO PollResponses theMap <- polling cid cenv rks ExpectPactResult let values = mapMaybe (\rk -> _crResult <$> HashMap.lookup rk theMap) (NEL.toList $ _rkRequestKeys rks) return $! toS $! foldMap A.encode values -localTest :: IO (Time Micros) -> IO ChainwebNetwork -> IO () +localTest :: IO (Time Micros) -> IO ClientEnv -> IO () localTest iot nio = do - cenv <- fmap _runClientEnv nio + cenv <- nio mv <- newMVar 0 SubmitBatch batch <- testBatch iot mv gp let cmd = head $ toList batch @@ -190,9 +190,9 @@ localTest iot nio = do assertEqual "expect /local to return gas for tx" (_crGas res) 5 assertEqual "expect /local to succeed and return 3" e (Right (PLiteral $ LDecimal 3)) -localContTest :: IO (Time Micros) -> IO ChainwebNetwork -> TestTree +localContTest :: IO (Time Micros) -> IO ClientEnv -> TestTree localContTest iot nio = testCaseSteps "local continuation test" $ \step -> do - cenv <- _runClientEnv <$> nio + cenv <- nio let sid = unsafeChainId 0 step "execute /send with initial pact continuation tx" @@ -238,9 +238,9 @@ localContTest iot nio = testCaseSteps "local continuation test" $ \step -> do $ mkCont $ mkContMsg pid 1 -localChainDataTest :: IO (Time Micros) -> IO ChainwebNetwork -> IO () +localChainDataTest :: IO (Time Micros) -> IO ClientEnv -> IO () localChainDataTest iot nio = do - cenv <- fmap _runClientEnv nio + cenv <- nio mv <- newMVar (0 :: Int) SubmitBatch batch <- localTestBatch iot mv let cmd = head $ toList batch @@ -273,19 +273,19 @@ localChainDataTest iot nio = do assert' name value = assertEqual name (M.lookup (FieldKey (toS name)) m) (Just value) expectedResult _ = assertFailure "Didn't get back an object map!" -pollingBadlistTest :: IO ChainwebNetwork -> TestTree +pollingBadlistTest :: IO ClientEnv -> TestTree pollingBadlistTest nio = testCase "/poll reports badlisted txs" $ do - cenv <- fmap _runClientEnv nio + cenv <- nio let rks = RequestKeys $ NEL.fromList [pactDeadBeef] sid <- liftIO $ mkChainId v maxBound (0 :: Int) void $ polling sid cenv rks ExpectPactError -sendValidationTest :: IO (Time Micros) -> IO ChainwebNetwork -> TestTree +sendValidationTest :: IO (Time Micros) -> IO ClientEnv -> TestTree sendValidationTest iot nio = testCaseSteps "/send reports validation failure" $ \step -> do step "check sending poisoned TTL batch" - cenv <- fmap _runClientEnv nio + cenv <- nio mv <- newMVar 0 SubmitBatch batch1 <- testBatch' iot 10_000 mv gp SubmitBatch batch2 <- testBatch' (return $ Time $ TimeSpan 0) 2 mv gp @@ -341,9 +341,9 @@ expectSendFailure expectErr act = tryAllSynchronous act >>= \case test er = assertSatisfies ("Expected message containing '" ++ expectErr ++ "'") er (L.isInfixOf expectErr) -spvTest :: IO (Time Micros) -> IO ChainwebNetwork -> TestTree +spvTest :: IO (Time Micros) -> IO ClientEnv -> TestTree spvTest iot nio = testCaseSteps "spv client tests" $ \step -> do - cenv <- fmap _runClientEnv nio + cenv <- nio batch <- mkTxBatch sid <- mkChainId v maxBound (1 :: Int) r <- flip runClientM cenv $ do @@ -392,9 +392,9 @@ spvTest iot nio = testCaseSteps "spv client tests" $ \step -> do , "target-chain-id" A..= tid ] -txTooBigGasTest :: IO (Time Micros) -> IO ChainwebNetwork -> TestTree +txTooBigGasTest :: IO (Time Micros) -> IO ClientEnv -> TestTree txTooBigGasTest iot nio = testCaseSteps "transaction size gas tests" $ \step -> do - cenv <- fmap _runClientEnv nio + cenv <- nio sid <- mkChainId v maxBound (0 :: Int) let runSend batch expectation = flip runClientM cenv $ do @@ -457,12 +457,12 @@ txTooBigGasTest iot nio = testCaseSteps "transaction size gas tests" $ \step -> txcode1 = txcode0 <> "(identity 1)" -caplistTest :: IO (Time Micros) -> IO ChainwebNetwork -> TestTree +caplistTest :: IO (Time Micros) -> IO ClientEnv -> TestTree caplistTest iot nio = testCaseSteps "caplist TRANSFER + FUND_TX test" $ \step -> do let testCaseStep = void . liftIO . step - cenv <- fmap _runClientEnv nio + cenv <- nio sid <- liftIO $ mkChainId v maxBound (0 :: Int) r <- flip runClientM cenv $ do @@ -528,12 +528,12 @@ allocation02KeyPair' = , "2f75b5d875dd7bf07cc1a6973232a9e53dc1d4ffde2bab0bbace65cd87e87f53" ) -allocationTest :: IO (Time Micros) -> IO ChainwebNetwork -> TestTree +allocationTest :: IO (Time Micros) -> IO ClientEnv -> TestTree allocationTest iot nio = testCaseSteps "genesis allocation tests" $ \step -> do let testCaseStep = void . liftIO . step - cenv <- fmap _runClientEnv nio + cenv <- nio sid <- liftIO $ mkChainId v maxBound (0 :: Int) step "positive allocation test: allocation00 release" @@ -686,14 +686,14 @@ mkSingletonBatch iot kps (PactTransaction c d) nonce pmk clist = do withRequestKeys :: IO (Time Micros) -> IO (MVar Int) - -> IO ChainwebNetwork + -> IO ClientEnv -> (IO RequestKeys -> TestTree) -> TestTree withRequestKeys iot ioNonce networkIO f = withResource mkKeys (\_ -> return ()) f where mkKeys :: IO RequestKeys mkKeys = do - cenv <- _runClientEnv <$> networkIO + cenv <- networkIO mNonce <- ioNonce testSend iot mNonce cenv diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index f84399fcff..ca19d29040 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -1,6 +1,8 @@ +{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} module Chainweb.Test.Rosetta.RestAPI ( tests ) where @@ -16,6 +18,8 @@ import Data.Text (Text) import GHC.Natural +import Servant.Client + import Test.Tasty import Test.Tasty.HUnit @@ -48,8 +52,8 @@ v = FastTimedCPM petersonChainGraph nodes:: Natural nodes = 1 -sid :: ChainId -sid = unsafeChainId 0 +cid :: ChainId +cid = unsafeChainId 0 -- -------------------------------------------------------------------------- -- -- Test Tree @@ -58,14 +62,10 @@ tests :: RocksDb -> TestTree tests rdb = testGroup "Chainweb.Test.Rosetta.RestAPI" go where go = return $ - withNodes v "rosettaRemoteTests-" rdb nodes $ \nio -> - withTime $ \tio -> tgroup nio tio - - tgroup nio tio - = testGroup "Rosetta API tests" - $ fmap (\test -> test tio nio) tests_ + withNodes v "rosettaRemoteTests-" rdb nodes $ \envIo -> + withTime $ \tio -> testGroup "Rosetta API tests" (tgroup tio envIo) - tests_ = + tgroup tio envIo = fmap (\test -> test tio envIo) [ accountBalanceTests , blockTransactionTests , blockTests @@ -80,9 +80,9 @@ tests rdb = testGroup "Chainweb.Test.Rosetta.RestAPI" go accountBalanceTests :: RosettaTest -accountBalanceTests tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> do +accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step -> do step "check initial balance" - cenv <- _runClientEnv <$> _nio + cenv <- envIo resp0 <- accountBalance cenv req checkBalance resp0 100000000.000 @@ -106,45 +106,46 @@ accountBalanceTests tio _nio = testCaseSteps "Account Balance Lookup" $ \step -> curr @=? kda blockTransactionTests :: RosettaTest -blockTransactionTests _tio _nio = +blockTransactionTests tio envIo = testCaseSteps "Block Transaction Tests" $ \step -> return () blockTests :: RosettaTest -blockTests _tio _nio = +blockTests tio envIo = testCaseSteps "Block Tests" $ \step -> return () constructionMetadataTests :: RosettaTest -constructionMetadataTests _tio _nio = +constructionMetadataTests tio envIo = testCaseSteps "Construction Metadata Tests" $ \step -> return () constructionSubmitTests :: RosettaTest -constructionSubmitTests _tio _nio = +constructionSubmitTests tio envIo = testCaseSteps "Construction Submit Tests" $ \step -> return () mempoolTransactionTests :: RosettaTest -mempoolTransactionTests _tio _nio = +mempoolTransactionTests tio envIo = testCaseSteps "Mempool Transaction Tests" $ \step -> return () mempoolTests :: RosettaTest -mempoolTests _tio _nio = +mempoolTests tio envIo = testCaseSteps "Mempool Tests" $ \step -> return () networkListTests :: RosettaTest -networkListTests _tio _nio = +networkListTests tio envIo = testCaseSteps "Network List Tests" $ \step -> return () networkOptionsTests :: RosettaTest -networkOptionsTests _tio _nio = +networkOptionsTests tio envIo = testCaseSteps "Network Options Tests" $ \step -> return () networkStatusTests :: RosettaTest -networkStatusTests _tio _nio = testCaseSteps "Network Status Tests" $ \step -> +networkStatusTests tio envIo = testCaseSteps "Network Status Tests" $ \step -> return () -- ------------------------------------------------------------------ -- -- Test Data -type RosettaTest = IO (Time Micros) -> IO ChainwebNetwork -> TestTree +type RosettaTest + = IO (Time Micros) -> IO ClientEnv -> TestTree kda :: Currency kda = Currency "KDA" 12 Nothing diff --git a/test/Chainweb/Test/Utils.hs b/test/Chainweb/Test/Utils.hs index eb1a3c2841..5043a06552 100644 --- a/test/Chainweb/Test/Utils.hs +++ b/test/Chainweb/Test/Utils.hs @@ -106,7 +106,6 @@ module Chainweb.Test.Utils , genEnum -- * Multi-node testing utils -, ChainwebNetwork(..) , withNodes , runTestNodes , node @@ -890,11 +889,11 @@ withNodes -> B.ByteString -> RocksDb -> Natural - -> (IO ChainwebNetwork -> TestTree) + -> (IO ClientEnv -> TestTree) -> TestTree withNodes v label rdb n f = withResource start (cancel . fst) - (f . fmap (ChainwebNetwork . snd)) + (f . fmap snd) where start :: IO (Async (), ClientEnv) start = do @@ -1010,8 +1009,6 @@ host = unsafeHostnameFromText "::1" interface :: W.HostPreference interface = "::1" -newtype ChainwebNetwork = ChainwebNetwork { _runClientEnv :: ClientEnv } - getClientEnv :: BaseUrl -> IO ClientEnv getClientEnv url = flip mkClientEnv url <$> HTTP.newTlsManagerWith mgrSettings where From e3dd33b7eb0d3c579e24439537878eae832d6044 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Fri, 19 Jun 2020 00:42:14 -0400 Subject: [PATCH 15/48] add block stuff --- test/Chainweb/Test/Pact/RemotePactTest.hs | 2 -- test/Chainweb/Test/Rosetta/RestAPI.hs | 12 ++++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/test/Chainweb/Test/Pact/RemotePactTest.hs b/test/Chainweb/Test/Pact/RemotePactTest.hs index 1773a97ca8..8d9a926490 100644 --- a/test/Chainweb/Test/Pact/RemotePactTest.hs +++ b/test/Chainweb/Test/Pact/RemotePactTest.hs @@ -28,7 +28,6 @@ module Chainweb.Test.Pact.RemotePactTest , polling , sending , PollingExpectation(..) -, ClientEnv(..) ) where import Control.Concurrent hiding (modifyMVar, newMVar, putMVar, readMVar) @@ -61,7 +60,6 @@ import Numeric.Natural import Servant.Client - import Test.Tasty import Test.Tasty.HUnit diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index ca19d29040..8e210243e0 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -110,8 +110,13 @@ blockTransactionTests tio envIo = testCaseSteps "Block Transaction Tests" $ \step -> return () blockTests :: RosettaTest -blockTests tio envIo = - testCaseSteps "Block Tests" $ \step -> return () +blockTests tio envIo = testCaseSteps "Block Tests" $ \step -> do + step "fetch genesis block" + cenv <- envIo + resp <- block cenv req + return () + where + req = BlockReq nid $ PartialBlockId (Just 0) Nothing constructionMetadataTests :: RosettaTest constructionMetadataTests tio envIo = @@ -170,6 +175,9 @@ aid = AccountId , _accountId_metadata = Nothing } +genesisId :: BlockId +genesisId = BlockId 0 "qU76xuohSdCyFQd2QWm7TMJHyHIRCENmdax9KMnQiSQ" + -- ------------------------------------------------------------------ -- -- Test Pact Cmds From fa7a771269d7a9d3b0f00b2b9c56f4f84bc1988b Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Mon, 22 Jun 2020 14:48:23 -0400 Subject: [PATCH 16/48] implement block tests --- test/Chainweb/Test/Rosetta/RestAPI.hs | 29 ++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 8e210243e0..2dae7f59af 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -14,6 +14,7 @@ import Control.Lens import qualified Data.Aeson as A import Data.Functor (void) import qualified Data.List.NonEmpty as NEL +import qualified Data.HashMap.Strict as HM import Data.Text (Text) import GHC.Natural @@ -26,10 +27,12 @@ import Test.Tasty.HUnit -- internal pact modules import Pact.Types.API +import Pact.Types.Command -- internal chainweb modules import Chainweb.Graph +import Chainweb.Pact.Utils (aeson) import Chainweb.Rosetta.Utils import Chainweb.Test.Pact.Utils import Chainweb.Test.RestAPI.Utils @@ -113,10 +116,30 @@ blockTests :: RosettaTest blockTests tio envIo = testCaseSteps "Block Tests" $ \step -> do step "fetch genesis block" cenv <- envIo - resp <- block cenv req + resp0 <- _block_blockId . _blockResp_block <$> block cenv req0 + resp0 @=? genesisId + + step "send transaction in at block height 1" + batch0 <- transferOne tio + rks <- sending cid cenv batch0 + prs <- polling cid cenv rks ExpectPactResult + cmdMeta <- extractMetadata prs + bh <- cmdMeta ^?! at "blockHeight" . to fromAeson + + step "check tx at block height 1 matches sent tx" + resp1 <- block cenv $ BlockReq nid $ PartialBlockId (Just bh) Nothing + + return () where - req = BlockReq nid $ PartialBlockId (Just 0) Nothing + req0 = BlockReq nid $ PartialBlockId (Just 0) Nothing + + fromAeson = aeson assertFailure return . A.fromJSON + + extractMetadata (PollResponses pr) = + case _crMetaData . snd . head . HM.toList $ pr of + Nothing -> assertFailure "test transfer did not succeed" + Just (A.Object o) -> return o constructionMetadataTests :: RosettaTest constructionMetadataTests tio envIo = @@ -176,7 +199,7 @@ aid = AccountId } genesisId :: BlockId -genesisId = BlockId 0 "qU76xuohSdCyFQd2QWm7TMJHyHIRCENmdax9KMnQiSQ" +genesisId = BlockId 0 "d69wD5SUpshDI6rbmQGugDXTd1-riqr7gfg5ZjvUrqk" -- ------------------------------------------------------------------ -- -- Test Pact Cmds From b114ff04a58cc6195d77af83ffaf72baf0b9af77 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Tue, 23 Jun 2020 14:39:53 -0400 Subject: [PATCH 17/48] add simple checks fro network list/options/status --- test/Chainweb/Test/Rosetta/RestAPI.hs | 50 ++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 2dae7f59af..8104dcdd4a 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -58,6 +58,17 @@ nodes = 1 cid :: ChainId cid = unsafeChainId 0 +rosettaVersion :: RosettaNodeVersion +rosettaVersion = RosettaNodeVersion + { _version_rosettaVersion = "1.3.1" + , _version_nodeVersion = "1.9" + , _version_middlewareVersion = Nothing + , _version_metadata = Just $ HM.fromList + [ "node-api-version" A..= ("0.0" :: Text) + , "chainweb-version" A..= ("fastTimedCPM-peterson" :: Text) + ] + } + -- -------------------------------------------------------------------------- -- -- Test Tree @@ -124,11 +135,11 @@ blockTests tio envIo = testCaseSteps "Block Tests" $ \step -> do rks <- sending cid cenv batch0 prs <- polling cid cenv rks ExpectPactResult cmdMeta <- extractMetadata prs - bh <- cmdMeta ^?! at "blockHeight" . to fromAeson + bh <- cmdMeta ^?! ix "blockHeight" . to fromAeson step "check tx at block height 1 matches sent tx" resp1 <- block cenv $ BlockReq nid $ PartialBlockId (Just bh) Nothing - + print resp1 return () where @@ -158,16 +169,39 @@ mempoolTests tio envIo = testCaseSteps "Mempool Tests" $ \step -> return () networkListTests :: RosettaTest -networkListTests tio envIo = - testCaseSteps "Network List Tests" $ \step -> return () +networkListTests tio envIo = testCaseSteps "Network List Tests" $ \step -> do + cenv <- envIo + + step "send network list request" + resp <- networkList cenv req + print resp + return () + where + req = MetadataReq Nothing networkOptionsTests :: RosettaTest -networkOptionsTests tio envIo = - testCaseSteps "Network Options Tests" $ \step -> return () +networkOptionsTests tio envIo = testCaseSteps "Network Options Tests" $ \step -> do + cenv <- envIo + + step "send network options request" + resp <- networkOptions cenv req + + step "check options response against node version" + _networkOptionsResp_version resp @=? rosettaVersion + where + req = NetworkReq nid Nothing networkStatusTests :: RosettaTest -networkStatusTests tio envIo = testCaseSteps "Network Status Tests" $ \step -> - return () +networkStatusTests tio envIo = testCaseSteps "Network Status Tests" $ \step -> do + cenv <- envIo + + step "send network status request" + resp <- networkStatus cenv req + + step "check status response against genesis" + genesisId @=? _networkStatusResp_genesisBlockId resp + where + req = NetworkReq nid Nothing -- ------------------------------------------------------------------ -- -- Test Data From 741c334feddd6c6be69e10362696446b91cf3342 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Tue, 23 Jun 2020 19:02:49 -0400 Subject: [PATCH 18/48] making progress. TODO's listed --- test/Chainweb/Test/Rosetta/RestAPI.hs | 150 ++++++++++++++++---------- 1 file changed, 96 insertions(+), 54 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 8104dcdd4a..d15eaee0e5 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -3,6 +3,7 @@ {-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} +{-# LANGUAGE TypeApplications #-} module Chainweb.Test.Rosetta.RestAPI ( tests ) where @@ -13,9 +14,10 @@ import Control.Lens import qualified Data.Aeson as A import Data.Functor (void) -import qualified Data.List.NonEmpty as NEL import qualified Data.HashMap.Strict as HM +import Data.IORef import Data.Text (Text) +import Data.Foldable (traverse_) import GHC.Natural @@ -45,6 +47,7 @@ import Data.CAS.RocksDB import Rosetta +import System.IO.Unsafe (unsafePerformIO) -- -------------------------------------------------------------------------- -- -- Global Settings @@ -58,16 +61,15 @@ nodes = 1 cid :: ChainId cid = unsafeChainId 0 -rosettaVersion :: RosettaNodeVersion -rosettaVersion = RosettaNodeVersion - { _version_rosettaVersion = "1.3.1" - , _version_nodeVersion = "1.9" - , _version_middlewareVersion = Nothing - , _version_metadata = Just $ HM.fromList - [ "node-api-version" A..= ("0.0" :: Text) - , "chainweb-version" A..= ("fastTimedCPM-peterson" :: Text) - ] - } +cids :: [Text] +cids = chainIds v ^.. folded . to (sshow @Int. chainIdInt) + +nonceRef :: IORef Natural +nonceRef = unsafePerformIO $ newIORef 0 + + +type RosettaTest + = IO (Time Micros) -> IO ClientEnv -> TestTree -- -------------------------------------------------------------------------- -- -- Test Tree @@ -83,7 +85,6 @@ tests rdb = testGroup "Chainweb.Test.Rosetta.RestAPI" go [ accountBalanceTests , blockTransactionTests , blockTests - , constructionMetadataTests , constructionSubmitTests , mempoolTransactionTests , mempoolTests @@ -101,9 +102,7 @@ accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step - checkBalance resp0 100000000.000 step "send 1.0 tokens to sender00 from sender01" - batch0 <- transferOne tio - rks <- sending cid cenv batch0 - void $ polling cid cenv rks ExpectPactResult + void $ transferOne tio cenv step "check post-transfer balance" resp1 <- accountBalance cenv req @@ -121,29 +120,37 @@ accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step - blockTransactionTests :: RosettaTest blockTransactionTests tio envIo = - testCaseSteps "Block Transaction Tests" $ \step -> return () + testCaseSteps "Block Transaction Tests" $ \step -> do + cenv <- envIo + + step "fetch genesis tx id" + -- resp <- blockTransaction cenv req + + return () + where + req = BlockTransactionReq nid genesisId genesisTxId blockTests :: RosettaTest blockTests tio envIo = testCaseSteps "Block Tests" $ \step -> do step "fetch genesis block" cenv <- envIo - resp0 <- _block_blockId . _blockResp_block <$> block cenv req0 + resp0 <- _block_blockId . _blockResp_block <$> block cenv (req 0) resp0 @=? genesisId - step "send transaction in at block height 1" - batch0 <- transferOne tio - rks <- sending cid cenv batch0 - prs <- polling cid cenv rks ExpectPactResult + step "send transaction" + prs <- transferOne tio cenv cmdMeta <- extractMetadata prs bh <- cmdMeta ^?! ix "blockHeight" . to fromAeson - step "check tx at block height 1 matches sent tx" - resp1 <- block cenv $ BlockReq nid $ PartialBlockId (Just bh) Nothing - print resp1 + step "check tx at block height matches sent tx" + resp1 <- block cenv (req bh) + step "validate remediations at block height 1" + remResp <- block cenv (req 1) + -- check remediation tx id's return () where - req0 = BlockReq nid $ PartialBlockId (Just 0) Nothing + req h = BlockReq nid $ PartialBlockId (Just h) Nothing fromAeson = aeson assertFailure return . A.fromJSON @@ -152,10 +159,6 @@ blockTests tio envIo = testCaseSteps "Block Tests" $ \step -> do Nothing -> assertFailure "test transfer did not succeed" Just (A.Object o) -> return o -constructionMetadataTests :: RosettaTest -constructionMetadataTests tio envIo = - testCaseSteps "Construction Metadata Tests" $ \step -> return () - constructionSubmitTests :: RosettaTest constructionSubmitTests tio envIo = testCaseSteps "Construction Submit Tests" $ \step -> return () @@ -169,46 +172,54 @@ mempoolTests tio envIo = testCaseSteps "Mempool Tests" $ \step -> return () networkListTests :: RosettaTest -networkListTests tio envIo = testCaseSteps "Network List Tests" $ \step -> do +networkListTests _ envIo = testCaseSteps "Network List Tests" $ \step -> do cenv <- envIo - step "send network list request" resp <- networkList cenv req - print resp - return () + traverse_ checkChainIds (_networkListResp_networkIds resp) where req = MetadataReq Nothing + checkChainIds n = do + _networkId_blockchain n @=? "kadena" + _networkId_network n @=? "fastTimedCPM-peterson" + assertBool "chain id of subnetwork is valid" $ + case _networkId_subNetworkId n of + Nothing -> False + Just a -> elem (_subNetworkId_network a) cids + networkOptionsTests :: RosettaTest -networkOptionsTests tio envIo = testCaseSteps "Network Options Tests" $ \step -> do +networkOptionsTests _ envIo = testCaseSteps "Network Options Tests" $ \step -> do cenv <- envIo step "send network options request" - resp <- networkOptions cenv req + resp <- networkOptions cenv req0 step "check options response against node version" _networkOptionsResp_version resp @=? rosettaVersion + + -- enumerate over exceptions + where - req = NetworkReq nid Nothing + req0 = NetworkReq nid Nothing networkStatusTests :: RosettaTest networkStatusTests tio envIo = testCaseSteps "Network Status Tests" $ \step -> do cenv <- envIo step "send network status request" + transferOne_ tio cenv resp <- networkStatus cenv req step "check status response against genesis" genesisId @=? _networkStatusResp_genesisBlockId resp + -- check current block (should be updated by tx) where req = NetworkReq nid Nothing -- ------------------------------------------------------------------ -- -- Test Data -type RosettaTest - = IO (Time Micros) -> IO ClientEnv -> TestTree - kda :: Currency kda = Currency "KDA" 12 Nothing @@ -235,22 +246,53 @@ aid = AccountId genesisId :: BlockId genesisId = BlockId 0 "d69wD5SUpshDI6rbmQGugDXTd1-riqr7gfg5ZjvUrqk" +rosettaVersion :: RosettaNodeVersion +rosettaVersion = RosettaNodeVersion + { _version_rosettaVersion = "1.3.1" + , _version_nodeVersion = "1.9" + , _version_middlewareVersion = Nothing + , _version_metadata = Just $ HM.fromList + [ "node-api-version" A..= ("0.0" :: Text) + , "chainweb-version" A..= ("fastTimedCPM-peterson" :: Text) + ] + } + +genesisTxId :: TransactionId +genesisTxId = TransactionId "Inlsd2hVbVVBOUtnZjM5d191c2dGRHoycV9RX09YX1lMQmNDMXZBSC1Mc0Ei" + +-- write out allowables and check failures against alloweds + -- ------------------------------------------------------------------ -- -- Test Pact Cmds -transferOne :: IO (Time Micros) -> IO SubmitBatch -transferOne tio = do - t <- toTxCreationTime <$> tio - c <- buildTextCmd - $ set cbSigners - [ mkSigner' sender00 - [ mkTransferCap "sender00" "sender01" 1.0 - , mkGasCap +-- | Transfer one token from sender00 to sender01, polling for responses +-- +transferOne :: IO (Time Micros) -> ClientEnv -> IO PollResponses +transferOne tio cenv = do + batch0 <- mkTransfer + rks <- sending cid cenv batch0 + prs <- polling cid cenv rks ExpectPactResult + return prs + where + mkTransfer = do + t <- toTxCreationTime <$> tio + n <- readIORef nonceRef + c <- buildTextCmd + $ set cbSigners + [ mkSigner' sender00 + [ mkTransferCap "sender00" "sender01" 1.0 + , mkGasCap + ] ] - ] - $ set cbCreationTime t - $ set cbNetworkId (Just v) - $ mkCmd ("nonce-transfer-" <> sshow t) - $ mkExec' "(coin.transfer \"sender00\" \"sender01\" 1.0)" - - return $ SubmitBatch (pure c) + $ set cbCreationTime t + $ set cbNetworkId (Just v) + $ mkCmd ("nonce-transfer-" <> sshow t <> "-" <> sshow n) + $ mkExec' "(coin.transfer \"sender00\" \"sender01\" 1.0)" + + modifyIORef' nonceRef (+1) + return $ SubmitBatch (pure c) + +-- | Transfer one, ignoring the resulting responses +-- +transferOne_ :: IO (Time Micros) -> ClientEnv -> IO () +transferOne_ tio cenv = void $! transferOne tio cenv From d49309840ab4c609733819ae7ed532f9b1f2ce8c Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Tue, 23 Jun 2020 19:19:43 -0400 Subject: [PATCH 19/48] update status test --- test/Chainweb/Test/Rosetta/RestAPI.hs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index d15eaee0e5..a30bae9a1d 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -156,8 +156,8 @@ blockTests tio envIo = testCaseSteps "Block Tests" $ \step -> do extractMetadata (PollResponses pr) = case _crMetaData . snd . head . HM.toList $ pr of - Nothing -> assertFailure "test transfer did not succeed" Just (A.Object o) -> return o + _ -> assertFailure "test transfer did not succeed" constructionSubmitTests :: RosettaTest constructionSubmitTests tio envIo = @@ -208,15 +208,23 @@ networkStatusTests tio envIo = testCaseSteps "Network Status Tests" $ \step -> d cenv <- envIo step "send network status request" - transferOne_ tio cenv - resp <- networkStatus cenv req + resp0 <- networkStatus cenv req step "check status response against genesis" - genesisId @=? _networkStatusResp_genesisBlockId resp - -- check current block (should be updated by tx) + genesisId @=? _networkStatusResp_genesisBlockId resp0 + + step "send in a transaction and update current block" + transferOne_ tio cenv + resp1 <- networkStatus cenv req + + step "check status response genesis and block height" + genesisId @=? _networkStatusResp_genesisBlockId resp1 + (blockIdOf resp1 > blockIdOf resp0) @? "current block id heights must increment" where req = NetworkReq nid Nothing + blockIdOf = _blockId_index . _networkStatusResp_currentBlockId + -- ------------------------------------------------------------------ -- -- Test Data From 256621dab7f2c0988401077250ee59d6803621f4 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Tue, 23 Jun 2020 20:21:08 -0400 Subject: [PATCH 20/48] make options test a little nicer --- test/Chainweb/Test/Rosetta/RestAPI.hs | 41 +++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index a30bae9a1d..6db043241a 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -16,6 +16,7 @@ import qualified Data.Aeson as A import Data.Functor (void) import qualified Data.HashMap.Strict as HM import Data.IORef +import Data.List (union) import Data.Text (Text) import Data.Foldable (traverse_) @@ -35,6 +36,7 @@ import Pact.Types.Command import Chainweb.Graph import Chainweb.Pact.Utils (aeson) +import Chainweb.Rosetta.RestAPI import Chainweb.Rosetta.Utils import Chainweb.Test.Pact.Utils import Chainweb.Test.RestAPI.Utils @@ -195,13 +197,27 @@ networkOptionsTests _ envIo = testCaseSteps "Network Options Tests" $ \step -> d step "send network options request" resp <- networkOptions cenv req0 - step "check options response against node version" - _networkOptionsResp_version resp @=? rosettaVersion + let allow = _networkOptionsResp_allow resp + version = _networkOptionsResp_version resp - -- enumerate over exceptions + step "check options responses against allowable data and versions" + version @=? rosettaVersion + + step "Check that response errors are a subset of valid errors" + (respErrors resp `subset` rosettaFailures) @? + "allowable errors must coincide with failure list" + + step "Check that response statuses are a subset of valid statuses" + (_allow_operationStatuses allow `union` operationStatuses) `subset` operationStatuses @? + "allowed operation statuses coincide" + + step "Check that response op types are a subset of op types" + (_allow_operationTypes allow `subset` allowedOperations) @? "allowed operations coincide" where req0 = NetworkReq nid Nothing + respErrors = _allow_errors . _networkOptionsResp_allow + allowedOperations = _operationStatus_status <$> operationStatuses networkStatusTests :: RosettaTest networkStatusTests tio envIo = testCaseSteps "Network Status Tests" $ \step -> do @@ -270,6 +286,19 @@ genesisTxId = TransactionId "Inlsd2hVbVVBOUtnZjM5d191c2dGRHoycV9RX09YX1lMQmNDMXZ -- write out allowables and check failures against alloweds +rosettaFailures :: [RosettaError] +rosettaFailures = rosettaError <$> enumFrom RosettaChainUnspecified + +operationStatuses :: [OperationStatus] +operationStatuses = + [ OperationStatus "Successful" True + , OperationStatus "Remediation" True + , OperationStatus "CoinbaseReward" True + , OperationStatus "FundTx" True + , OperationStatus "GasPayment" True + , OperationStatus "TransferOrCreateAcct" True + ] + -- ------------------------------------------------------------------ -- -- Test Pact Cmds @@ -304,3 +333,9 @@ transferOne tio cenv = do -- transferOne_ :: IO (Time Micros) -> ClientEnv -> IO () transferOne_ tio cenv = void $! transferOne tio cenv + +-- ------------------------------------------------------------------ -- +-- Utils + +subset :: Eq a => [a] -> [a] -> Bool +subset as bs = all (`elem` bs) as From c9bd5efacfc2346b793436e90417550941027356 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Tue, 23 Jun 2020 20:33:19 -0400 Subject: [PATCH 21/48] fix account balance test --- test/Chainweb/Test/Rosetta/RestAPI.hs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 6db043241a..aafac49157 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -69,9 +69,7 @@ cids = chainIds v ^.. folded . to (sshow @Int. chainIdInt) nonceRef :: IORef Natural nonceRef = unsafePerformIO $ newIORef 0 - -type RosettaTest - = IO (Time Micros) -> IO ClientEnv -> TestTree +type RosettaTest = IO (Time Micros) -> IO ClientEnv -> TestTree -- -------------------------------------------------------------------------- -- -- Test Tree @@ -95,7 +93,6 @@ tests rdb = testGroup "Chainweb.Test.Rosetta.RestAPI" go , networkStatusTests ] - accountBalanceTests :: RosettaTest accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step -> do step "check initial balance" @@ -108,7 +105,7 @@ accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step - step "check post-transfer balance" resp1 <- accountBalance cenv req - checkBalance resp1 99999998.9453 + checkBalance resp1 99999997.8906 where req = AccountBalanceReq nid aid Nothing @@ -178,18 +175,18 @@ networkListTests _ envIo = testCaseSteps "Network List Tests" $ \step -> do cenv <- envIo step "send network list request" resp <- networkList cenv req + + let checkChainIds n = do + _networkId_blockchain n @=? "kadena" + _networkId_network n @=? "fastTimedCPM-peterson" + assertBool "chain id of subnetwork is valid" + $ maybe False (\a -> elem (_subNetworkId_network a) cids) + $ _networkId_subNetworkId n + traverse_ checkChainIds (_networkListResp_networkIds resp) where req = MetadataReq Nothing - checkChainIds n = do - _networkId_blockchain n @=? "kadena" - _networkId_network n @=? "fastTimedCPM-peterson" - assertBool "chain id of subnetwork is valid" $ - case _networkId_subNetworkId n of - Nothing -> False - Just a -> elem (_subNetworkId_network a) cids - networkOptionsTests :: RosettaTest networkOptionsTests _ envIo = testCaseSteps "Network Options Tests" $ \step -> do cenv <- envIo From 1dcc5ffbd324c797578f9d3fcfd84951d2addbcb Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Wed, 24 Jun 2020 13:22:57 -0400 Subject: [PATCH 22/48] small changes --- test/Chainweb/Test/Rosetta/RestAPI.hs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index aafac49157..f01642c837 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -18,7 +18,7 @@ import qualified Data.HashMap.Strict as HM import Data.IORef import Data.List (union) import Data.Text (Text) -import Data.Foldable (traverse_) +import Data.Foldable import GHC.Natural @@ -64,7 +64,7 @@ cid :: ChainId cid = unsafeChainId 0 cids :: [Text] -cids = chainIds v ^.. folded . to (sshow @Int. chainIdInt) +cids = chainIds v ^.. folded . to (sshow @Int . chainIdInt) nonceRef :: IORef Natural nonceRef = unsafePerformIO $ newIORef 0 @@ -176,14 +176,12 @@ networkListTests _ envIo = testCaseSteps "Network List Tests" $ \step -> do step "send network list request" resp <- networkList cenv req - let checkChainIds n = do - _networkId_blockchain n @=? "kadena" - _networkId_network n @=? "fastTimedCPM-peterson" - assertBool "chain id of subnetwork is valid" - $ maybe False (\a -> elem (_subNetworkId_network a) cids) - $ _networkId_subNetworkId n - - traverse_ checkChainIds (_networkListResp_networkIds resp) + for_ (_networkListResp_networkIds resp) $ \n -> do + _networkId_blockchain n @=? "kadena" + _networkId_network n @=? "fastTimedCPM-peterson" + assertBool "chain id of subnetwork is valid" + $ maybe False (\a -> elem (_subNetworkId_network a) cids) + $ _networkId_subNetworkId n where req = MetadataReq Nothing @@ -209,7 +207,8 @@ networkOptionsTests _ envIo = testCaseSteps "Network Options Tests" $ \step -> d "allowed operation statuses coincide" step "Check that response op types are a subset of op types" - (_allow_operationTypes allow `subset` allowedOperations) @? "allowed operations coincide" + (_allow_operationTypes allow `subset` allowedOperations) @? + "allowed operations coincide" where req0 = NetworkReq nid Nothing @@ -281,8 +280,6 @@ rosettaVersion = RosettaNodeVersion genesisTxId :: TransactionId genesisTxId = TransactionId "Inlsd2hVbVVBOUtnZjM5d191c2dGRHoycV9RX09YX1lMQmNDMXZBSC1Mc0Ei" --- write out allowables and check failures against alloweds - rosettaFailures :: [RosettaError] rosettaFailures = rosettaError <$> enumFrom RosettaChainUnspecified @@ -334,5 +331,5 @@ transferOne_ tio cenv = void $! transferOne tio cenv -- ------------------------------------------------------------------ -- -- Utils -subset :: Eq a => [a] -> [a] -> Bool +subset :: (Foldable f, Eq a) => f a -> f a -> Bool subset as bs = all (`elem` bs) as From e6fa205bbe12a608f4bddf7756e81d9aaf5a87aa Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 25 Jun 2020 17:28:00 -0400 Subject: [PATCH 23/48] add async tests for mempool --- test/Chainweb/Test/RestAPI/Utils.hs | 9 +++ test/Chainweb/Test/Rosetta/RestAPI.hs | 88 +++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 5 deletions(-) diff --git a/test/Chainweb/Test/RestAPI/Utils.hs b/test/Chainweb/Test/RestAPI/Utils.hs index b81257f75f..b79715a311 100644 --- a/test/Chainweb/Test/RestAPI/Utils.hs +++ b/test/Chainweb/Test/RestAPI/Utils.hs @@ -8,6 +8,8 @@ module Chainweb.Test.RestAPI.Utils testRetryPolicy -- * Debugging , debug + -- * Utils +, repeatUntil -- * Pact client DSL , PactTestFailure(..) , PollingExpectation(..) @@ -98,6 +100,13 @@ data PactTestFailure instance Exception PactTestFailure +-- | Retry an IO action until it satisfies a predicate +-- +repeatUntil :: (a -> IO Bool) -> IO a -> IO a +repeatUntil test action = retrying testRetryPolicy + (\_ b -> not <$> test b) + (const action) + -- | Calls to /local via the pact local api client with retry -- local diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index f01642c837..919cd22077 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -9,7 +9,8 @@ module Chainweb.Test.Rosetta.RestAPI ) where - +import Control.Concurrent.Async +import Control.Concurrent.MVar import Control.Lens import qualified Data.Aeson as A @@ -17,6 +18,7 @@ import Data.Functor (void) import qualified Data.HashMap.Strict as HM import Data.IORef import Data.List (union) +import qualified Data.List.NonEmpty as NEL import Data.Text (Text) import Data.Foldable @@ -93,6 +95,8 @@ tests rdb = testGroup "Chainweb.Test.Rosetta.RestAPI" go , networkStatusTests ] +-- | Rosetta account balance endpoint tests +-- accountBalanceTests :: RosettaTest accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step -> do step "check initial balance" @@ -117,6 +121,8 @@ accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step - b1 @=? b0 curr @=? kda +-- | Rosetta block transaction endpoint tests +-- blockTransactionTests :: RosettaTest blockTransactionTests tio envIo = testCaseSteps "Block Transaction Tests" $ \step -> do @@ -129,6 +135,8 @@ blockTransactionTests tio envIo = where req = BlockTransactionReq nid genesisId genesisTxId +-- | Rosetta block endpoint tests +-- blockTests :: RosettaTest blockTests tio envIo = testCaseSteps "Block Tests" $ \step -> do step "fetch genesis block" @@ -158,18 +166,54 @@ blockTests tio envIo = testCaseSteps "Block Tests" $ \step -> do Just (A.Object o) -> return o _ -> assertFailure "test transfer did not succeed" +-- | Rosetta construction submit endpoint tests (i.e. tx submission directly to mempool) +-- constructionSubmitTests :: RosettaTest constructionSubmitTests tio envIo = testCaseSteps "Construction Submit Tests" $ \step -> return () +-- | Rosetta mempool transaction endpoint tests +-- mempoolTransactionTests :: RosettaTest -mempoolTransactionTests tio envIo = - testCaseSteps "Mempool Transaction Tests" $ \step -> return () +mempoolTransactionTests tio envIo = testCaseSteps "Mempool Transaction Tests" $ \step -> do + cenv <- envIo + rkmv <- newEmptyMVar @RequestKeys + + step "execute transfer and wait on mempool data" + a <- async $ transferOneAsync tio cenv (putMVar rkmv) + MempoolResp [tid] <- repeatUntil test $ do + RequestKeys (rk NEL.:| []) <- _rkRequestKeys <$> takeMVar rkmv + mempoolTransaction cenv req (req rk) + step "compare requestkey against transaction id" + rk NEL.:| [] <- _rkRequestKeys <$> takeMVar rkmv + show rk @=? show (_transactionId_hash tid) + where + req = MempoolReq nid + +-- | Rosetta mempool endpoint tests +-- mempoolTests :: RosettaTest -mempoolTests tio envIo = - testCaseSteps "Mempool Tests" $ \step -> return () +mempoolTests tio envIo = testCaseSteps "Mempool Tests" $ \step -> do + cenv <- envIo + rkmv <- newEmptyMVar @RequestKeys + + step "execute transfer and wait on mempool data" + a <- async $ transferOneAsync tio cenv (putMVar rkmv) + + let test (MempoolResp [xs]) = return True + test (MempoolResp _) = return False + + MempoolResp [tid] <- repeatUntil test $ mempool cenv req + + step "compare requestkey against transaction id" + rk NEL.:| [] <- _rkRequestKeys <$> takeMVar rkmv + show rk @=? show (_transactionId_hash tid) + where + req = MempoolReq nid +-- | Rosetta network list endpoint tests +-- networkListTests :: RosettaTest networkListTests _ envIo = testCaseSteps "Network List Tests" $ \step -> do cenv <- envIo @@ -185,6 +229,8 @@ networkListTests _ envIo = testCaseSteps "Network List Tests" $ \step -> do where req = MetadataReq Nothing +-- | Rosetta network options tests +-- networkOptionsTests :: RosettaTest networkOptionsTests _ envIo = testCaseSteps "Network Options Tests" $ \step -> do cenv <- envIo @@ -215,6 +261,8 @@ networkOptionsTests _ envIo = testCaseSteps "Network Options Tests" $ \step -> d respErrors = _allow_errors . _networkOptionsResp_allow allowedOperations = _operationStatus_status <$> operationStatuses +-- | Rosetta network status tests +-- networkStatusTests :: RosettaTest networkStatusTests tio envIo = testCaseSteps "Network Status Tests" $ \step -> do cenv <- envIo @@ -328,6 +376,36 @@ transferOne tio cenv = do transferOne_ :: IO (Time Micros) -> ClientEnv -> IO () transferOne_ tio cenv = void $! transferOne tio cenv +-- | Transfer one token from sender00 to sender01, polling for responses +-- +transferOneAsync + :: IO (Time Micros) + -> ClientEnv + -> (RequestKeys -> IO ()) + -> IO () +transferOneAsync tio cenv callback = do + batch0 <- mkTransfer + rks <- sending cid cenv batch0 + void $! callback rks + where + mkTransfer = do + t <- toTxCreationTime <$> tio + n <- readIORef nonceRef + c <- buildTextCmd + $ set cbSigners + [ mkSigner' sender00 + [ mkTransferCap "sender00" "sender01" 1.0 + , mkGasCap + ] + ] + $ set cbCreationTime t + $ set cbNetworkId (Just v) + $ mkCmd ("nonce-transfer-" <> sshow t <> "-" <> sshow n) + $ mkExec' "(coin.transfer \"sender00\" \"sender01\" 1.0)" + + modifyIORef' nonceRef (+1) + return $ SubmitBatch (pure c) + -- ------------------------------------------------------------------ -- -- Utils From 5f7ee94d74e136e05953e71fb451ab14a28e13a2 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 25 Jun 2020 19:53:05 -0400 Subject: [PATCH 24/48] add fixes to mempool test, keep going on mempool transaction --- test/Chainweb/Test/RestAPI/Utils.hs | 59 +++++++++++---- test/Chainweb/Test/Rosetta/RestAPI.hs | 100 ++++++++++++-------------- 2 files changed, 92 insertions(+), 67 deletions(-) diff --git a/test/Chainweb/Test/RestAPI/Utils.hs b/test/Chainweb/Test/RestAPI/Utils.hs index b79715a311..adb1b6a9c8 100644 --- a/test/Chainweb/Test/RestAPI/Utils.hs +++ b/test/Chainweb/Test/RestAPI/Utils.hs @@ -4,8 +4,9 @@ {-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} module Chainweb.Test.RestAPI.Utils -( -- * Retry Policy +( -- * Retry Policies testRetryPolicy +, fastRetryPolicy -- * Debugging , debug -- * Utils @@ -26,6 +27,7 @@ module Chainweb.Test.RestAPI.Utils , constructionMetadata , constructionSubmit , mempoolTransaction +, mempoolTransactionWithFastRetry , mempool , networkOptions , networkList @@ -86,6 +88,23 @@ testRetryPolicy = stepped <> limitRetries 150 2 -> Just 100_000 _ -> Just 250_000 +-- | Backoff up to a constant 25ms, limiting to 12s +-- +fastRetryPolicy :: RetryPolicy +fastRetryPolicy = fastSteps <> limitRetries 500 + where + fastSteps = retryPolicy $ \rs -> case rsIterNumber rs of + 0 -> Just 100 + 1 -> Just 200 + 2 -> Just 300 + 3 -> Just 400 + 4 -> Just 500 + 5 -> Just 600 + 6 -> Just 700 + 7 -> Just 800 + 8 -> Just 900 + _ -> Just 25_000 + -- ------------------------------------------------------------------ -- -- Pact api client utils w/ retry @@ -136,10 +155,8 @@ localTestToRetry -> Command Text -> (CommandResult Hash -> Bool) -> IO (CommandResult Hash) -localTestToRetry sid cenv cmd test = retrying testRetryPolicy check_ (\_ -> go) - where - go = local sid cenv cmd - check_ _ cr = return $ not $ test cr +localTestToRetry sid cenv cmd test = + repeatUntil (return . test) (local sid cenv cmd) -- | Request an SPV proof using exponential retry logic -- @@ -256,7 +273,7 @@ accountBalance accountBalance cenv req = recovering testRetryPolicy [h] $ \s -> do debug - $ "requesting account balance for " <> (take 10 $ show req) + $ "requesting account balance for " <> (show req) <> " [" <> show (view rsIterNumberL s) <> "]" runClientM (rosettaAccountBalanceApiClient v req) cenv >>= \case @@ -274,7 +291,7 @@ blockTransaction blockTransaction cenv req = recovering testRetryPolicy [h] $ \s -> do debug - $ "requesting block transaction for " <> (take 10 $ show req) + $ "requesting block transaction for " <> (show req) <> " [" <> show (view rsIterNumberL s) <> "]" runClientM (rosettaBlockTransactionApiClient v req) cenv >>= \case @@ -292,7 +309,7 @@ block block cenv req = recovering testRetryPolicy [h] $ \s -> do debug - $ "requesting block for " <> (take 10 $ show req) + $ "requesting block for " <> (show req) <> " [" <> show (view rsIterNumberL s) <> "]" runClientM (rosettaBlockApiClient v req) cenv >>= \case @@ -310,7 +327,7 @@ constructionMetadata constructionMetadata cenv req = recovering testRetryPolicy [h] $ \s -> do debug - $ "requesting construction metadata for " <> (take 10 $ show req) + $ "requesting construction metadata for " <> (show req) <> " [" <> show (view rsIterNumberL s) <> "]" runClientM (rosettaConstructionMetadataApiClient v req) cenv >>= \case @@ -328,7 +345,7 @@ constructionSubmit constructionSubmit cenv req = recovering testRetryPolicy [h] $ \s -> do debug - $ "requesting construction submit for " <> (take 10 $ show req) + $ "requesting construction submit for " <> (show req) <> " [" <> show (view rsIterNumberL s) <> "]" runClientM (rosettaConstructionSubmitApiClient v req) cenv >>= \case @@ -346,7 +363,25 @@ mempoolTransaction mempoolTransaction cenv req = recovering testRetryPolicy [h] $ \s -> do debug - $ "requesting mempool transaction for " <> (take 10 $ show req) + $ "requesting mempool transaction for " <> (show req) + <> " [" <> show (view rsIterNumberL s) <> "]" + + runClientM (rosettaMempoolTransactionApiClient v req) cenv >>= \case + Left e -> throwM $ MempoolTransactionFailure (show e) + Right t -> return t + where + h _ = Handler $ \case + MempoolTransactionFailure _ -> return True + _ -> return False + +mempoolTransactionWithFastRetry + :: ClientEnv + -> MempoolTransactionReq + -> IO MempoolTransactionResp +mempoolTransactionWithFastRetry cenv req = + recovering fastRetryPolicy [h] $ \s -> do + debug + $ "requesting mempool transaction for " <> (show req) <> " [" <> show (view rsIterNumberL s) <> "]" runClientM (rosettaMempoolTransactionApiClient v req) cenv >>= \case @@ -364,7 +399,7 @@ mempool mempool cenv req = recovering testRetryPolicy [h] $ \s -> do debug - $ "requesting mempool for " <> (take 10 $ show req) + $ "requesting mempool for " <> (show req) <> " [" <> show (view rsIterNumberL s) <> "]" runClientM (rosettaMempoolApiClient v req) cenv >>= \case diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 919cd22077..d636a0bf69 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -175,21 +175,22 @@ constructionSubmitTests tio envIo = -- | Rosetta mempool transaction endpoint tests -- mempoolTransactionTests :: RosettaTest -mempoolTransactionTests tio envIo = testCaseSteps "Mempool Transaction Tests" $ \step -> do - cenv <- envIo - rkmv <- newEmptyMVar @RequestKeys +mempoolTransactionTests tio envIo = + testCaseSteps "Mempool Transaction Tests" $ \step -> do + cenv <- envIo + rkmv <- newEmptyMVar @RequestKeys - step "execute transfer and wait on mempool data" - a <- async $ transferOneAsync tio cenv (putMVar rkmv) - MempoolResp [tid] <- repeatUntil test $ do - RequestKeys (rk NEL.:| []) <- _rkRequestKeys <$> takeMVar rkmv - mempoolTransaction cenv req (req rk) + step "execute transfer and wait on mempool data" + void $! async $ transferOneAsync tio cenv (putMVar rkmv) - step "compare requestkey against transaction id" - rk NEL.:| [] <- _rkRequestKeys <$> takeMVar rkmv - show rk @=? show (_transactionId_hash tid) + step "wait until mempool registers transfer" + rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv + MempoolTransactionResp tx _meta <- mempoolTransactionWithFastRetry cenv (req rk) + + step "compare requestkey against transaction id" + rkToTransactionId rk @=? _transaction_transactionId tx where - req = MempoolReq nid + req rk = MempoolTransactionReq nid (rkToTransactionId rk) -- | Rosetta mempool endpoint tests -- @@ -199,16 +200,16 @@ mempoolTests tio envIo = testCaseSteps "Mempool Tests" $ \step -> do rkmv <- newEmptyMVar @RequestKeys step "execute transfer and wait on mempool data" - a <- async $ transferOneAsync tio cenv (putMVar rkmv) + void $! async $ transferOneAsync tio cenv (putMVar rkmv) - let test (MempoolResp [xs]) = return True + let test (MempoolResp [_]) = return True test (MempoolResp _) = return False MempoolResp [tid] <- repeatUntil test $ mempool cenv req step "compare requestkey against transaction id" rk NEL.:| [] <- _rkRequestKeys <$> takeMVar rkmv - show rk @=? show (_transactionId_hash tid) + rkToTransactionId rk @=? tid where req = MempoolReq nid @@ -348,35 +349,40 @@ operationStatuses = -- transferOne :: IO (Time Micros) -> ClientEnv -> IO PollResponses transferOne tio cenv = do - batch0 <- mkTransfer + batch0 <- mkTransfer tio rks <- sending cid cenv batch0 prs <- polling cid cenv rks ExpectPactResult return prs - where - mkTransfer = do - t <- toTxCreationTime <$> tio - n <- readIORef nonceRef - c <- buildTextCmd - $ set cbSigners - [ mkSigner' sender00 - [ mkTransferCap "sender00" "sender01" 1.0 - , mkGasCap - ] - ] - $ set cbCreationTime t - $ set cbNetworkId (Just v) - $ mkCmd ("nonce-transfer-" <> sshow t <> "-" <> sshow n) - $ mkExec' "(coin.transfer \"sender00\" \"sender01\" 1.0)" - - modifyIORef' nonceRef (+1) - return $ SubmitBatch (pure c) -- | Transfer one, ignoring the resulting responses -- transferOne_ :: IO (Time Micros) -> ClientEnv -> IO () transferOne_ tio cenv = void $! transferOne tio cenv --- | Transfer one token from sender00 to sender01, polling for responses +-- | Build a simple transfer from sender00 to sender01 +-- +mkTransfer :: IO (Time Micros) -> IO SubmitBatch +mkTransfer tio = do + t <- toTxCreationTime <$> tio + n <- readIORef nonceRef + c <- buildTextCmd + $ set cbSigners + [ mkSigner' sender00 + [ mkTransferCap "sender00" "sender01" 1.0 + , mkGasCap + ] + ] + $ set cbCreationTime t + $ set cbNetworkId (Just v) + $ mkCmd ("nonce-transfer-" <> sshow t <> "-" <> sshow n) + $ mkExec' "(coin.transfer \"sender00\" \"sender01\" 1.0)" + + modifyIORef' nonceRef (+1) + return $ SubmitBatch (pure c) + +-- | Transfer one token from sender00 to sender01, applying some callback to +-- the command batch before sending. This is used for updating 'MVar's that +-- require request keys for rosetta tx submission in the mempool endpoints. -- transferOneAsync :: IO (Time Micros) @@ -384,27 +390,11 @@ transferOneAsync -> (RequestKeys -> IO ()) -> IO () transferOneAsync tio cenv callback = do - batch0 <- mkTransfer - rks <- sending cid cenv batch0 - void $! callback rks + batch0 <- mkTransfer tio + void $ callback (f batch0) + void $ sending cid cenv batch0 where - mkTransfer = do - t <- toTxCreationTime <$> tio - n <- readIORef nonceRef - c <- buildTextCmd - $ set cbSigners - [ mkSigner' sender00 - [ mkTransferCap "sender00" "sender01" 1.0 - , mkGasCap - ] - ] - $ set cbCreationTime t - $ set cbNetworkId (Just v) - $ mkCmd ("nonce-transfer-" <> sshow t <> "-" <> sshow n) - $ mkExec' "(coin.transfer \"sender00\" \"sender01\" 1.0)" - - modifyIORef' nonceRef (+1) - return $ SubmitBatch (pure c) + f (SubmitBatch cs) = RequestKeys (cmdToRequestKey <$> cs) -- ------------------------------------------------------------------ -- -- Utils From 0c67a2ac761bf639f8cad506106cb3bf61b94acf Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Fri, 26 Jun 2020 17:04:39 -0400 Subject: [PATCH 25/48] remove cruft, finish block tx test --- src/Chainweb/Mempool/InMem.hs | 1 - test/Chainweb/Test/RestAPI/Utils.hs | 41 +---- test/Chainweb/Test/Rosetta/RestAPI.hs | 213 ++++++++++++++++---------- test/ChainwebTests.hs | 7 +- 4 files changed, 142 insertions(+), 120 deletions(-) diff --git a/src/Chainweb/Mempool/InMem.hs b/src/Chainweb/Mempool/InMem.hs index 39c1b434c7..5a04837e4c 100644 --- a/src/Chainweb/Mempool/InMem.hs +++ b/src/Chainweb/Mempool/InMem.hs @@ -189,7 +189,6 @@ memberInMem :: MVar (InMemoryMempoolData t) memberInMem lock txs = do q <- withMVarMasked lock (readIORef . _inmemPending) V.mapM (memberOne q) txs - where memberOne q txHash = return $! HashMap.member txHash q diff --git a/test/Chainweb/Test/RestAPI/Utils.hs b/test/Chainweb/Test/RestAPI/Utils.hs index adb1b6a9c8..d373783d18 100644 --- a/test/Chainweb/Test/RestAPI/Utils.hs +++ b/test/Chainweb/Test/RestAPI/Utils.hs @@ -6,11 +6,13 @@ module Chainweb.Test.RestAPI.Utils ( -- * Retry Policies testRetryPolicy -, fastRetryPolicy + -- * Debugging , debug + -- * Utils , repeatUntil + -- * Pact client DSL , PactTestFailure(..) , PollingExpectation(..) @@ -19,6 +21,7 @@ module Chainweb.Test.RestAPI.Utils , spv , sending , polling + -- * Rosetta client DSL , RosettaTestException(..) , accountBalance @@ -27,7 +30,6 @@ module Chainweb.Test.RestAPI.Utils , constructionMetadata , constructionSubmit , mempoolTransaction -, mempoolTransactionWithFastRetry , mempool , networkOptions , networkList @@ -88,23 +90,6 @@ testRetryPolicy = stepped <> limitRetries 150 2 -> Just 100_000 _ -> Just 250_000 --- | Backoff up to a constant 25ms, limiting to 12s --- -fastRetryPolicy :: RetryPolicy -fastRetryPolicy = fastSteps <> limitRetries 500 - where - fastSteps = retryPolicy $ \rs -> case rsIterNumber rs of - 0 -> Just 100 - 1 -> Just 200 - 2 -> Just 300 - 3 -> Just 400 - 4 -> Just 500 - 5 -> Just 600 - 6 -> Just 700 - 7 -> Just 800 - 8 -> Just 900 - _ -> Just 25_000 - -- ------------------------------------------------------------------ -- -- Pact api client utils w/ retry @@ -374,24 +359,6 @@ mempoolTransaction cenv req = MempoolTransactionFailure _ -> return True _ -> return False -mempoolTransactionWithFastRetry - :: ClientEnv - -> MempoolTransactionReq - -> IO MempoolTransactionResp -mempoolTransactionWithFastRetry cenv req = - recovering fastRetryPolicy [h] $ \s -> do - debug - $ "requesting mempool transaction for " <> (show req) - <> " [" <> show (view rsIterNumberL s) <> "]" - - runClientM (rosettaMempoolTransactionApiClient v req) cenv >>= \case - Left e -> throwM $ MempoolTransactionFailure (show e) - Right t -> return t - where - h _ = Handler $ \case - MempoolTransactionFailure _ -> return True - _ -> return False - mempool :: ClientEnv -> MempoolReq diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index d636a0bf69..0836da3555 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -1,5 +1,6 @@ {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} @@ -76,8 +77,8 @@ type RosettaTest = IO (Time Micros) -> IO ClientEnv -> TestTree -- -------------------------------------------------------------------------- -- -- Test Tree -tests :: RocksDb -> TestTree -tests rdb = testGroup "Chainweb.Test.Rosetta.RestAPI" go +tests :: RocksDb -> ScheduledTest +tests rdb = testGroupSch "Chainweb.Test.Rosetta.RestAPI" go where go = return $ withNodes v "rosettaRemoteTests-" rdb nodes $ \envIo -> @@ -88,7 +89,7 @@ tests rdb = testGroup "Chainweb.Test.Rosetta.RestAPI" go , blockTransactionTests , blockTests , constructionSubmitTests - , mempoolTransactionTests + -- , mempoolTransactionTests , mempoolTests , networkListTests , networkOptionsTests @@ -105,7 +106,7 @@ accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step - checkBalance resp0 100000000.000 step "send 1.0 tokens to sender00 from sender01" - void $ transferOne tio cenv + transferOneAsync_ tio cenv (void . return) step "check post-transfer balance" resp1 <- accountBalance cenv req @@ -124,92 +125,130 @@ accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step - -- | Rosetta block transaction endpoint tests -- blockTransactionTests :: RosettaTest -blockTransactionTests tio envIo = +blockTransactionTests tio envIo = after AllSucceed "Account Balance" $ testCaseSteps "Block Transaction Tests" $ \step -> do cenv <- envIo + rkmv <- newEmptyMVar @RequestKeys - step "fetch genesis tx id" - -- resp <- blockTransaction cenv req + step "send 1.0 from sender00 to sender01 and extract block tx request" + prs <- transferOneAsync tio cenv (putMVar rkmv) + req <- mkTxReq rkmv prs + + step "send in block tx request" + resp <- blockTransaction cenv req + + (fundtx,cred,deb,redeem,reward) <- + case _transaction_operations $ _blockTransactionResp_transaction resp of + [a,b,c,d,e] -> return (a,b,c,d,e) + _ -> assertFailure "every transfer should result in 5 transactions" + + step "validate initial gas buy at index 0" + validateOp 0 "99999996890600000000" "FundTx" fundtx + + step "validate sender01 credit at index 1" + validateOp 1 "110000003000000000000" "TransferOrCreateAcct" cred + + step "validate sender00 debit at index 2" + validateOp 2 "99999995890600000000" "TransferOrCreateAcct" deb + + step "validate sender00 gas redemption at index 3" + validateOp 3 "99999996835900000000" "GasPayment" redeem + + step "validate miner gas reward at index 4" + validateOp 4 "7077669000000" "GasPayment" reward - return () where - req = BlockTransactionReq nid genesisId genesisTxId + mkTxReq rkmv prs = do + rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv + hm <- extractMetadata rk prs + bh <- hm ^?! ix "blockHeight" . to readAeson + bhash <- hm ^?! ix "blockHash" . to readAeson + + let bid = BlockId bh bhash + tid = rkToTransactionId rk + + return $ BlockTransactionReq nid bid tid + + validateOp idx amount opType o = do + _operation_operationId o @?= OperationId idx Nothing + _operation_type o @?= opType + _operation_status o @?= "Successful" + _operation_amount o @?= Just (Amount amount kda Nothing) + -- | Rosetta block endpoint tests -- blockTests :: RosettaTest -blockTests tio envIo = testCaseSteps "Block Tests" $ \step -> do - step "fetch genesis block" - cenv <- envIo - resp0 <- _block_blockId . _blockResp_block <$> block cenv (req 0) - resp0 @=? genesisId +blockTests tio envIo = after AllSucceed "Block Transaction Tests" $ + testCaseSteps "Block Tests" $ \step -> do + cenv <- envIo + rkmv <- newEmptyMVar @RequestKeys - step "send transaction" - prs <- transferOne tio cenv - cmdMeta <- extractMetadata prs - bh <- cmdMeta ^?! ix "blockHeight" . to fromAeson + step "fetch genesis block" + resp0 <- _block_blockId . _blockResp_block <$> block cenv (req 0) + resp0 @=? genesisId + + step "send transaction" + prs <- transferOneAsync tio cenv (putMVar rkmv) + rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv + cmdMeta <- extractMetadata rk prs + bh <- cmdMeta ^?! ix "blockHeight" . to readAeson - step "check tx at block height matches sent tx" - resp1 <- block cenv (req bh) + step "check tx at block height matches sent tx" + resp1 <- block cenv (req bh) - step "validate remediations at block height 1" - remResp <- block cenv (req 1) - -- check remediation tx id's - return () + step "validate remediations at block height 1" + remResp <- block cenv (req 1) + -- check remediation tx id's + return () where req h = BlockReq nid $ PartialBlockId (Just h) Nothing - fromAeson = aeson assertFailure return . A.fromJSON - - extractMetadata (PollResponses pr) = - case _crMetaData . snd . head . HM.toList $ pr of - Just (A.Object o) -> return o - _ -> assertFailure "test transfer did not succeed" - -- | Rosetta construction submit endpoint tests (i.e. tx submission directly to mempool) -- constructionSubmitTests :: RosettaTest -constructionSubmitTests tio envIo = +constructionSubmitTests tio envIo = after AllSucceed "Block Tests" $ testCaseSteps "Construction Submit Tests" $ \step -> return () --- | Rosetta mempool transaction endpoint tests --- -mempoolTransactionTests :: RosettaTest -mempoolTransactionTests tio envIo = - testCaseSteps "Mempool Transaction Tests" $ \step -> do - cenv <- envIo - rkmv <- newEmptyMVar @RequestKeys +-- -- | Rosetta mempool transaction endpoint tests +-- -- +-- -- (PENDING: the only way to test this is to DOS the mempool) +-- -- +-- mempoolTransactionTests :: RosettaTest +-- mempoolTransactionTests tio envIo = +-- testCaseSteps "Mempool Transaction Tests" $ \step -> do +-- cenv <- envIo +-- rkmv <- newEmptyMVar @RequestKeys - step "execute transfer and wait on mempool data" - void $! async $ transferOneAsync tio cenv (putMVar rkmv) +-- step "execute transfer and wait on mempool data" +-- void $! async $ transferOneAsync_ tio cenv (putMVar rkmv) - step "wait until mempool registers transfer" - rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv - MempoolTransactionResp tx _meta <- mempoolTransactionWithFastRetry cenv (req rk) +-- step "wait until mempool registers transfer" +-- rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv +-- MempoolTransactionResp tx _meta <- mempoolTransactionWithFastRetry cenv (req rk) - step "compare requestkey against transaction id" - rkToTransactionId rk @=? _transaction_transactionId tx - where - req rk = MempoolTransactionReq nid (rkToTransactionId rk) +-- step "compare requestkey against transaction id" +-- rkToTransactionId rk @=? _transaction_transactionId tx +-- where +-- req rk = MempoolTransactionReq nid (rkToTransactionId rk) -- | Rosetta mempool endpoint tests -- mempoolTests :: RosettaTest -mempoolTests tio envIo = testCaseSteps "Mempool Tests" $ \step -> do - cenv <- envIo - rkmv <- newEmptyMVar @RequestKeys - - step "execute transfer and wait on mempool data" - void $! async $ transferOneAsync tio cenv (putMVar rkmv) +mempoolTests tio envIo = after AllSucceed "Construction Submit Tests" $ + testCaseSteps "Mempool Tests" $ \step -> do + cenv <- envIo + rkmv <- newEmptyMVar @RequestKeys - let test (MempoolResp [_]) = return True - test (MempoolResp _) = return False + step "execute transfer and wait on mempool data" + void $! async $ transferOneAsync_ tio cenv (putMVar rkmv) + rk NEL.:| [] <- _rkRequestKeys <$> takeMVar rkmv - MempoolResp [tid] <- repeatUntil test $ mempool cenv req + let tid = rkToTransactionId rk + let test (MempoolResp ts) = return $ elem tid ts - step "compare requestkey against transaction id" - rk NEL.:| [] <- _rkRequestKeys <$> takeMVar rkmv - rkToTransactionId rk @=? tid + step "compare requestkey against mempool responses" + void $! repeatUntil test $ mempool cenv req where req = MempoolReq nid @@ -218,6 +257,7 @@ mempoolTests tio envIo = testCaseSteps "Mempool Tests" $ \step -> do networkListTests :: RosettaTest networkListTests _ envIo = testCaseSteps "Network List Tests" $ \step -> do cenv <- envIo + step "send network list request" resp <- networkList cenv req @@ -275,7 +315,7 @@ networkStatusTests tio envIo = testCaseSteps "Network Status Tests" $ \step -> d genesisId @=? _networkStatusResp_genesisBlockId resp0 step "send in a transaction and update current block" - transferOne_ tio cenv + transferOneAsync_ tio cenv (void . return) resp1 <- networkStatus cenv req step "check status response genesis and block height" @@ -326,9 +366,6 @@ rosettaVersion = RosettaNodeVersion ] } -genesisTxId :: TransactionId -genesisTxId = TransactionId "Inlsd2hVbVVBOUtnZjM5d191c2dGRHoycV9RX09YX1lMQmNDMXZBSC1Mc0Ei" - rosettaFailures :: [RosettaError] rosettaFailures = rosettaError <$> enumFrom RosettaChainUnspecified @@ -345,20 +382,6 @@ operationStatuses = -- ------------------------------------------------------------------ -- -- Test Pact Cmds --- | Transfer one token from sender00 to sender01, polling for responses --- -transferOne :: IO (Time Micros) -> ClientEnv -> IO PollResponses -transferOne tio cenv = do - batch0 <- mkTransfer tio - rks <- sending cid cenv batch0 - prs <- polling cid cenv rks ExpectPactResult - return prs - --- | Transfer one, ignoring the resulting responses --- -transferOne_ :: IO (Time Micros) -> ClientEnv -> IO () -transferOne_ tio cenv = void $! transferOne tio cenv - -- | Build a simple transfer from sender00 to sender01 -- mkTransfer :: IO (Time Micros) -> IO SubmitBatch @@ -388,16 +411,44 @@ transferOneAsync :: IO (Time Micros) -> ClientEnv -> (RequestKeys -> IO ()) - -> IO () + -> IO PollResponses transferOneAsync tio cenv callback = do batch0 <- mkTransfer tio - void $ callback (f batch0) - void $ sending cid cenv batch0 + void $! callback (f batch0) + rks <- sending cid cenv batch0 + prs <- polling cid cenv rks ExpectPactResult + return prs where f (SubmitBatch cs) = RequestKeys (cmdToRequestKey <$> cs) +transferOneAsync_ + :: IO (Time Micros) + -> ClientEnv + -> (RequestKeys -> IO ()) + -> IO () +transferOneAsync_ tio cenv callback + = void $! transferOneAsync tio cenv callback + -- ------------------------------------------------------------------ -- -- Utils + +-- | Extract poll response metadata at some request key +-- +extractMetadata :: RequestKey -> PollResponses -> IO (HM.HashMap Text A.Value) +extractMetadata rk (PollResponses pr) = case HM.lookup rk pr of + Just cr -> case _crMetaData cr of + Just (A.Object o) -> return o + _ -> assertFailure "impossible: empty metadata" + _ -> assertFailure "test transfer did not succeed" + +-- | Tell whether a list is a subset of +-- another list +-- subset :: (Foldable f, Eq a) => f a -> f a -> Bool subset as bs = all (`elem` bs) as + +-- | Decode a JSON value or fail as an assertion. Analogous to 'read' +-- +readAeson :: A.FromJSON b => A.Value -> IO b +readAeson = aeson assertFailure return . A.fromJSON diff --git a/test/ChainwebTests.hs b/test/ChainwebTests.hs index 9b2303ccfa..78d5c1d7a1 100644 --- a/test/ChainwebTests.hs +++ b/test/ChainwebTests.hs @@ -73,6 +73,7 @@ main = $ testGroup "Chainweb Tests" . schedule Sequential $ pactTestSuite rdb : mempoolTestSuite db h0 + : rosettaTestSuite rdb : suite rdb where adj NoTimeout = Timeout (1_000_000 * 60 * 10) "10m" @@ -96,6 +97,11 @@ pactTestSuite rdb = testGroupSch "Chainweb-Pact Tests" , Chainweb.Test.Pact.NoCoinbase.tests ] +rosettaTestSuite :: RocksDb -> ScheduledTest +rosettaTestSuite rdb = testGroupSch "Chainweb-Rosetta API Tests" $ schedule Sequential + [ Chainweb.Test.Rosetta.RestAPI.tests rdb + ] + suite :: RocksDb -> [ScheduledTest] suite rdb = [ testGroupSch "Chainweb Unit Tests" @@ -108,7 +114,6 @@ suite rdb = , Chainweb.Test.Store.CAS.FS.tests , Chainweb.Test.Roundtrips.tests , Chainweb.Test.Rosetta.tests - , Chainweb.Test.Rosetta.RestAPI.tests rdb , Chainweb.Test.RestAPI.tests rdb , Chainweb.Test.SPV.tests rdb , Chainweb.Test.Pact.SPV.tests From 02255497a68883418a163e19bfe730ac9d48df45 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Tue, 30 Jun 2020 16:54:34 -0400 Subject: [PATCH 26/48] add construction submit endpoint test --- test/Chainweb/Test/Rosetta/RestAPI.hs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 0836da3555..197cca382d 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -208,11 +208,31 @@ blockTests tio envIo = after AllSucceed "Block Transaction Tests" $ -- constructionSubmitTests :: RosettaTest constructionSubmitTests tio envIo = after AllSucceed "Block Tests" $ - testCaseSteps "Construction Submit Tests" $ \step -> return () + testCaseSteps "Construction Submit Tests" $ \step -> do + cenv <- envIo + + step "build one-off construction submit request" + SubmitBatch (c NEL.:| []) <- mkTransfer tio + + let rk = cmdToRequestKey c + req = ConstructionSubmitReq nid (encodeToText c) + + step "send construction submit request and poll on request key" + resp0 <- constructionSubmit cenv req + + _constructionSubmitResp_transactionId resp0 @?= rkToTransactionId rk + _constructionSubmitResp_metadata resp0 @?= Nothing + + step "confirm transaction details via poll" + PollResponses prs <- polling cid cenv (RequestKeys $ pure rk) ExpectPactResult + + case HM.lookup rk prs of + Nothing -> assertFailure $ "unable to find poll response for: " <> show rk + Just cr -> _crReqKey cr @?= rk -- -- | Rosetta mempool transaction endpoint tests -- -- --- -- (PENDING: the only way to test this is to DOS the mempool) +-- -- (PENDING: the only way to test this currently is to DOS the mempool) -- -- -- mempoolTransactionTests :: RosettaTest -- mempoolTransactionTests tio envIo = @@ -449,6 +469,7 @@ subset :: (Foldable f, Eq a) => f a -> f a -> Bool subset as bs = all (`elem` bs) as -- | Decode a JSON value or fail as an assertion. Analogous to 'read' +-- with failure assertion -- readAeson :: A.FromJSON b => A.Value -> IO b readAeson = aeson assertFailure return . A.fromJSON From efb45005841104fea5a409260edb13298bbcac47 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Tue, 30 Jun 2020 17:02:30 -0400 Subject: [PATCH 27/48] unnecessary scheduling --- src/Chainweb/Mempool/InMem.hs | 1 + src/Chainweb/Rosetta/RestAPI.hs | 1 - src/Chainweb/Rosetta/RestAPI/Server.hs | 1 - test/Chainweb/Test/Rosetta/RestAPI.hs | 3 +-- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Chainweb/Mempool/InMem.hs b/src/Chainweb/Mempool/InMem.hs index 5a04837e4c..39c1b434c7 100644 --- a/src/Chainweb/Mempool/InMem.hs +++ b/src/Chainweb/Mempool/InMem.hs @@ -189,6 +189,7 @@ memberInMem :: MVar (InMemoryMempoolData t) memberInMem lock txs = do q <- withMVarMasked lock (readIORef . _inmemPending) V.mapM (memberOne q) txs + where memberOne q txHash = return $! HashMap.member txHash q diff --git a/src/Chainweb/Rosetta/RestAPI.hs b/src/Chainweb/Rosetta/RestAPI.hs index 138d25873b..24e7a7c8fe 100644 --- a/src/Chainweb/Rosetta/RestAPI.hs +++ b/src/Chainweb/Rosetta/RestAPI.hs @@ -159,7 +159,6 @@ type RosettaNetworkListApi_ :> ReqBody '[JSON] MetadataReq :> Post '[JSON] NetworkListResp - type RosettaNetworkOptionsApi_ = "network" :> "options" diff --git a/src/Chainweb/Rosetta/RestAPI/Server.hs b/src/Chainweb/Rosetta/RestAPI/Server.hs index e32ee65720..7134e5a5f2 100644 --- a/src/Chainweb/Rosetta/RestAPI/Server.hs +++ b/src/Chainweb/Rosetta/RestAPI/Server.hs @@ -154,7 +154,6 @@ blockH blockH v cutDb ps crs (BlockReq net (PartialBlockId bheight bhash)) = runExceptT work >>= either throwRosetta pure where - block :: BlockHeader -> [Transaction] -> Block block bh txs = Block { _block_blockId = blockId bh diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 197cca382d..693f238a82 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -207,8 +207,7 @@ blockTests tio envIo = after AllSucceed "Block Transaction Tests" $ -- | Rosetta construction submit endpoint tests (i.e. tx submission directly to mempool) -- constructionSubmitTests :: RosettaTest -constructionSubmitTests tio envIo = after AllSucceed "Block Tests" $ - testCaseSteps "Construction Submit Tests" $ \step -> do +constructionSubmitTests tio envIo = testCaseSteps "Construction Submit Tests" $ \step -> do cenv <- envIo step "build one-off construction submit request" From d632f0f6db7bda166820f4ca7e30139a790cd20a Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Tue, 30 Jun 2020 18:29:10 -0400 Subject: [PATCH 28/48] done for the day --- test/Chainweb/Test/Rosetta/RestAPI.hs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 693f238a82..1c75c4af01 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -18,7 +18,6 @@ import qualified Data.Aeson as A import Data.Functor (void) import qualified Data.HashMap.Strict as HM import Data.IORef -import Data.List (union) import qualified Data.List.NonEmpty as NEL import Data.Text (Text) import Data.Foldable @@ -67,7 +66,7 @@ cid :: ChainId cid = unsafeChainId 0 cids :: [Text] -cids = chainIds v ^.. folded . to (sshow @Int . chainIdInt) +cids = chainIds v ^.. folded . to chainIdInt . to (sshow @Int) nonceRef :: IORef Natural nonceRef = unsafePerformIO $ newIORef 0 @@ -185,8 +184,8 @@ blockTests tio envIo = after AllSucceed "Block Transaction Tests" $ rkmv <- newEmptyMVar @RequestKeys step "fetch genesis block" - resp0 <- _block_blockId . _blockResp_block <$> block cenv (req 0) - resp0 @=? genesisId + resp0 <- block cenv (req 0) + (_block_blockId $ _blockResp_block resp0) @?= genesisId step "send transaction" prs <- transferOneAsync tio cenv (putMVar rkmv) @@ -196,6 +195,7 @@ blockTests tio envIo = after AllSucceed "Block Transaction Tests" $ step "check tx at block height matches sent tx" resp1 <- block cenv (req bh) + validateBlock rk cmdMeta resp1 step "validate remediations at block height 1" remResp <- block cenv (req 1) @@ -204,6 +204,11 @@ blockTests tio envIo = after AllSucceed "Block Transaction Tests" $ where req h = BlockReq nid $ PartialBlockId (Just h) Nothing + validateBlock rk meta resp = do + print resp + + + -- | Rosetta construction submit endpoint tests (i.e. tx submission directly to mempool) -- constructionSubmitTests :: RosettaTest @@ -309,7 +314,7 @@ networkOptionsTests _ envIo = testCaseSteps "Network Options Tests" $ \step -> d "allowable errors must coincide with failure list" step "Check that response statuses are a subset of valid statuses" - (_allow_operationStatuses allow `union` operationStatuses) `subset` operationStatuses @? + (_allow_operationStatuses allow `subset` operationStatuses) @? "allowed operation statuses coincide" step "Check that response op types are a subset of op types" @@ -451,7 +456,6 @@ transferOneAsync_ tio cenv callback -- ------------------------------------------------------------------ -- -- Utils - -- | Extract poll response metadata at some request key -- extractMetadata :: RequestKey -> PollResponses -> IO (HM.HashMap Text A.Value) From 2e36deb65943e870969ddd94dddff7c58253bdae Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Mon, 6 Jul 2020 15:16:22 -0400 Subject: [PATCH 29/48] last thing: remeds --- test/Chainweb/Test/Rosetta/RestAPI.hs | 126 ++++++++++++++++---------- 1 file changed, 79 insertions(+), 47 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 1c75c4af01..3c6196e657 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -5,6 +5,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} module Chainweb.Test.Rosetta.RestAPI ( tests ) where @@ -23,6 +24,7 @@ import Data.Text (Text) import Data.Foldable import GHC.Natural +import GHC.Word import Servant.Client @@ -53,6 +55,7 @@ import Rosetta import System.IO.Unsafe (unsafePerformIO) + -- -------------------------------------------------------------------------- -- -- Global Settings @@ -83,12 +86,17 @@ tests rdb = testGroupSch "Chainweb.Test.Rosetta.RestAPI" go withNodes v "rosettaRemoteTests-" rdb nodes $ \envIo -> withTime $ \tio -> testGroup "Rosetta API tests" (tgroup tio envIo) + -- Not supported: + -- + -- * Mempool Transaction: cant test reasonably without DOS'ing the mempool + -- * Construction Metadata: N/A + -- + tgroup tio envIo = fmap (\test -> test tio envIo) [ accountBalanceTests , blockTransactionTests , blockTests , constructionSubmitTests - -- , mempoolTransactionTests , mempoolTests , networkListTests , networkOptionsTests @@ -142,38 +150,32 @@ blockTransactionTests tio envIo = after AllSucceed "Account Balance" $ _ -> assertFailure "every transfer should result in 5 transactions" step "validate initial gas buy at index 0" - validateOp 0 "99999996890600000000" "FundTx" fundtx + validateOp 0 "99999996890600000000" "FundTx" "sender00" fundtx step "validate sender01 credit at index 1" - validateOp 1 "110000003000000000000" "TransferOrCreateAcct" cred + validateOp 1 "110000003000000000000" "TransferOrCreateAcct" "sender01" cred step "validate sender00 debit at index 2" - validateOp 2 "99999995890600000000" "TransferOrCreateAcct" deb + validateOp 2 "99999995890600000000" "TransferOrCreateAcct" "sender00" deb step "validate sender00 gas redemption at index 3" - validateOp 3 "99999996835900000000" "GasPayment" redeem + validateOp 3 "99999996835900000000" "GasPayment" "sender00" redeem step "validate miner gas reward at index 4" - validateOp 4 "7077669000000" "GasPayment" reward + validateOp 4 "7077669000000" "GasPayment" "NoMiner" reward where mkTxReq rkmv prs = do rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv - hm <- extractMetadata rk prs - bh <- hm ^?! ix "blockHeight" . to readAeson - bhash <- hm ^?! ix "blockHash" . to readAeson + meta <- extractMetadata rk prs + bh <- meta ^?! mix "blockHeight" + bhash <- meta ^?! mix "blockHash" let bid = BlockId bh bhash tid = rkToTransactionId rk return $ BlockTransactionReq nid bid tid - validateOp idx amount opType o = do - _operation_operationId o @?= OperationId idx Nothing - _operation_type o @?= opType - _operation_status o @?= "Successful" - _operation_amount o @?= Just (Amount amount kda Nothing) - -- | Rosetta block endpoint tests -- @@ -191,21 +193,44 @@ blockTests tio envIo = after AllSucceed "Block Transaction Tests" $ prs <- transferOneAsync tio cenv (putMVar rkmv) rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv cmdMeta <- extractMetadata rk prs - bh <- cmdMeta ^?! ix "blockHeight" . to readAeson + bh <- cmdMeta ^?! mix "blockHeight" step "check tx at block height matches sent tx" resp1 <- block cenv (req bh) - validateBlock rk cmdMeta resp1 + validateTransferResp bh resp1 step "validate remediations at block height 1" remResp <- block cenv (req 1) - -- check remediation tx id's + + print remResp return () where req h = BlockReq nid $ PartialBlockId (Just h) Nothing - validateBlock rk meta resp = do - print resp + validateTransferResp bh resp = do + _blockResp_otherTransactions resp @?= Nothing + + let validateBlock b = do + _block_metadata b @?= Nothing + _blockId_index (_block_blockId b) @?= bh + _blockId_index (_block_parentBlockId b) @?= (bh - 1) + + (cbase,fundtx,cred,deb,redeem,reward) <- + case _block_transactions b of + [x,y] -> case _transaction_operations x <> _transaction_operations y of + [a,b',c,d,e,f] -> return (a,b',c,d,e,f) + _ -> assertFailure "total tx # should be 6: coinbase + 5 for every tx" + _ -> assertFailure "every block should result in at least 2 transactions: coinbase + txs" + + validateOp 0 "4609046000000" "CoinbaseReward" "NoMiner" cbase + validateOp 0 "99999999000000000000" "FundTx" "sender00" fundtx + validateOp 1 "110000001000000000000" "TransferOrCreateAcct" "sender01" cred + validateOp 2 "99999998000000000000" "TransferOrCreateAcct" "sender00" deb + validateOp 3 "99999998945300000000" "GasPayment" "sender00" redeem + validateOp 4 "4663746000000" "GasPayment" "NoMiner" reward + + validateBlock $ _blockResp_block resp + @@ -234,28 +259,6 @@ constructionSubmitTests tio envIo = testCaseSteps "Construction Submit Tests" $ Nothing -> assertFailure $ "unable to find poll response for: " <> show rk Just cr -> _crReqKey cr @?= rk --- -- | Rosetta mempool transaction endpoint tests --- -- --- -- (PENDING: the only way to test this currently is to DOS the mempool) --- -- --- mempoolTransactionTests :: RosettaTest --- mempoolTransactionTests tio envIo = --- testCaseSteps "Mempool Transaction Tests" $ \step -> do --- cenv <- envIo --- rkmv <- newEmptyMVar @RequestKeys - --- step "execute transfer and wait on mempool data" --- void $! async $ transferOneAsync_ tio cenv (putMVar rkmv) - --- step "wait until mempool registers transfer" --- rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv --- MempoolTransactionResp tx _meta <- mempoolTransactionWithFastRetry cenv (req rk) - --- step "compare requestkey against transaction id" --- rkToTransactionId rk @=? _transaction_transactionId tx --- where --- req rk = MempoolTransactionReq nid (rkToTransactionId rk) - -- | Rosetta mempool endpoint tests -- mempoolTests :: RosettaTest @@ -377,7 +380,7 @@ aid = AccountId } genesisId :: BlockId -genesisId = BlockId 0 "d69wD5SUpshDI6rbmQGugDXTd1-riqr7gfg5ZjvUrqk" +genesisId = BlockId 0 "rdfJIktp_WL0oMr8Wr6lH49YkERAJ9MlFp0RPLMXPDE" rosettaVersion :: RosettaNodeVersion rosettaVersion = RosettaNodeVersion @@ -403,6 +406,27 @@ operationStatuses = , OperationStatus "TransferOrCreateAcct" True ] +-- | Validate all useful data for a tx operation +-- +validateOp + :: Word64 + -- ^ tx idx + -> Text + -- ^ operation amount + -> Text + -- ^ operation type + -> Text + -- ^ operation account name + -> Operation + -- ^ the op + -> Assertion +validateOp idx amount opType acct o = do + _operation_operationId o @?= OperationId idx Nothing + _operation_type o @?= opType + _operation_status o @?= "Successful" + _operation_amount o @?= Just (Amount amount kda Nothing) + _operation_account o @?= Just (AccountId acct Nothing Nothing) + -- ------------------------------------------------------------------ -- -- Test Pact Cmds @@ -471,8 +495,16 @@ extractMetadata rk (PollResponses pr) = case HM.lookup rk pr of subset :: (Foldable f, Eq a) => f a -> f a -> Bool subset as bs = all (`elem` bs) as --- | Decode a JSON value or fail as an assertion. Analogous to 'read' --- with failure assertion +-- | A composition of an index into a k-v structure with aeson values +-- and conversion to non-JSONified structured, asserting test failure if +-- it fails to decode as the give type @a@. -- -readAeson :: A.FromJSON b => A.Value -> IO b -readAeson = aeson assertFailure return . A.fromJSON +mix + :: forall a m + . ( A.FromJSON a + , Ixed m + , IxValue m ~ A.Value + ) + => Index m + -> Fold m (IO a) +mix i = ix i . to A.fromJSON . to (aeson assertFailure return) From fb738112bd78e543597224e5a5aa8fe87a692625 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Mon, 6 Jul 2020 17:12:13 -0400 Subject: [PATCH 30/48] use actual devnet remediations (hash-changing update) --- .../remediations/testnet/remediations.yaml | 6 +++++ .../Transactions/DevelopmentTransactions.hs | 2 +- .../Transactions/FastTimedCPMTransactions.hs | 22 +++++++++++++++++++ .../Pact/Transactions/OtherTransactions.hs | 2 ++ test/Chainweb/Test/Rosetta/RestAPI.hs | 21 ++++++++++-------- tools/ea/Ea.hs | 6 +++-- 6 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 pact/coin-contract/remediations/testnet/remediations.yaml create mode 100644 src/Chainweb/Pact/Transactions/FastTimedCPMTransactions.hs diff --git a/pact/coin-contract/remediations/testnet/remediations.yaml b/pact/coin-contract/remediations/testnet/remediations.yaml new file mode 100644 index 0000000000..c435a0a1b1 --- /dev/null +++ b/pact/coin-contract/remediations/testnet/remediations.yaml @@ -0,0 +1,6 @@ +# testnet remediations + +code: |- + (coin.remediate "sender00" 1337.7) +nonce: testnet-other-remediations +keyPairs: [] \ No newline at end of file diff --git a/src/Chainweb/Pact/Transactions/DevelopmentTransactions.hs b/src/Chainweb/Pact/Transactions/DevelopmentTransactions.hs index afa88a3f4e..bf87add20a 100644 --- a/src/Chainweb/Pact/Transactions/DevelopmentTransactions.hs +++ b/src/Chainweb/Pact/Transactions/DevelopmentTransactions.hs @@ -18,5 +18,5 @@ transactions = , "eyJoYXNoIjoibVZzMjNxNnJyUjZrWDFGX0ItamNCX05hLXdZdmR3dnRwa1cwQVNaZExjRSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihtb2R1bGUgY29pbiBHT1ZFUk5BTkNFXFxuXFxuICBAZG9jIFxcXCInY29pbicgcmVwcmVzZW50cyB0aGUgS2FkZW5hIENvaW4gQ29udHJhY3QuIFRoaXMgY29udHJhY3QgcHJvdmlkZXMgYm90aCB0aGUgXFxcXFxcbiAgXFxcXGJ1eS9yZWRlZW0gZ2FzIHN1cHBvcnQgaW4gdGhlIGZvcm0gb2YgJ2Z1bmQtdHgnLCBhcyB3ZWxsIGFzIHRyYW5zZmVyLCAgICAgICBcXFxcXFxuICBcXFxcY3JlZGl0LCBkZWJpdCwgY29pbmJhc2UsIGFjY291bnQgY3JlYXRpb24gYW5kIHF1ZXJ5LCBhcyB3ZWxsIGFzIFNQViBidXJuICAgIFxcXFxcXG4gIFxcXFxjcmVhdGUuIFRvIGFjY2VzcyB0aGUgY29pbiBjb250cmFjdCwgeW91IG1heSB1c2UgaXRzIGZ1bGx5LXF1YWxpZmllZCBuYW1lLCAgXFxcXFxcbiAgXFxcXG9yIGlzc3VlIHRoZSAnKHVzZSBjb2luKScgY29tbWFuZCBpbiB0aGUgYm9keSBvZiBhIG1vZHVsZSBkZWNsYXJhdGlvbi5cXFwiXFxuXFxuICBAbW9kZWxcXG4gICAgWyAoZGVmcHJvcGVydHkgY29uc2VydmVzLW1hc3NcXG4gICAgICAgICg9IChjb2x1bW4tZGVsdGEgY29pbi10YWJsZSAnYmFsYW5jZSkgMC4wKSlcXG5cXG4gICAgICAoZGVmcHJvcGVydHkgdmFsaWQtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgICAgICAoYW5kXFxuICAgICAgICAgICg-PSAobGVuZ3RoIGFjY291bnQpIDMpXFxuICAgICAgICAgICg8PSAobGVuZ3RoIGFjY291bnQpIDI1NikpKVxcbiAgICBdXFxuXFxuICAoaW1wbGVtZW50cyBmdW5naWJsZS12MilcXG5cXG4gIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cXG4gIDsgU2NoZW1hcyBhbmQgVGFibGVzXFxuXFxuICAoZGVmc2NoZW1hIGNvaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlRoZSBjb2luIGNvbnRyYWN0IHRva2VuIHNjaGVtYVxcXCJcXG4gICAgQG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBndWFyZDpndWFyZClcXG5cXG4gIChkZWZ0YWJsZSBjb2luLXRhYmxlOntjb2luLXNjaGVtYX0pXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENhcGFiaWxpdGllc1xcblxcbiAgKGRlZmNhcCBHT1ZFUk5BTkNFICgpXFxuICAgIChlbmZvcmNlIGZhbHNlIFxcXCJFbmZvcmNlIG5vbi11cGdyYWRlYWJpbGl0eVxcXCIpKVxcblxcbiAgKGRlZmNhcCBHQVMgKClcXG4gICAgXFxcIk1hZ2ljIGNhcGFiaWxpdHkgdG8gcHJvdGVjdCBnYXMgYnV5IGFuZCByZWRlZW1cXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIENPSU5CQVNFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IHRvIHByb3RlY3QgbWluZXIgcmV3YXJkXFxcIlxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBHRU5FU0lTICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGNvbnN0cmFpbmluZyBnZW5lc2lzIHRyYW5zYWN0aW9uc1xcXCJcXG4gICAgdHJ1ZSlcXG5cXG4gIChkZWZjYXAgUkVNRURJQVRFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnNcXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIERFQklUIChzZW5kZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgZGViaXRpbmcgb3BlcmF0aW9uc1xcXCJcXG4gICAgKGVuZm9yY2UtZ3VhcmQgKGF0ICdndWFyZCAocmVhZCBjb2luLXRhYmxlIHNlbmRlcikpKVxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIFxcXCJcXFwiKSBcXFwidmFsaWQgc2VuZGVyXFxcIikpXFxuXFxuICAoZGVmY2FwIENSRURJVCAocmVjZWl2ZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgY3JlZGl0aW5nIG9wZXJhdGlvbnNcXFwiXFxuICAgIChlbmZvcmNlICghPSByZWNlaXZlciBcXFwiXFxcIikgXFxcInZhbGlkIHJlY2VpdmVyXFxcIikpXFxuXFxuICAoZGVmY2FwIFJPVEFURSAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkF1dG9ub21vdXNseSBtYW5hZ2VkIGNhcGFiaWxpdHkgZm9yIGd1YXJkIHJvdGF0aW9uXFxcIlxcbiAgICBAbWFuYWdlZFxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBUUkFOU0ZFUjpib29sXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsXFxuICAgIClcXG4gICAgQG1hbmFnZWQgYW1vdW50IFRSQU5TRkVSLW1nclxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIHJlY2VpdmVyKSBcXFwic2FtZSBzZW5kZXIgYW5kIHJlY2VpdmVyXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApIFxcXCJQb3NpdGl2ZSBhbW91bnRcXFwiKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChDUkVESVQgcmVjZWl2ZXIpKVxcbiAgKVxcblxcbiAgKGRlZnVuIFRSQU5TRkVSLW1ncjpkZWNpbWFsXFxuICAgICggbWFuYWdlZDpkZWNpbWFsXFxuICAgICAgcmVxdWVzdGVkOmRlY2ltYWxcXG4gICAgKVxcblxcbiAgICAobGV0ICgobmV3YmFsICgtIG1hbmFnZWQgcmVxdWVzdGVkKSkpXFxuICAgICAgKGVuZm9yY2UgKD49IG5ld2JhbCAwLjApXFxuICAgICAgICAoZm9ybWF0IFxcXCJUUkFOU0ZFUiBleGNlZWRlZCBmb3IgYmFsYW5jZSB7fVxcXCIgW21hbmFnZWRdKSlcXG4gICAgICBuZXdiYWwpXFxuICApXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvbnN0YW50c1xcblxcbiAgKGRlZmNvbnN0IENPSU5fQ0hBUlNFVCBDSEFSU0VUX0xBVElOMVxcbiAgICBcXFwiVGhlIGRlZmF1bHQgY29pbiBjb250cmFjdCBjaGFyYWN0ZXIgc2V0XFxcIilcXG5cXG4gIChkZWZjb25zdCBNSU5JTVVNX1BSRUNJU0lPTiAxMlxcbiAgICBcXFwiTWluaW11bSBhbGxvd2VkIHByZWNpc2lvbiBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiKVxcblxcbiAgKGRlZmNvbnN0IE1JTklNVU1fQUNDT1VOVF9MRU5HVEggM1xcbiAgICBcXFwiTWluaW11bSBhY2NvdW50IGxlbmd0aCBhZG1pc3NpYmxlIGZvciBjb2luIGFjY291bnRzXFxcIilcXG5cXG4gIChkZWZjb25zdCBNQVhJTVVNX0FDQ09VTlRfTEVOR1RIIDI1NlxcbiAgICBcXFwiTWF4aW11bSBhY2NvdW50IG5hbWUgbGVuZ3RoIGFkbWlzc2libGUgZm9yIGNvaW4gYWNjb3VudHNcXFwiKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBVdGlsaXRpZXNcXG5cXG4gIChkZWZ1biBlbmZvcmNlLXVuaXQ6Ym9vbCAoYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgbWluaW11bSBwcmVjaXNpb24gYWxsb3dlZCBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiXFxuXFxuICAgIChlbmZvcmNlXFxuICAgICAgKD0gKGZsb29yIGFtb3VudCBNSU5JTVVNX1BSRUNJU0lPTilcXG4gICAgICAgICBhbW91bnQpXFxuICAgICAgKGZvcm1hdCBcXFwiQW1vdW50IHZpb2xhdGVzIG1pbmltdW0gcHJlY2lzaW9uOiB7fVxcXCIgW2Ftb3VudF0pKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdmFsaWRhdGUtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgdGhhdCBhbiBhY2NvdW50IG5hbWUgY29uZm9ybXMgdG8gdGhlIGNvaW4gY29udHJhY3QgXFxcXFxcbiAgICAgICAgIFxcXFxtaW5pbXVtIGFuZCBtYXhpbXVtIGxlbmd0aCByZXF1aXJlbWVudHMsIGFzIHdlbGwgYXMgdGhlICAgIFxcXFxcXG4gICAgICAgICBcXFxcbGF0aW4tMSBjaGFyYWN0ZXIgc2V0LlxcXCJcXG5cXG4gICAgKGVuZm9yY2VcXG4gICAgICAoaXMtY2hhcnNldCBDT0lOX0NIQVJTRVQgYWNjb3VudClcXG4gICAgICAoZm9ybWF0XFxuICAgICAgICBcXFwiQWNjb3VudCBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBjb2luIGNvbnRyYWN0IGNoYXJzZXQ6IHt9XFxcIlxcbiAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgKGxldCAoKGFjY291bnQtbGVuZ3RoIChsZW5ndGggYWNjb3VudCkpKVxcblxcbiAgICAgIChlbmZvcmNlXFxuICAgICAgICAoPj0gYWNjb3VudC1sZW5ndGggTUlOSU1VTV9BQ0NPVU5UX0xFTkdUSClcXG4gICAgICAgIChmb3JtYXRcXG4gICAgICAgICAgXFxcIkFjY291bnQgbmFtZSBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBtaW4gbGVuZ3RoIHJlcXVpcmVtZW50OiB7fVxcXCJcXG4gICAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgICAoZW5mb3JjZVxcbiAgICAgICAgKDw9IGFjY291bnQtbGVuZ3RoIE1BWElNVU1fQUNDT1VOVF9MRU5HVEgpXFxuICAgICAgICAoZm9ybWF0XFxuICAgICAgICAgIFxcXCJBY2NvdW50IG5hbWUgZG9lcyBub3QgY29uZm9ybSB0byB0aGUgbWF4IGxlbmd0aCByZXF1aXJlbWVudDoge31cXFwiXFxuICAgICAgICAgIFthY2NvdW50XSkpXFxuICAgICAgKVxcbiAgKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBDb2luIENvbnRyYWN0XFxuXFxuICAoZGVmdW4gZ2FzLW9ubHkgKClcXG4gICAgXFxcIlByZWRpY2F0ZSBmb3IgZ2FzLW9ubHkgdXNlciBndWFyZHMuXFxcIlxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKSlcXG5cXG4gIChkZWZ1biBnYXMtZ3VhcmQgKGd1YXJkOmd1YXJkKVxcbiAgICBcXFwiUHJlZGljYXRlIGZvciBnYXMgKyBzaW5nbGUga2V5IHVzZXIgZ3VhcmRzXFxcIlxcbiAgICAoZW5mb3JjZS1vbmVcXG4gICAgICBcXFwiRW5mb3JjZSBlaXRoZXIgdGhlIHByZXNlbmNlIG9mIGEgR0FTIGNhcCBvciBrZXlzZXRcXFwiXFxuICAgICAgWyAoZ2FzLW9ubHkpXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG4gICAgICBdKSlcXG5cXG4gIChkZWZ1biBidXktZ2FzOnN0cmluZyAoc2VuZGVyOnN0cmluZyB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCJUaGlzIGZ1bmN0aW9uIGRlc2NyaWJlcyB0aGUgbWFpbiAnZ2FzIGJ1eScgb3BlcmF0aW9uLiBBdCB0aGlzIHBvaW50IFxcXFxcXG4gICAgXFxcXE1JTkVSIGhhcyBiZWVuIGNob3NlbiBmcm9tIHRoZSBwb29sLCBhbmQgd2lsbCBiZSB2YWxpZGF0ZWQuIFRoZSBTRU5ERVIgICBcXFxcXFxuICAgIFxcXFxvZiB0aGlzIHRyYW5zYWN0aW9uIGhhcyBzcGVjaWZpZWQgYSBnYXMgbGltaXQgTElNSVQgKG1heGltdW0gZ2FzKSBmb3IgICAgXFxcXFxcbiAgICBcXFxcdGhlIHRyYW5zYWN0aW9uLCBhbmQgdGhlIHByaWNlIGlzIHRoZSBzcG90IHByaWNlIG9mIGdhcyBhdCB0aGF0IHRpbWUuICAgIFxcXFxcXG4gICAgXFxcXFRoZSBnYXMgYnV5IHdpbGwgYmUgZXhlY3V0ZWQgcHJpb3IgdG8gZXhlY3V0aW5nIFNFTkRFUidzIGNvZGUuXFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCB0b3RhbClcXG4gICAgKGVuZm9yY2UgKD4gdG90YWwgMC4wKSBcXFwiZ2FzIHN1cHBseSBtdXN0IGJlIGEgcG9zaXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuICAgICAgKGRlYml0IHNlbmRlciB0b3RhbCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZWRlZW0tZ2FzOnN0cmluZyAobWluZXI6c3RyaW5nIG1pbmVyLWd1YXJkOmd1YXJkIHNlbmRlcjpzdHJpbmcgdG90YWw6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiVGhpcyBmdW5jdGlvbiBkZXNjcmliZXMgdGhlIG1haW4gJ3JlZGVlbSBnYXMnIG9wZXJhdGlvbi4gQXQgdGhpcyAgICBcXFxcXFxuICAgIFxcXFxwb2ludCwgdGhlIFNFTkRFUidzIHRyYW5zYWN0aW9uIGhhcyBiZWVuIGV4ZWN1dGVkLCBhbmQgdGhlIGdhcyB0aGF0ICAgICAgXFxcXFxcbiAgICBcXFxcd2FzIGNoYXJnZWQgaGFzIGJlZW4gY2FsY3VsYXRlZC4gTUlORVIgd2lsbCBiZSBjcmVkaXRlZCB0aGUgZ2FzIGNvc3QsICAgIFxcXFxcXG4gICAgXFxcXGFuZCBTRU5ERVIgd2lsbCByZWNlaXZlIHRoZSByZW1haW5kZXIgdXAgdG8gdGhlIGxpbWl0XFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBtaW5lcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG4gICAgKHZhbGlkYXRlLWFjY291bnQgbWluZXIpXFxuICAgIChlbmZvcmNlLXVuaXQgdG90YWwpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKEdBUykpXFxuICAgIChsZXQqXFxuICAgICAgKChmZWUgKHJlYWQtZGVjaW1hbCBcXFwiZmVlXFxcIikpXFxuICAgICAgIChyZWZ1bmQgKC0gdG90YWwgZmVlKSkpXFxuXFxuICAgICAgKGVuZm9yY2UtdW5pdCBmZWUpXFxuICAgICAgKGVuZm9yY2UgKD49IGZlZSAwLjApXFxuICAgICAgICBcXFwiZmVlIG11c3QgYmUgYSBub24tbmVnYXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAgIChlbmZvcmNlICg-PSByZWZ1bmQgMC4wKVxcbiAgICAgICAgXFxcInJlZnVuZCBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIHF1YW50aXR5XFxcIilcXG5cXG4gICAgICAgIDsgZGlyZWN0bHkgdXBkYXRlIGluc3RlYWQgb2YgY3JlZGl0XFxuICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHNlbmRlcilcXG4gICAgICAgIChpZiAoPiByZWZ1bmQgMC4wKVxcbiAgICAgICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgc2VuZGVyXFxuICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOj0gYmFsYW5jZSB9XFxuICAgICAgICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIHNlbmRlclxcbiAgICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCI6ICgrIGJhbGFuY2UgcmVmdW5kKSB9KSlcXG5cXG4gICAgICAgICAgXFxcIm5vb3BcXFwiKSlcXG5cXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChDUkVESVQgbWluZXIpXFxuICAgICAgICAoaWYgKD4gZmVlIDAuMClcXG4gICAgICAgICAgKGNyZWRpdCBtaW5lciBtaW5lci1ndWFyZCBmZWUpXFxuICAgICAgICAgIFxcXCJub29wXFxcIikpXFxuICAgICAgKVxcblxcbiAgICApXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFjY291bnQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZClcXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKSBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChpbnNlcnQgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgICA6IGd1YXJkXFxuICAgICAgfSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGdldC1iYWxhbmNlOmRlY2ltYWwgKGFjY291bnQ6c3RyaW5nKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcbiAgICAgIGJhbGFuY2VcXG4gICAgICApXFxuICAgIClcXG5cXG4gIChkZWZ1biBkZXRhaWxzOm9iamVjdHtmdW5naWJsZS12Mi5hY2NvdW50LWRldGFpbHN9XFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIiA6PSBnIH1cXG4gICAgICB7IFxcXCJhY2NvdW50XFxcIiA6IGFjY291bnRcXG4gICAgICAsIFxcXCJiYWxhbmNlXFxcIiA6IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIjogZyB9KVxcbiAgICApXFxuXFxuICAoZGVmdW4gcm90YXRlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgbmV3LWd1YXJkOmd1YXJkKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChST1RBVEUgYWNjb3VudClcXG4gICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IG9sZC1ndWFyZCB9XFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBvbGQtZ3VhcmQpXFxuXFxuICAgICAgICAodXBkYXRlIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgICB7IFxcXCJndWFyZFxcXCIgOiBuZXctZ3VhcmQgfVxcbiAgICAgICAgICApKSlcXG4gICAgKVxcblxcblxcbiAgKGRlZnVuIHByZWNpc2lvbjppbnRlZ2VyXFxuICAgICgpXFxuICAgIE1JTklNVU1fUFJFQ0lTSU9OKVxcblxcbiAgKGRlZnVuIHRyYW5zZmVyOnN0cmluZyAoc2VuZGVyOnN0cmluZyByZWNlaXZlcjpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcylcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgcmVjZWl2ZXIpKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgICh3aXRoLXJlYWQgY29pbi10YWJsZSByZWNlaXZlclxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IGcgfVxcblxcbiAgICAgICAgKGNyZWRpdCByZWNlaXZlciBnIGFtb3VudCkpXFxuICAgICAgKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdHJhbnNmZXItY3JlYXRlOnN0cmluZ1xcbiAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5IGNvbnNlcnZlcy1tYXNzKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgIChjcmVkaXQgcmVjZWl2ZXIgcmVjZWl2ZXItZ3VhcmQgYW1vdW50KSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGNvaW5iYXNlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYWNjb3VudC1ndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiSW50ZXJuYWwgZnVuY3Rpb24gZm9yIHRoZSBpbml0aWFsIGNyZWF0aW9uIG9mIGNvaW5zLiAgVGhpcyBmdW5jdGlvbiBcXFxcXFxuICAgIFxcXFxjYW5ub3QgYmUgdXNlZCBvdXRzaWRlIG9mIHRoZSBjb2luIGNvbnRyYWN0LlxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKD4gYW1vdW50IDAuMCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChDT0lOQkFTRSkpXFxuICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgIChjcmVkaXQgYWNjb3VudCBhY2NvdW50LWd1YXJkIGFtb3VudCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZW1lZGlhdGU6c3RyaW5nIChhY2NvdW50OnN0cmluZyBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQWxsb3dzIGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnMuIFRoaXMgZnVuY3Rpb24gXFxcXFxcbiAgICAgICAgIFxcXFxpcyBwcm90ZWN0ZWQgYnkgdGhlIFJFTUVESUFURSBjYXBhYmlsaXR5XFxcIlxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG5cXG4gICAgKGVuZm9yY2UgKD4gYW1vdW50IDAuMClcXG4gICAgICBcXFwiUmVtZWRpYXRpb24gYW1vdW50IG11c3QgYmUgcG9zaXRpdmVcXFwiKVxcblxcbiAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgKHJlcXVpcmUtY2FwYWJpbGl0eSAoUkVNRURJQVRFKSlcXG4gICAgKHdpdGgtcmVhZCBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6PSBiYWxhbmNlIH1cXG5cXG4gICAgICAoZW5mb3JjZSAoPD0gYW1vdW50IGJhbGFuY2UpIFxcXCJJbnN1ZmZpY2llbnQgZnVuZHNcXFwiKVxcblxcbiAgICAgICh1cGRhdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgtIGJhbGFuY2UgYW1vdW50KSB9XFxuICAgICAgICApKVxcbiAgICApXFxuXFxuICAoZGVmcGFjdCBmdW5kLXR4IChzZW5kZXI6c3RyaW5nIG1pbmVyOnN0cmluZyBtaW5lci1ndWFyZDpndWFyZCB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCInZnVuZC10eCcgaXMgYSBzcGVjaWFsIHBhY3QgdG8gZnVuZCBhIHRyYW5zYWN0aW9uIGluIHR3byBzdGVwcywgICAgIFxcXFxcXG4gICAgXFxcXHdpdGggdGhlIGFjdHVhbCB0cmFuc2FjdGlvbiB0cmFuc3BpcmluZyBpbiB0aGUgbWlkZGxlOiAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXFxcXFxcbiAgICBcXFxcICAxKSBBIGJ1eWluZyBwaGFzZSwgZGViaXRpbmcgdGhlIHNlbmRlciBmb3IgdG90YWwgZ2FzIGFuZCBmZWUsIHlpZWxkaW5nIFxcXFxcXG4gICAgXFxcXCAgICAgVFhfTUFYX0NIQVJHRS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgIDIpIEEgc2V0dGxlbWVudCBwaGFzZSwgcmVzdW1pbmcgVFhfTUFYX0NIQVJHRSwgYW5kIGFsbG9jYXRpbmcgdG8gdGhlICAgXFxcXFxcbiAgICBcXFxcICAgICBjb2luYmFzZSBhY2NvdW50IGZvciB1c2VkIGdhcyBhbmQgZmVlLCBhbmQgc2VuZGVyIGFjY291bnQgZm9yIGJhbC0gIFxcXFxcXG4gICAgXFxcXCAgICAgYW5jZSAodW51c2VkIGdhcywgaWYgYW55KS5cXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiB0b3RhbCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IG1pbmVyKSlcXG4gICAgICAgICAgICAgOyhwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcykgbm90IHN1cHBvcnRlZCB5ZXRcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXAgKGJ1eS1nYXMgc2VuZGVyIHRvdGFsKSlcXG4gICAgKHN0ZXAgKHJlZGVlbS1nYXMgbWluZXIgbWluZXItZ3VhcmQgc2VuZGVyIHRvdGFsKSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGRlYml0OnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkRlYml0IEFNT1VOVCBmcm9tIEFDQ09VTlQgYmFsYW5jZVxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApXFxuICAgICAgXFxcImRlYml0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKERFQklUIGFjY291bnQpKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcblxcbiAgICAgIChlbmZvcmNlICg8PSBhbW91bnQgYmFsYW5jZSkgXFxcIkluc3VmZmljaWVudCBmdW5kc1xcXCIpXFxuXFxuICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogKC0gYmFsYW5jZSBhbW91bnQpIH1cXG4gICAgICAgICkpXFxuICAgIClcXG5cXG5cXG4gIChkZWZ1biBjcmVkaXQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQ3JlZGl0IEFNT1VOVCB0byBBQ0NPVU5UIGJhbGFuY2VcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKSBcXFwiY3JlZGl0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KSlcXG4gICAgKHdpdGgtZGVmYXVsdC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogMC4wLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmQgfVxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UsIFxcXCJndWFyZFxcXCIgOj0gcmV0ZyB9XFxuICAgICAgOyB3ZSBkb24ndCB3YW50IHRvIG92ZXJ3cml0ZSBhbiBleGlzdGluZyBndWFyZCB3aXRoIHRoZSB1c2VyLXN1cHBsaWVkIG9uZVxcbiAgICAgIChlbmZvcmNlICg9IHJldGcgZ3VhcmQpXFxuICAgICAgICBcXFwiYWNjb3VudCBndWFyZHMgZG8gbm90IG1hdGNoXFxcIilcXG5cXG4gICAgICAod3JpdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgrIGJhbGFuY2UgYW1vdW50KVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiICAgOiByZXRnXFxuICAgICAgICB9KVxcbiAgICAgICkpXFxuXFxuXFxuICAoZGVmc2NoZW1hIGNyb3NzY2hhaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlNjaGVtYSBmb3IgeWllbGRlZCB2YWx1ZSBpbiBjcm9zcy1jaGFpbiB0cmFuc2ZlcnNcXFwiXFxuICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICBhbW91bnQ6ZGVjaW1hbClcXG5cXG4gIChkZWZwYWN0IHRyYW5zZmVyLWNyb3NzY2hhaW46c3RyaW5nXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyLWd1YXJkOmd1YXJkXFxuICAgICAgdGFyZ2V0LWNoYWluOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXBcXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCByZWNlaXZlcilcXG5cXG4gICAgICAgIChlbmZvcmNlICghPSBcXFwiXFxcIiB0YXJnZXQtY2hhaW4pIFxcXCJlbXB0eSB0YXJnZXQtY2hhaW5cXFwiKVxcbiAgICAgICAgKGVuZm9yY2UgKCE9IChhdCAnY2hhaW4taWQgKGNoYWluLWRhdGEpKSB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgIFxcXCJjYW5ub3QgcnVuIGNyb3NzLWNoYWluIHRyYW5zZmVycyB0byB0aGUgc2FtZSBjaGFpblxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgICAgICBcXFwidHJhbnNmZXIgcXVhbnRpdHkgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgICAgIDs7IHN0ZXAgMSAtIGRlYml0IGRlbGV0ZS1hY2NvdW50IG9uIGN1cnJlbnQgY2hhaW5cXG4gICAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcblxcbiAgICAgICAgKGxldFxcbiAgICAgICAgICAoKGNyb3NzY2hhaW4tZGV0YWlsczpvYmplY3R7Y3Jvc3NjaGFpbi1zY2hlbWF9XFxuICAgICAgICAgICAgeyBcXFwicmVjZWl2ZXJcXFwiIDogcmVjZWl2ZXJcXG4gICAgICAgICAgICAsIFxcXCJyZWNlaXZlci1ndWFyZFxcXCIgOiByZWNlaXZlci1ndWFyZFxcbiAgICAgICAgICAgICwgXFxcImFtb3VudFxcXCIgOiBhbW91bnRcXG4gICAgICAgICAgICB9KSlcXG4gICAgICAgICAgKHlpZWxkIGNyb3NzY2hhaW4tZGV0YWlscyB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgICkpKVxcblxcbiAgICAoc3RlcFxcbiAgICAgIChyZXN1bWVcXG4gICAgICAgIHsgXFxcInJlY2VpdmVyXFxcIiA6PSByZWNlaXZlclxcbiAgICAgICAgLCBcXFwicmVjZWl2ZXItZ3VhcmRcXFwiIDo9IHJlY2VpdmVyLWd1YXJkXFxuICAgICAgICAsIFxcXCJhbW91bnRcXFwiIDo9IGFtb3VudFxcbiAgICAgICAgfVxcblxcbiAgICAgICAgOzsgc3RlcCAyIC0gY3JlZGl0IGNyZWF0ZSBhY2NvdW50IG9uIHRhcmdldCBjaGFpblxcbiAgICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHJlY2VpdmVyKVxcbiAgICAgICAgICAoY3JlZGl0IHJlY2VpdmVyIHJlY2VpdmVyLWd1YXJkIGFtb3VudCkpXFxuICAgICAgICApKVxcbiAgICApXFxuXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvaW4gYWxsb2NhdGlvbnNcXG5cXG4gIChkZWZzY2hlbWEgYWxsb2NhdGlvbi1zY2hlbWFcXG4gICAgQGRvYyBcXFwiR2VuZXNpcyBhbGxvY2F0aW9uIHJlZ2lzdHJ5XFxcIlxcbiAgICA7QG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBkYXRlOnRpbWVcXG4gICAgZ3VhcmQ6Z3VhcmRcXG4gICAgcmVkZWVtZWQ6Ym9vbClcXG5cXG4gIChkZWZ0YWJsZSBhbGxvY2F0aW9uLXRhYmxlOnthbGxvY2F0aW9uLXNjaGVtYX0pXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFsbG9jYXRpb24tYWNjb3VudFxcbiAgICAoIGFjY291bnQ6c3RyaW5nXFxuICAgICAgZGF0ZTp0aW1lXFxuICAgICAga2V5c2V0LXJlZjpzdHJpbmdcXG4gICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICApXFxuXFxuICAgIEBkb2MgXFxcIkFkZCBhbiBlbnRyeSB0byB0aGUgY29pbiBhbGxvY2F0aW9uIHRhYmxlLiBUaGlzIGZ1bmN0aW9uIFxcXFxcXG4gICAgICAgICBcXFxcYWxzbyBjcmVhdGVzIGEgY29ycmVzcG9uZGluZyBlbXB0eSBjb2luIGNvbnRyYWN0IGFjY291bnQgXFxcXFxcbiAgICAgICAgIFxcXFxvZiB0aGUgc2FtZSBuYW1lIGFuZCBndWFyZC4gUmVxdWlyZXMgR0VORVNJUyBjYXBhYmlsaXR5LiBcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHRU5FU0lTKSlcXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG4gICAgKGVuZm9yY2UgKD49IGFtb3VudCAwLjApXFxuICAgICAgXFxcImFsbG9jYXRpb24gYW1vdW50IG11c3QgYmUgbm9uLW5lZ2F0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChsZXRcXG4gICAgICAoKGd1YXJkOmd1YXJkIChrZXlzZXQtcmVmLWd1YXJkIGtleXNldC1yZWYpKSlcXG5cXG4gICAgICAoY3JlYXRlLWFjY291bnQgYWNjb3VudCBndWFyZClcXG5cXG4gICAgICAoaW5zZXJ0IGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiBhbW91bnRcXG4gICAgICAgICwgXFxcImRhdGVcXFwiIDogZGF0ZVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmRcXG4gICAgICAgICwgXFxcInJlZGVlbWVkXFxcIiA6IGZhbHNlXFxuICAgICAgICB9KSkpXFxuXFxuICAoZGVmdW4gcmVsZWFzZS1hbGxvY2F0aW9uXFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcblxcbiAgICBAZG9jIFxcXCJSZWxlYXNlIGZ1bmRzIGFzc29jaWF0ZWQgd2l0aCBhbGxvY2F0aW9uIEFDQ09VTlQgaW50byBtYWluIGxlZGdlci4gICBcXFxcXFxuICAgICAgICAgXFxcXEFDQ09VTlQgbXVzdCBhbHJlYWR5IGV4aXN0IGluIG1haW4gbGVkZ2VyLiBBbGxvY2F0aW9uIGlzIGRlYWN0aXZhdGVkIFxcXFxcXG4gICAgICAgICBcXFxcYWZ0ZXIgcmVsZWFzZS5cXFwiXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAod2l0aC1yZWFkIGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2VcXG4gICAgICAsIFxcXCJkYXRlXFxcIiA6PSByZWxlYXNlLXRpbWVcXG4gICAgICAsIFxcXCJyZWRlZW1lZFxcXCIgOj0gcmVkZWVtZWRcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgOj0gZ3VhcmRcXG4gICAgICB9XFxuXFxuICAgICAgKGxldCAoKGN1cnItdGltZTp0aW1lIChhdCAnYmxvY2stdGltZSAoY2hhaW4tZGF0YSkpKSlcXG5cXG4gICAgICAgIChlbmZvcmNlIChub3QgcmVkZWVtZWQpXFxuICAgICAgICAgIFxcXCJhbGxvY2F0aW9uIGZ1bmRzIGhhdmUgYWxyZWFkeSBiZWVuIHJlZGVlbWVkXFxcIilcXG5cXG4gICAgICAgIChlbmZvcmNlXFxuICAgICAgICAgICg-PSBjdXJyLXRpbWUgcmVsZWFzZS10aW1lKVxcbiAgICAgICAgICAoZm9ybWF0IFxcXCJmdW5kcyBsb2NrZWQgdW50aWwge30uIGN1cnJlbnQgdGltZToge31cXFwiIFtyZWxlYXNlLXRpbWUgY3Vyci10aW1lXSkpXFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG5cXG4gICAgICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgICAgICAoY3JlZGl0IGFjY291bnQgZ3VhcmQgYmFsYW5jZSlcXG5cXG4gICAgICAgICAgKHVwZGF0ZSBhbGxvY2F0aW9uLXRhYmxlIGFjY291bnRcXG4gICAgICAgICAgICB7IFxcXCJyZWRlZW1lZFxcXCIgOiB0cnVlXFxuICAgICAgICAgICAgLCBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAgICAgICB9KVxcblxcbiAgICAgICAgICBcXFwiQWxsb2NhdGlvbiBzdWNjZXNzZnVsbHkgcmVsZWFzZWQgdG8gbWFpbiBsZWRnZXJcXFwiKVxcbiAgICApKSlcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJjb2luLWNvbnRyYWN0LXYyXCJ9In0" , - "eyJoYXNoIjoiS1BleXNfYndLeHpGV1M4cEdrWVg0QmZSWkh6MXhiVm43MkVTSk9PRGs0WSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihjb2luLnJlbWVkaWF0ZSBcXFwic2VuZGVyMDdcXFwiIDEzMzcuNylcXG4oY29pbi5yZW1lZGlhdGUgXFxcInNlbmRlcjA5XFxcIiAxMzM3LjkpXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJkZXZuZXQtb3RoZXItcmVtZWRpYXRpb25zXCJ9In0" + "eyJoYXNoIjoic1dNcmcxeUdCSDRnSWRnc2ZKV2VIN2l6MHc4d0gzdGphQWktRXpQSmlRNCIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihjb2luLnJlbWVkaWF0ZSBcXFwic2VuZGVyMDdcXFwiIDEzMzcuNylcXG4oY29pbi5yZW1lZGlhdGUgXFxcInNlbmRlcjA5XFxcIiAxMzM3LjkpXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJkZXZuZXQtcmVtZWRpYXRpb25zXCJ9In0" ] diff --git a/src/Chainweb/Pact/Transactions/FastTimedCPMTransactions.hs b/src/Chainweb/Pact/Transactions/FastTimedCPMTransactions.hs new file mode 100644 index 0000000000..f6a3a45827 --- /dev/null +++ b/src/Chainweb/Pact/Transactions/FastTimedCPMTransactions.hs @@ -0,0 +1,22 @@ +{-# LANGUAGE OverloadedStrings #-} + +-- This module is auto-generated. DO NOT EDIT IT MANUALLY. + +module Chainweb.Pact.Transactions.FastTimedCPMTransactions ( transactions ) where + +import Data.Bifunctor (first) + +import Chainweb.Transaction +import Chainweb.Utils + +transactions :: IO [ChainwebTransaction] +transactions = + let decodeTx t = + fromEitherM . (first (userError . show)) . codecDecode chainwebPayloadCodec =<< decodeB64UrlNoPaddingText t + in mapM decodeTx [ + "eyJoYXNoIjoiMDVCdGo3ZUJaQlc3by1TYUxvVmhBaWNNVVBaVUJiRzZRVDhfTEFrQ3hIcyIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihpbnRlcmZhY2UgZnVuZ2libGUtdjJcXG5cXG4gIFxcXCIgU3RhbmRhcmQgZm9yIGZ1bmdpYmxlIGNvaW5zIGFuZCB0b2tlbnMgYXMgc3BlY2lmaWVkIGluIEtJUC0wMDAyLiBcXFwiXFxuXFxuICAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICAgOyBTY2hlbWFcXG5cXG4gICAoZGVmc2NoZW1hIGFjY291bnQtZGV0YWlsc1xcbiAgICBAZG9jIFxcXCJTY2hlbWEgZm9yIHJlc3VsdHMgb2YgJ2FjY291bnQnIG9wZXJhdGlvbi5cXFwiXFxuICAgIEBtb2RlbCBbIChpbnZhcmlhbnQgKCE9IFxcXCJcXFwiIHNlbmRlcikpIF1cXG5cXG4gICAgYWNjb3VudDpzdHJpbmdcXG4gICAgYmFsYW5jZTpkZWNpbWFsXFxuICAgIGd1YXJkOmd1YXJkKVxcblxcblxcbiAgIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgIDsgQ2Fwc1xcblxcbiAgIChkZWZjYXAgVFJBTlNGRVI6Ym9vbFxcbiAgICAgKCBzZW5kZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIE1hbmFnZWQgY2FwYWJpbGl0eSBzZWFsaW5nIEFNT1VOVCBmb3IgdHJhbnNmZXIgZnJvbSBTRU5ERVIgdG8gXFxcXFxcbiAgICAgICAgICBcXFxcIFJFQ0VJVkVSLiBQZXJtaXRzIGFueSBudW1iZXIgb2YgdHJhbnNmZXJzIHVwIHRvIEFNT1VOVC5cXFwiXFxuICAgICBAbWFuYWdlZCBhbW91bnQgVFJBTlNGRVItbWdyXFxuICAgICApXFxuXFxuICAgKGRlZnVuIFRSQU5TRkVSLW1ncjpkZWNpbWFsXFxuICAgICAoIG1hbmFnZWQ6ZGVjaW1hbFxcbiAgICAgICByZXF1ZXN0ZWQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIE1hbmFnZXMgVFJBTlNGRVIgQU1PVU5UIGxpbmVhcmx5LCBcXFxcXFxuICAgICAgICAgIFxcXFwgc3VjaCB0aGF0IGEgcmVxdWVzdCBmb3IgMS4wIGFtb3VudCBvbiBhIDMuMCBcXFxcXFxuICAgICAgICAgIFxcXFwgbWFuYWdlZCBxdWFudGl0eSBlbWl0cyB1cGRhdGVkIGFtb3VudCAyLjAuXFxcIlxcbiAgICAgKVxcblxcbiAgIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgIDsgRnVuY3Rpb25hbGl0eVxcblxcblxcbiAgKGRlZnVuIHRyYW5zZmVyOnN0cmluZ1xcbiAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlcjpzdHJpbmdcXG4gICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICApXFxuICAgIEBkb2MgXFxcIiBUcmFuc2ZlciBBTU9VTlQgYmV0d2VlbiBhY2NvdW50cyBTRU5ERVIgYW5kIFJFQ0VJVkVSLiBcXFxcXFxuICAgICAgICAgXFxcXCBGYWlscyBpZiBlaXRoZXIgU0VOREVSIG9yIFJFQ0VJVkVSIGRvZXMgbm90IGV4aXN0LlxcXCJcXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAoIT0gcmVjZWl2ZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICBdXFxuICAgIClcXG5cXG4gICAoZGVmdW4gdHJhbnNmZXItY3JlYXRlOnN0cmluZ1xcbiAgICAgKCBzZW5kZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIFRyYW5zZmVyIEFNT1VOVCBiZXR3ZWVuIGFjY291bnRzIFNFTkRFUiBhbmQgUkVDRUlWRVIuIFxcXFxcXG4gICAgICAgICAgXFxcXCBGYWlscyBpZiBTRU5ERVIgZG9lcyBub3QgZXhpc3QuIElmIFJFQ0VJVkVSIGV4aXN0cywgZ3VhcmQgXFxcXFxcbiAgICAgICAgICBcXFxcIG11c3QgbWF0Y2ggZXhpc3RpbmcgdmFsdWUuIElmIFJFQ0VJVkVSIGRvZXMgbm90IGV4aXN0LCBcXFxcXFxuICAgICAgICAgIFxcXFwgUkVDRUlWRVIgYWNjb3VudCBpcyBjcmVhdGVkIHVzaW5nIFJFQ0VJVkVSLUdVQVJELiBcXFxcXFxuICAgICAgICAgIFxcXFwgU3ViamVjdCB0byBtYW5hZ2VtZW50IGJ5IFRSQU5TRkVSIGNhcGFiaWxpdHkuXFxcIlxcbiAgICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSByZWNlaXZlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICAgXVxcbiAgICAgKVxcblxcbiAgIChkZWZwYWN0IHRyYW5zZmVyLWNyb3NzY2hhaW46c3RyaW5nXFxuICAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICAgcmVjZWl2ZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyLWd1YXJkOmd1YXJkXFxuICAgICAgIHRhcmdldC1jaGFpbjpzdHJpbmdcXG4gICAgICAgYW1vdW50OmRlY2ltYWxcXG4gICAgIClcXG4gICAgIEBkb2MgXFxcIiAyLXN0ZXAgcGFjdCB0byB0cmFuc2ZlciBBTU9VTlQgZnJvbSBTRU5ERVIgb24gY3VycmVudCBjaGFpbiBcXFxcXFxuICAgICAgICAgIFxcXFwgdG8gUkVDRUlWRVIgb24gVEFSR0VULUNIQUlOIHZpYSBTUFYgcHJvb2YuIFxcXFxcXG4gICAgICAgICAgXFxcXCBUQVJHRVQtQ0hBSU4gbXVzdCBiZSBkaWZmZXJlbnQgdGhhbiBjdXJyZW50IGNoYWluIGlkLiBcXFxcXFxuICAgICAgICAgIFxcXFwgRmlyc3Qgc3RlcCBkZWJpdHMgQU1PVU5UIGNvaW5zIGluIFNFTkRFUiBhY2NvdW50IGFuZCB5aWVsZHMgXFxcXFxcbiAgICAgICAgICBcXFxcIFJFQ0VJVkVSLCBSRUNFSVZFUl9HVUFSRCBhbmQgQU1PVU5UIHRvIFRBUkdFVC1DSEFJTi4gXFxcXFxcbiAgICAgICAgICBcXFxcIFNlY29uZCBzdGVwIGNvbnRpbnVhdGlvbiBpcyBzZW50IGludG8gVEFSR0VULUNIQUlOIHdpdGggcHJvb2YgXFxcXFxcbiAgICAgICAgICBcXFxcIG9idGFpbmVkIGZyb20gdGhlIHNwdiAnb3V0cHV0JyBlbmRwb2ludCBvZiBDaGFpbndlYi4gXFxcXFxcbiAgICAgICAgICBcXFxcIFByb29mIGlzIHZhbGlkYXRlZCBhbmQgUkVDRUlWRVIgaXMgY3JlZGl0ZWQgd2l0aCBBTU9VTlQgXFxcXFxcbiAgICAgICAgICBcXFxcIGNyZWF0aW5nIGFjY291bnQgd2l0aCBSRUNFSVZFUl9HVUFSRCBhcyBuZWNlc3NhcnkuXFxcIlxcbiAgICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSByZWNlaXZlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHRhcmdldC1jaGFpbiBcXFwiXFxcIikpXFxuICAgICAgICAgICAgXVxcbiAgICAgKVxcblxcbiAgIChkZWZ1biBnZXQtYmFsYW5jZTpkZWNpbWFsXFxuICAgICAoIGFjY291bnQ6c3RyaW5nIClcXG4gICAgIFxcXCIgR2V0IGJhbGFuY2UgZm9yIEFDQ09VTlQuIEZhaWxzIGlmIGFjY291bnQgZG9lcyBub3QgZXhpc3QuXFxcIlxcbiAgICAgKVxcblxcbiAgIChkZWZ1biBkZXRhaWxzOm9iamVjdHthY2NvdW50LWRldGFpbHN9XFxuICAgICAoIGFjY291bnQ6IHN0cmluZyApXFxuICAgICBcXFwiIEdldCBhbiBvYmplY3Qgd2l0aCBkZXRhaWxzIG9mIEFDQ09VTlQuIFxcXFxcXG4gICAgIFxcXFwgRmFpbHMgaWYgYWNjb3VudCBkb2VzIG5vdCBleGlzdC5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIHByZWNpc2lvbjppbnRlZ2VyXFxuICAgICAoKVxcbiAgICAgXFxcIlJldHVybiB0aGUgbWF4aW11bSBhbGxvd2VkIGRlY2ltYWwgcHJlY2lzaW9uLlxcXCJcXG4gICAgIClcXG5cXG4gICAoZGVmdW4gZW5mb3JjZS11bml0OmJvb2xcXG4gICAgICggYW1vdW50OmRlY2ltYWwgKVxcbiAgICAgXFxcIiBFbmZvcmNlIG1pbmltdW0gcHJlY2lzaW9uIGFsbG93ZWQgZm9yIHRyYW5zYWN0aW9ucy5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIGNyZWF0ZS1hY2NvdW50OnN0cmluZ1xcbiAgICAgKCBhY2NvdW50OnN0cmluZ1xcbiAgICAgICBndWFyZDpndWFyZFxcbiAgICAgKVxcbiAgICAgXFxcIiBDcmVhdGUgQUNDT1VOVCB3aXRoIDAuMCBiYWxhbmNlLCB3aXRoIEdVQVJEIGNvbnRyb2xsaW5nIGFjY2Vzcy5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIHJvdGF0ZTpzdHJpbmdcXG4gICAgICggYWNjb3VudDpzdHJpbmdcXG4gICAgICAgbmV3LWd1YXJkOmd1YXJkXFxuICAgICApXFxuICAgICBcXFwiIFJvdGF0ZSBndWFyZCBmb3IgQUNDT1VOVC4gVHJhbnNhY3Rpb24gaXMgdmFsaWRhdGVkIGFnYWluc3QgXFxcXFxcbiAgICAgXFxcXCBleGlzdGluZyBndWFyZCBiZWZvcmUgaW5zdGFsbGluZyBuZXcgZ3VhcmQuIFxcXCJcXG4gICAgIClcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJmdW5naWJsZS1hc3NldC12MlwifSJ9" + , + "eyJoYXNoIjoibVZzMjNxNnJyUjZrWDFGX0ItamNCX05hLXdZdmR3dnRwa1cwQVNaZExjRSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihtb2R1bGUgY29pbiBHT1ZFUk5BTkNFXFxuXFxuICBAZG9jIFxcXCInY29pbicgcmVwcmVzZW50cyB0aGUgS2FkZW5hIENvaW4gQ29udHJhY3QuIFRoaXMgY29udHJhY3QgcHJvdmlkZXMgYm90aCB0aGUgXFxcXFxcbiAgXFxcXGJ1eS9yZWRlZW0gZ2FzIHN1cHBvcnQgaW4gdGhlIGZvcm0gb2YgJ2Z1bmQtdHgnLCBhcyB3ZWxsIGFzIHRyYW5zZmVyLCAgICAgICBcXFxcXFxuICBcXFxcY3JlZGl0LCBkZWJpdCwgY29pbmJhc2UsIGFjY291bnQgY3JlYXRpb24gYW5kIHF1ZXJ5LCBhcyB3ZWxsIGFzIFNQViBidXJuICAgIFxcXFxcXG4gIFxcXFxjcmVhdGUuIFRvIGFjY2VzcyB0aGUgY29pbiBjb250cmFjdCwgeW91IG1heSB1c2UgaXRzIGZ1bGx5LXF1YWxpZmllZCBuYW1lLCAgXFxcXFxcbiAgXFxcXG9yIGlzc3VlIHRoZSAnKHVzZSBjb2luKScgY29tbWFuZCBpbiB0aGUgYm9keSBvZiBhIG1vZHVsZSBkZWNsYXJhdGlvbi5cXFwiXFxuXFxuICBAbW9kZWxcXG4gICAgWyAoZGVmcHJvcGVydHkgY29uc2VydmVzLW1hc3NcXG4gICAgICAgICg9IChjb2x1bW4tZGVsdGEgY29pbi10YWJsZSAnYmFsYW5jZSkgMC4wKSlcXG5cXG4gICAgICAoZGVmcHJvcGVydHkgdmFsaWQtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgICAgICAoYW5kXFxuICAgICAgICAgICg-PSAobGVuZ3RoIGFjY291bnQpIDMpXFxuICAgICAgICAgICg8PSAobGVuZ3RoIGFjY291bnQpIDI1NikpKVxcbiAgICBdXFxuXFxuICAoaW1wbGVtZW50cyBmdW5naWJsZS12MilcXG5cXG4gIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cXG4gIDsgU2NoZW1hcyBhbmQgVGFibGVzXFxuXFxuICAoZGVmc2NoZW1hIGNvaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlRoZSBjb2luIGNvbnRyYWN0IHRva2VuIHNjaGVtYVxcXCJcXG4gICAgQG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBndWFyZDpndWFyZClcXG5cXG4gIChkZWZ0YWJsZSBjb2luLXRhYmxlOntjb2luLXNjaGVtYX0pXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENhcGFiaWxpdGllc1xcblxcbiAgKGRlZmNhcCBHT1ZFUk5BTkNFICgpXFxuICAgIChlbmZvcmNlIGZhbHNlIFxcXCJFbmZvcmNlIG5vbi11cGdyYWRlYWJpbGl0eVxcXCIpKVxcblxcbiAgKGRlZmNhcCBHQVMgKClcXG4gICAgXFxcIk1hZ2ljIGNhcGFiaWxpdHkgdG8gcHJvdGVjdCBnYXMgYnV5IGFuZCByZWRlZW1cXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIENPSU5CQVNFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IHRvIHByb3RlY3QgbWluZXIgcmV3YXJkXFxcIlxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBHRU5FU0lTICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGNvbnN0cmFpbmluZyBnZW5lc2lzIHRyYW5zYWN0aW9uc1xcXCJcXG4gICAgdHJ1ZSlcXG5cXG4gIChkZWZjYXAgUkVNRURJQVRFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnNcXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIERFQklUIChzZW5kZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgZGViaXRpbmcgb3BlcmF0aW9uc1xcXCJcXG4gICAgKGVuZm9yY2UtZ3VhcmQgKGF0ICdndWFyZCAocmVhZCBjb2luLXRhYmxlIHNlbmRlcikpKVxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIFxcXCJcXFwiKSBcXFwidmFsaWQgc2VuZGVyXFxcIikpXFxuXFxuICAoZGVmY2FwIENSRURJVCAocmVjZWl2ZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgY3JlZGl0aW5nIG9wZXJhdGlvbnNcXFwiXFxuICAgIChlbmZvcmNlICghPSByZWNlaXZlciBcXFwiXFxcIikgXFxcInZhbGlkIHJlY2VpdmVyXFxcIikpXFxuXFxuICAoZGVmY2FwIFJPVEFURSAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkF1dG9ub21vdXNseSBtYW5hZ2VkIGNhcGFiaWxpdHkgZm9yIGd1YXJkIHJvdGF0aW9uXFxcIlxcbiAgICBAbWFuYWdlZFxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBUUkFOU0ZFUjpib29sXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsXFxuICAgIClcXG4gICAgQG1hbmFnZWQgYW1vdW50IFRSQU5TRkVSLW1nclxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIHJlY2VpdmVyKSBcXFwic2FtZSBzZW5kZXIgYW5kIHJlY2VpdmVyXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApIFxcXCJQb3NpdGl2ZSBhbW91bnRcXFwiKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChDUkVESVQgcmVjZWl2ZXIpKVxcbiAgKVxcblxcbiAgKGRlZnVuIFRSQU5TRkVSLW1ncjpkZWNpbWFsXFxuICAgICggbWFuYWdlZDpkZWNpbWFsXFxuICAgICAgcmVxdWVzdGVkOmRlY2ltYWxcXG4gICAgKVxcblxcbiAgICAobGV0ICgobmV3YmFsICgtIG1hbmFnZWQgcmVxdWVzdGVkKSkpXFxuICAgICAgKGVuZm9yY2UgKD49IG5ld2JhbCAwLjApXFxuICAgICAgICAoZm9ybWF0IFxcXCJUUkFOU0ZFUiBleGNlZWRlZCBmb3IgYmFsYW5jZSB7fVxcXCIgW21hbmFnZWRdKSlcXG4gICAgICBuZXdiYWwpXFxuICApXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvbnN0YW50c1xcblxcbiAgKGRlZmNvbnN0IENPSU5fQ0hBUlNFVCBDSEFSU0VUX0xBVElOMVxcbiAgICBcXFwiVGhlIGRlZmF1bHQgY29pbiBjb250cmFjdCBjaGFyYWN0ZXIgc2V0XFxcIilcXG5cXG4gIChkZWZjb25zdCBNSU5JTVVNX1BSRUNJU0lPTiAxMlxcbiAgICBcXFwiTWluaW11bSBhbGxvd2VkIHByZWNpc2lvbiBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiKVxcblxcbiAgKGRlZmNvbnN0IE1JTklNVU1fQUNDT1VOVF9MRU5HVEggM1xcbiAgICBcXFwiTWluaW11bSBhY2NvdW50IGxlbmd0aCBhZG1pc3NpYmxlIGZvciBjb2luIGFjY291bnRzXFxcIilcXG5cXG4gIChkZWZjb25zdCBNQVhJTVVNX0FDQ09VTlRfTEVOR1RIIDI1NlxcbiAgICBcXFwiTWF4aW11bSBhY2NvdW50IG5hbWUgbGVuZ3RoIGFkbWlzc2libGUgZm9yIGNvaW4gYWNjb3VudHNcXFwiKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBVdGlsaXRpZXNcXG5cXG4gIChkZWZ1biBlbmZvcmNlLXVuaXQ6Ym9vbCAoYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgbWluaW11bSBwcmVjaXNpb24gYWxsb3dlZCBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiXFxuXFxuICAgIChlbmZvcmNlXFxuICAgICAgKD0gKGZsb29yIGFtb3VudCBNSU5JTVVNX1BSRUNJU0lPTilcXG4gICAgICAgICBhbW91bnQpXFxuICAgICAgKGZvcm1hdCBcXFwiQW1vdW50IHZpb2xhdGVzIG1pbmltdW0gcHJlY2lzaW9uOiB7fVxcXCIgW2Ftb3VudF0pKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdmFsaWRhdGUtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgdGhhdCBhbiBhY2NvdW50IG5hbWUgY29uZm9ybXMgdG8gdGhlIGNvaW4gY29udHJhY3QgXFxcXFxcbiAgICAgICAgIFxcXFxtaW5pbXVtIGFuZCBtYXhpbXVtIGxlbmd0aCByZXF1aXJlbWVudHMsIGFzIHdlbGwgYXMgdGhlICAgIFxcXFxcXG4gICAgICAgICBcXFxcbGF0aW4tMSBjaGFyYWN0ZXIgc2V0LlxcXCJcXG5cXG4gICAgKGVuZm9yY2VcXG4gICAgICAoaXMtY2hhcnNldCBDT0lOX0NIQVJTRVQgYWNjb3VudClcXG4gICAgICAoZm9ybWF0XFxuICAgICAgICBcXFwiQWNjb3VudCBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBjb2luIGNvbnRyYWN0IGNoYXJzZXQ6IHt9XFxcIlxcbiAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgKGxldCAoKGFjY291bnQtbGVuZ3RoIChsZW5ndGggYWNjb3VudCkpKVxcblxcbiAgICAgIChlbmZvcmNlXFxuICAgICAgICAoPj0gYWNjb3VudC1sZW5ndGggTUlOSU1VTV9BQ0NPVU5UX0xFTkdUSClcXG4gICAgICAgIChmb3JtYXRcXG4gICAgICAgICAgXFxcIkFjY291bnQgbmFtZSBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBtaW4gbGVuZ3RoIHJlcXVpcmVtZW50OiB7fVxcXCJcXG4gICAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgICAoZW5mb3JjZVxcbiAgICAgICAgKDw9IGFjY291bnQtbGVuZ3RoIE1BWElNVU1fQUNDT1VOVF9MRU5HVEgpXFxuICAgICAgICAoZm9ybWF0XFxuICAgICAgICAgIFxcXCJBY2NvdW50IG5hbWUgZG9lcyBub3QgY29uZm9ybSB0byB0aGUgbWF4IGxlbmd0aCByZXF1aXJlbWVudDoge31cXFwiXFxuICAgICAgICAgIFthY2NvdW50XSkpXFxuICAgICAgKVxcbiAgKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBDb2luIENvbnRyYWN0XFxuXFxuICAoZGVmdW4gZ2FzLW9ubHkgKClcXG4gICAgXFxcIlByZWRpY2F0ZSBmb3IgZ2FzLW9ubHkgdXNlciBndWFyZHMuXFxcIlxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKSlcXG5cXG4gIChkZWZ1biBnYXMtZ3VhcmQgKGd1YXJkOmd1YXJkKVxcbiAgICBcXFwiUHJlZGljYXRlIGZvciBnYXMgKyBzaW5nbGUga2V5IHVzZXIgZ3VhcmRzXFxcIlxcbiAgICAoZW5mb3JjZS1vbmVcXG4gICAgICBcXFwiRW5mb3JjZSBlaXRoZXIgdGhlIHByZXNlbmNlIG9mIGEgR0FTIGNhcCBvciBrZXlzZXRcXFwiXFxuICAgICAgWyAoZ2FzLW9ubHkpXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG4gICAgICBdKSlcXG5cXG4gIChkZWZ1biBidXktZ2FzOnN0cmluZyAoc2VuZGVyOnN0cmluZyB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCJUaGlzIGZ1bmN0aW9uIGRlc2NyaWJlcyB0aGUgbWFpbiAnZ2FzIGJ1eScgb3BlcmF0aW9uLiBBdCB0aGlzIHBvaW50IFxcXFxcXG4gICAgXFxcXE1JTkVSIGhhcyBiZWVuIGNob3NlbiBmcm9tIHRoZSBwb29sLCBhbmQgd2lsbCBiZSB2YWxpZGF0ZWQuIFRoZSBTRU5ERVIgICBcXFxcXFxuICAgIFxcXFxvZiB0aGlzIHRyYW5zYWN0aW9uIGhhcyBzcGVjaWZpZWQgYSBnYXMgbGltaXQgTElNSVQgKG1heGltdW0gZ2FzKSBmb3IgICAgXFxcXFxcbiAgICBcXFxcdGhlIHRyYW5zYWN0aW9uLCBhbmQgdGhlIHByaWNlIGlzIHRoZSBzcG90IHByaWNlIG9mIGdhcyBhdCB0aGF0IHRpbWUuICAgIFxcXFxcXG4gICAgXFxcXFRoZSBnYXMgYnV5IHdpbGwgYmUgZXhlY3V0ZWQgcHJpb3IgdG8gZXhlY3V0aW5nIFNFTkRFUidzIGNvZGUuXFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCB0b3RhbClcXG4gICAgKGVuZm9yY2UgKD4gdG90YWwgMC4wKSBcXFwiZ2FzIHN1cHBseSBtdXN0IGJlIGEgcG9zaXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuICAgICAgKGRlYml0IHNlbmRlciB0b3RhbCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZWRlZW0tZ2FzOnN0cmluZyAobWluZXI6c3RyaW5nIG1pbmVyLWd1YXJkOmd1YXJkIHNlbmRlcjpzdHJpbmcgdG90YWw6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiVGhpcyBmdW5jdGlvbiBkZXNjcmliZXMgdGhlIG1haW4gJ3JlZGVlbSBnYXMnIG9wZXJhdGlvbi4gQXQgdGhpcyAgICBcXFxcXFxuICAgIFxcXFxwb2ludCwgdGhlIFNFTkRFUidzIHRyYW5zYWN0aW9uIGhhcyBiZWVuIGV4ZWN1dGVkLCBhbmQgdGhlIGdhcyB0aGF0ICAgICAgXFxcXFxcbiAgICBcXFxcd2FzIGNoYXJnZWQgaGFzIGJlZW4gY2FsY3VsYXRlZC4gTUlORVIgd2lsbCBiZSBjcmVkaXRlZCB0aGUgZ2FzIGNvc3QsICAgIFxcXFxcXG4gICAgXFxcXGFuZCBTRU5ERVIgd2lsbCByZWNlaXZlIHRoZSByZW1haW5kZXIgdXAgdG8gdGhlIGxpbWl0XFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBtaW5lcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG4gICAgKHZhbGlkYXRlLWFjY291bnQgbWluZXIpXFxuICAgIChlbmZvcmNlLXVuaXQgdG90YWwpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKEdBUykpXFxuICAgIChsZXQqXFxuICAgICAgKChmZWUgKHJlYWQtZGVjaW1hbCBcXFwiZmVlXFxcIikpXFxuICAgICAgIChyZWZ1bmQgKC0gdG90YWwgZmVlKSkpXFxuXFxuICAgICAgKGVuZm9yY2UtdW5pdCBmZWUpXFxuICAgICAgKGVuZm9yY2UgKD49IGZlZSAwLjApXFxuICAgICAgICBcXFwiZmVlIG11c3QgYmUgYSBub24tbmVnYXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAgIChlbmZvcmNlICg-PSByZWZ1bmQgMC4wKVxcbiAgICAgICAgXFxcInJlZnVuZCBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIHF1YW50aXR5XFxcIilcXG5cXG4gICAgICAgIDsgZGlyZWN0bHkgdXBkYXRlIGluc3RlYWQgb2YgY3JlZGl0XFxuICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHNlbmRlcilcXG4gICAgICAgIChpZiAoPiByZWZ1bmQgMC4wKVxcbiAgICAgICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgc2VuZGVyXFxuICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOj0gYmFsYW5jZSB9XFxuICAgICAgICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIHNlbmRlclxcbiAgICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCI6ICgrIGJhbGFuY2UgcmVmdW5kKSB9KSlcXG5cXG4gICAgICAgICAgXFxcIm5vb3BcXFwiKSlcXG5cXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChDUkVESVQgbWluZXIpXFxuICAgICAgICAoaWYgKD4gZmVlIDAuMClcXG4gICAgICAgICAgKGNyZWRpdCBtaW5lciBtaW5lci1ndWFyZCBmZWUpXFxuICAgICAgICAgIFxcXCJub29wXFxcIikpXFxuICAgICAgKVxcblxcbiAgICApXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFjY291bnQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZClcXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKSBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChpbnNlcnQgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgICA6IGd1YXJkXFxuICAgICAgfSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGdldC1iYWxhbmNlOmRlY2ltYWwgKGFjY291bnQ6c3RyaW5nKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcbiAgICAgIGJhbGFuY2VcXG4gICAgICApXFxuICAgIClcXG5cXG4gIChkZWZ1biBkZXRhaWxzOm9iamVjdHtmdW5naWJsZS12Mi5hY2NvdW50LWRldGFpbHN9XFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIiA6PSBnIH1cXG4gICAgICB7IFxcXCJhY2NvdW50XFxcIiA6IGFjY291bnRcXG4gICAgICAsIFxcXCJiYWxhbmNlXFxcIiA6IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIjogZyB9KVxcbiAgICApXFxuXFxuICAoZGVmdW4gcm90YXRlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgbmV3LWd1YXJkOmd1YXJkKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChST1RBVEUgYWNjb3VudClcXG4gICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IG9sZC1ndWFyZCB9XFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBvbGQtZ3VhcmQpXFxuXFxuICAgICAgICAodXBkYXRlIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgICB7IFxcXCJndWFyZFxcXCIgOiBuZXctZ3VhcmQgfVxcbiAgICAgICAgICApKSlcXG4gICAgKVxcblxcblxcbiAgKGRlZnVuIHByZWNpc2lvbjppbnRlZ2VyXFxuICAgICgpXFxuICAgIE1JTklNVU1fUFJFQ0lTSU9OKVxcblxcbiAgKGRlZnVuIHRyYW5zZmVyOnN0cmluZyAoc2VuZGVyOnN0cmluZyByZWNlaXZlcjpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcylcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgcmVjZWl2ZXIpKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgICh3aXRoLXJlYWQgY29pbi10YWJsZSByZWNlaXZlclxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IGcgfVxcblxcbiAgICAgICAgKGNyZWRpdCByZWNlaXZlciBnIGFtb3VudCkpXFxuICAgICAgKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdHJhbnNmZXItY3JlYXRlOnN0cmluZ1xcbiAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5IGNvbnNlcnZlcy1tYXNzKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgIChjcmVkaXQgcmVjZWl2ZXIgcmVjZWl2ZXItZ3VhcmQgYW1vdW50KSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGNvaW5iYXNlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYWNjb3VudC1ndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiSW50ZXJuYWwgZnVuY3Rpb24gZm9yIHRoZSBpbml0aWFsIGNyZWF0aW9uIG9mIGNvaW5zLiAgVGhpcyBmdW5jdGlvbiBcXFxcXFxuICAgIFxcXFxjYW5ub3QgYmUgdXNlZCBvdXRzaWRlIG9mIHRoZSBjb2luIGNvbnRyYWN0LlxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKD4gYW1vdW50IDAuMCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChDT0lOQkFTRSkpXFxuICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgIChjcmVkaXQgYWNjb3VudCBhY2NvdW50LWd1YXJkIGFtb3VudCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZW1lZGlhdGU6c3RyaW5nIChhY2NvdW50OnN0cmluZyBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQWxsb3dzIGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnMuIFRoaXMgZnVuY3Rpb24gXFxcXFxcbiAgICAgICAgIFxcXFxpcyBwcm90ZWN0ZWQgYnkgdGhlIFJFTUVESUFURSBjYXBhYmlsaXR5XFxcIlxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG5cXG4gICAgKGVuZm9yY2UgKD4gYW1vdW50IDAuMClcXG4gICAgICBcXFwiUmVtZWRpYXRpb24gYW1vdW50IG11c3QgYmUgcG9zaXRpdmVcXFwiKVxcblxcbiAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgKHJlcXVpcmUtY2FwYWJpbGl0eSAoUkVNRURJQVRFKSlcXG4gICAgKHdpdGgtcmVhZCBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6PSBiYWxhbmNlIH1cXG5cXG4gICAgICAoZW5mb3JjZSAoPD0gYW1vdW50IGJhbGFuY2UpIFxcXCJJbnN1ZmZpY2llbnQgZnVuZHNcXFwiKVxcblxcbiAgICAgICh1cGRhdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgtIGJhbGFuY2UgYW1vdW50KSB9XFxuICAgICAgICApKVxcbiAgICApXFxuXFxuICAoZGVmcGFjdCBmdW5kLXR4IChzZW5kZXI6c3RyaW5nIG1pbmVyOnN0cmluZyBtaW5lci1ndWFyZDpndWFyZCB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCInZnVuZC10eCcgaXMgYSBzcGVjaWFsIHBhY3QgdG8gZnVuZCBhIHRyYW5zYWN0aW9uIGluIHR3byBzdGVwcywgICAgIFxcXFxcXG4gICAgXFxcXHdpdGggdGhlIGFjdHVhbCB0cmFuc2FjdGlvbiB0cmFuc3BpcmluZyBpbiB0aGUgbWlkZGxlOiAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXFxcXFxcbiAgICBcXFxcICAxKSBBIGJ1eWluZyBwaGFzZSwgZGViaXRpbmcgdGhlIHNlbmRlciBmb3IgdG90YWwgZ2FzIGFuZCBmZWUsIHlpZWxkaW5nIFxcXFxcXG4gICAgXFxcXCAgICAgVFhfTUFYX0NIQVJHRS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgIDIpIEEgc2V0dGxlbWVudCBwaGFzZSwgcmVzdW1pbmcgVFhfTUFYX0NIQVJHRSwgYW5kIGFsbG9jYXRpbmcgdG8gdGhlICAgXFxcXFxcbiAgICBcXFxcICAgICBjb2luYmFzZSBhY2NvdW50IGZvciB1c2VkIGdhcyBhbmQgZmVlLCBhbmQgc2VuZGVyIGFjY291bnQgZm9yIGJhbC0gIFxcXFxcXG4gICAgXFxcXCAgICAgYW5jZSAodW51c2VkIGdhcywgaWYgYW55KS5cXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiB0b3RhbCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IG1pbmVyKSlcXG4gICAgICAgICAgICAgOyhwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcykgbm90IHN1cHBvcnRlZCB5ZXRcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXAgKGJ1eS1nYXMgc2VuZGVyIHRvdGFsKSlcXG4gICAgKHN0ZXAgKHJlZGVlbS1nYXMgbWluZXIgbWluZXItZ3VhcmQgc2VuZGVyIHRvdGFsKSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGRlYml0OnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkRlYml0IEFNT1VOVCBmcm9tIEFDQ09VTlQgYmFsYW5jZVxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApXFxuICAgICAgXFxcImRlYml0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKERFQklUIGFjY291bnQpKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcblxcbiAgICAgIChlbmZvcmNlICg8PSBhbW91bnQgYmFsYW5jZSkgXFxcIkluc3VmZmljaWVudCBmdW5kc1xcXCIpXFxuXFxuICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogKC0gYmFsYW5jZSBhbW91bnQpIH1cXG4gICAgICAgICkpXFxuICAgIClcXG5cXG5cXG4gIChkZWZ1biBjcmVkaXQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQ3JlZGl0IEFNT1VOVCB0byBBQ0NPVU5UIGJhbGFuY2VcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKSBcXFwiY3JlZGl0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KSlcXG4gICAgKHdpdGgtZGVmYXVsdC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogMC4wLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmQgfVxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UsIFxcXCJndWFyZFxcXCIgOj0gcmV0ZyB9XFxuICAgICAgOyB3ZSBkb24ndCB3YW50IHRvIG92ZXJ3cml0ZSBhbiBleGlzdGluZyBndWFyZCB3aXRoIHRoZSB1c2VyLXN1cHBsaWVkIG9uZVxcbiAgICAgIChlbmZvcmNlICg9IHJldGcgZ3VhcmQpXFxuICAgICAgICBcXFwiYWNjb3VudCBndWFyZHMgZG8gbm90IG1hdGNoXFxcIilcXG5cXG4gICAgICAod3JpdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgrIGJhbGFuY2UgYW1vdW50KVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiICAgOiByZXRnXFxuICAgICAgICB9KVxcbiAgICAgICkpXFxuXFxuXFxuICAoZGVmc2NoZW1hIGNyb3NzY2hhaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlNjaGVtYSBmb3IgeWllbGRlZCB2YWx1ZSBpbiBjcm9zcy1jaGFpbiB0cmFuc2ZlcnNcXFwiXFxuICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICBhbW91bnQ6ZGVjaW1hbClcXG5cXG4gIChkZWZwYWN0IHRyYW5zZmVyLWNyb3NzY2hhaW46c3RyaW5nXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyLWd1YXJkOmd1YXJkXFxuICAgICAgdGFyZ2V0LWNoYWluOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXBcXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCByZWNlaXZlcilcXG5cXG4gICAgICAgIChlbmZvcmNlICghPSBcXFwiXFxcIiB0YXJnZXQtY2hhaW4pIFxcXCJlbXB0eSB0YXJnZXQtY2hhaW5cXFwiKVxcbiAgICAgICAgKGVuZm9yY2UgKCE9IChhdCAnY2hhaW4taWQgKGNoYWluLWRhdGEpKSB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgIFxcXCJjYW5ub3QgcnVuIGNyb3NzLWNoYWluIHRyYW5zZmVycyB0byB0aGUgc2FtZSBjaGFpblxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgICAgICBcXFwidHJhbnNmZXIgcXVhbnRpdHkgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgICAgIDs7IHN0ZXAgMSAtIGRlYml0IGRlbGV0ZS1hY2NvdW50IG9uIGN1cnJlbnQgY2hhaW5cXG4gICAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcblxcbiAgICAgICAgKGxldFxcbiAgICAgICAgICAoKGNyb3NzY2hhaW4tZGV0YWlsczpvYmplY3R7Y3Jvc3NjaGFpbi1zY2hlbWF9XFxuICAgICAgICAgICAgeyBcXFwicmVjZWl2ZXJcXFwiIDogcmVjZWl2ZXJcXG4gICAgICAgICAgICAsIFxcXCJyZWNlaXZlci1ndWFyZFxcXCIgOiByZWNlaXZlci1ndWFyZFxcbiAgICAgICAgICAgICwgXFxcImFtb3VudFxcXCIgOiBhbW91bnRcXG4gICAgICAgICAgICB9KSlcXG4gICAgICAgICAgKHlpZWxkIGNyb3NzY2hhaW4tZGV0YWlscyB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgICkpKVxcblxcbiAgICAoc3RlcFxcbiAgICAgIChyZXN1bWVcXG4gICAgICAgIHsgXFxcInJlY2VpdmVyXFxcIiA6PSByZWNlaXZlclxcbiAgICAgICAgLCBcXFwicmVjZWl2ZXItZ3VhcmRcXFwiIDo9IHJlY2VpdmVyLWd1YXJkXFxuICAgICAgICAsIFxcXCJhbW91bnRcXFwiIDo9IGFtb3VudFxcbiAgICAgICAgfVxcblxcbiAgICAgICAgOzsgc3RlcCAyIC0gY3JlZGl0IGNyZWF0ZSBhY2NvdW50IG9uIHRhcmdldCBjaGFpblxcbiAgICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHJlY2VpdmVyKVxcbiAgICAgICAgICAoY3JlZGl0IHJlY2VpdmVyIHJlY2VpdmVyLWd1YXJkIGFtb3VudCkpXFxuICAgICAgICApKVxcbiAgICApXFxuXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvaW4gYWxsb2NhdGlvbnNcXG5cXG4gIChkZWZzY2hlbWEgYWxsb2NhdGlvbi1zY2hlbWFcXG4gICAgQGRvYyBcXFwiR2VuZXNpcyBhbGxvY2F0aW9uIHJlZ2lzdHJ5XFxcIlxcbiAgICA7QG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBkYXRlOnRpbWVcXG4gICAgZ3VhcmQ6Z3VhcmRcXG4gICAgcmVkZWVtZWQ6Ym9vbClcXG5cXG4gIChkZWZ0YWJsZSBhbGxvY2F0aW9uLXRhYmxlOnthbGxvY2F0aW9uLXNjaGVtYX0pXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFsbG9jYXRpb24tYWNjb3VudFxcbiAgICAoIGFjY291bnQ6c3RyaW5nXFxuICAgICAgZGF0ZTp0aW1lXFxuICAgICAga2V5c2V0LXJlZjpzdHJpbmdcXG4gICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICApXFxuXFxuICAgIEBkb2MgXFxcIkFkZCBhbiBlbnRyeSB0byB0aGUgY29pbiBhbGxvY2F0aW9uIHRhYmxlLiBUaGlzIGZ1bmN0aW9uIFxcXFxcXG4gICAgICAgICBcXFxcYWxzbyBjcmVhdGVzIGEgY29ycmVzcG9uZGluZyBlbXB0eSBjb2luIGNvbnRyYWN0IGFjY291bnQgXFxcXFxcbiAgICAgICAgIFxcXFxvZiB0aGUgc2FtZSBuYW1lIGFuZCBndWFyZC4gUmVxdWlyZXMgR0VORVNJUyBjYXBhYmlsaXR5LiBcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHRU5FU0lTKSlcXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG4gICAgKGVuZm9yY2UgKD49IGFtb3VudCAwLjApXFxuICAgICAgXFxcImFsbG9jYXRpb24gYW1vdW50IG11c3QgYmUgbm9uLW5lZ2F0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChsZXRcXG4gICAgICAoKGd1YXJkOmd1YXJkIChrZXlzZXQtcmVmLWd1YXJkIGtleXNldC1yZWYpKSlcXG5cXG4gICAgICAoY3JlYXRlLWFjY291bnQgYWNjb3VudCBndWFyZClcXG5cXG4gICAgICAoaW5zZXJ0IGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiBhbW91bnRcXG4gICAgICAgICwgXFxcImRhdGVcXFwiIDogZGF0ZVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmRcXG4gICAgICAgICwgXFxcInJlZGVlbWVkXFxcIiA6IGZhbHNlXFxuICAgICAgICB9KSkpXFxuXFxuICAoZGVmdW4gcmVsZWFzZS1hbGxvY2F0aW9uXFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcblxcbiAgICBAZG9jIFxcXCJSZWxlYXNlIGZ1bmRzIGFzc29jaWF0ZWQgd2l0aCBhbGxvY2F0aW9uIEFDQ09VTlQgaW50byBtYWluIGxlZGdlci4gICBcXFxcXFxuICAgICAgICAgXFxcXEFDQ09VTlQgbXVzdCBhbHJlYWR5IGV4aXN0IGluIG1haW4gbGVkZ2VyLiBBbGxvY2F0aW9uIGlzIGRlYWN0aXZhdGVkIFxcXFxcXG4gICAgICAgICBcXFxcYWZ0ZXIgcmVsZWFzZS5cXFwiXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAod2l0aC1yZWFkIGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2VcXG4gICAgICAsIFxcXCJkYXRlXFxcIiA6PSByZWxlYXNlLXRpbWVcXG4gICAgICAsIFxcXCJyZWRlZW1lZFxcXCIgOj0gcmVkZWVtZWRcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgOj0gZ3VhcmRcXG4gICAgICB9XFxuXFxuICAgICAgKGxldCAoKGN1cnItdGltZTp0aW1lIChhdCAnYmxvY2stdGltZSAoY2hhaW4tZGF0YSkpKSlcXG5cXG4gICAgICAgIChlbmZvcmNlIChub3QgcmVkZWVtZWQpXFxuICAgICAgICAgIFxcXCJhbGxvY2F0aW9uIGZ1bmRzIGhhdmUgYWxyZWFkeSBiZWVuIHJlZGVlbWVkXFxcIilcXG5cXG4gICAgICAgIChlbmZvcmNlXFxuICAgICAgICAgICg-PSBjdXJyLXRpbWUgcmVsZWFzZS10aW1lKVxcbiAgICAgICAgICAoZm9ybWF0IFxcXCJmdW5kcyBsb2NrZWQgdW50aWwge30uIGN1cnJlbnQgdGltZToge31cXFwiIFtyZWxlYXNlLXRpbWUgY3Vyci10aW1lXSkpXFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG5cXG4gICAgICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgICAgICAoY3JlZGl0IGFjY291bnQgZ3VhcmQgYmFsYW5jZSlcXG5cXG4gICAgICAgICAgKHVwZGF0ZSBhbGxvY2F0aW9uLXRhYmxlIGFjY291bnRcXG4gICAgICAgICAgICB7IFxcXCJyZWRlZW1lZFxcXCIgOiB0cnVlXFxuICAgICAgICAgICAgLCBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAgICAgICB9KVxcblxcbiAgICAgICAgICBcXFwiQWxsb2NhdGlvbiBzdWNjZXNzZnVsbHkgcmVsZWFzZWQgdG8gbWFpbiBsZWRnZXJcXFwiKVxcbiAgICApKSlcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJjb2luLWNvbnRyYWN0LXYyXCJ9In0" + , + "eyJoYXNoIjoiaFYyZ21vdERCV0U5ZnlZS29JRW4zZm5YRlhBWjBhWHFTVmtlYWJma0ptRSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihjb2luLnJlbWVkaWF0ZSBcXFwic2VuZGVyMDBcXFwiIDEzMzcuNylcIn19LFwic2lnbmVyc1wiOltdLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjoxNzI4MDAsXCJnYXNMaW1pdFwiOjAsXCJjaGFpbklkXCI6XCJcIixcImdhc1ByaWNlXCI6MCxcInNlbmRlclwiOlwiXCJ9LFwibm9uY2VcIjpcInRlc3RuZXQtb3RoZXItcmVtZWRpYXRpb25zXCJ9In0" + ] diff --git a/src/Chainweb/Pact/Transactions/OtherTransactions.hs b/src/Chainweb/Pact/Transactions/OtherTransactions.hs index 2da41ed596..e3714295da 100644 --- a/src/Chainweb/Pact/Transactions/OtherTransactions.hs +++ b/src/Chainweb/Pact/Transactions/OtherTransactions.hs @@ -17,4 +17,6 @@ transactions = "eyJoYXNoIjoiMDVCdGo3ZUJaQlc3by1TYUxvVmhBaWNNVVBaVUJiRzZRVDhfTEFrQ3hIcyIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihpbnRlcmZhY2UgZnVuZ2libGUtdjJcXG5cXG4gIFxcXCIgU3RhbmRhcmQgZm9yIGZ1bmdpYmxlIGNvaW5zIGFuZCB0b2tlbnMgYXMgc3BlY2lmaWVkIGluIEtJUC0wMDAyLiBcXFwiXFxuXFxuICAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICAgOyBTY2hlbWFcXG5cXG4gICAoZGVmc2NoZW1hIGFjY291bnQtZGV0YWlsc1xcbiAgICBAZG9jIFxcXCJTY2hlbWEgZm9yIHJlc3VsdHMgb2YgJ2FjY291bnQnIG9wZXJhdGlvbi5cXFwiXFxuICAgIEBtb2RlbCBbIChpbnZhcmlhbnQgKCE9IFxcXCJcXFwiIHNlbmRlcikpIF1cXG5cXG4gICAgYWNjb3VudDpzdHJpbmdcXG4gICAgYmFsYW5jZTpkZWNpbWFsXFxuICAgIGd1YXJkOmd1YXJkKVxcblxcblxcbiAgIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgIDsgQ2Fwc1xcblxcbiAgIChkZWZjYXAgVFJBTlNGRVI6Ym9vbFxcbiAgICAgKCBzZW5kZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIE1hbmFnZWQgY2FwYWJpbGl0eSBzZWFsaW5nIEFNT1VOVCBmb3IgdHJhbnNmZXIgZnJvbSBTRU5ERVIgdG8gXFxcXFxcbiAgICAgICAgICBcXFxcIFJFQ0VJVkVSLiBQZXJtaXRzIGFueSBudW1iZXIgb2YgdHJhbnNmZXJzIHVwIHRvIEFNT1VOVC5cXFwiXFxuICAgICBAbWFuYWdlZCBhbW91bnQgVFJBTlNGRVItbWdyXFxuICAgICApXFxuXFxuICAgKGRlZnVuIFRSQU5TRkVSLW1ncjpkZWNpbWFsXFxuICAgICAoIG1hbmFnZWQ6ZGVjaW1hbFxcbiAgICAgICByZXF1ZXN0ZWQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIE1hbmFnZXMgVFJBTlNGRVIgQU1PVU5UIGxpbmVhcmx5LCBcXFxcXFxuICAgICAgICAgIFxcXFwgc3VjaCB0aGF0IGEgcmVxdWVzdCBmb3IgMS4wIGFtb3VudCBvbiBhIDMuMCBcXFxcXFxuICAgICAgICAgIFxcXFwgbWFuYWdlZCBxdWFudGl0eSBlbWl0cyB1cGRhdGVkIGFtb3VudCAyLjAuXFxcIlxcbiAgICAgKVxcblxcbiAgIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgIDsgRnVuY3Rpb25hbGl0eVxcblxcblxcbiAgKGRlZnVuIHRyYW5zZmVyOnN0cmluZ1xcbiAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlcjpzdHJpbmdcXG4gICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICApXFxuICAgIEBkb2MgXFxcIiBUcmFuc2ZlciBBTU9VTlQgYmV0d2VlbiBhY2NvdW50cyBTRU5ERVIgYW5kIFJFQ0VJVkVSLiBcXFxcXFxuICAgICAgICAgXFxcXCBGYWlscyBpZiBlaXRoZXIgU0VOREVSIG9yIFJFQ0VJVkVSIGRvZXMgbm90IGV4aXN0LlxcXCJcXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAoIT0gcmVjZWl2ZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICBdXFxuICAgIClcXG5cXG4gICAoZGVmdW4gdHJhbnNmZXItY3JlYXRlOnN0cmluZ1xcbiAgICAgKCBzZW5kZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIFRyYW5zZmVyIEFNT1VOVCBiZXR3ZWVuIGFjY291bnRzIFNFTkRFUiBhbmQgUkVDRUlWRVIuIFxcXFxcXG4gICAgICAgICAgXFxcXCBGYWlscyBpZiBTRU5ERVIgZG9lcyBub3QgZXhpc3QuIElmIFJFQ0VJVkVSIGV4aXN0cywgZ3VhcmQgXFxcXFxcbiAgICAgICAgICBcXFxcIG11c3QgbWF0Y2ggZXhpc3RpbmcgdmFsdWUuIElmIFJFQ0VJVkVSIGRvZXMgbm90IGV4aXN0LCBcXFxcXFxuICAgICAgICAgIFxcXFwgUkVDRUlWRVIgYWNjb3VudCBpcyBjcmVhdGVkIHVzaW5nIFJFQ0VJVkVSLUdVQVJELiBcXFxcXFxuICAgICAgICAgIFxcXFwgU3ViamVjdCB0byBtYW5hZ2VtZW50IGJ5IFRSQU5TRkVSIGNhcGFiaWxpdHkuXFxcIlxcbiAgICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSByZWNlaXZlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICAgXVxcbiAgICAgKVxcblxcbiAgIChkZWZwYWN0IHRyYW5zZmVyLWNyb3NzY2hhaW46c3RyaW5nXFxuICAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICAgcmVjZWl2ZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyLWd1YXJkOmd1YXJkXFxuICAgICAgIHRhcmdldC1jaGFpbjpzdHJpbmdcXG4gICAgICAgYW1vdW50OmRlY2ltYWxcXG4gICAgIClcXG4gICAgIEBkb2MgXFxcIiAyLXN0ZXAgcGFjdCB0byB0cmFuc2ZlciBBTU9VTlQgZnJvbSBTRU5ERVIgb24gY3VycmVudCBjaGFpbiBcXFxcXFxuICAgICAgICAgIFxcXFwgdG8gUkVDRUlWRVIgb24gVEFSR0VULUNIQUlOIHZpYSBTUFYgcHJvb2YuIFxcXFxcXG4gICAgICAgICAgXFxcXCBUQVJHRVQtQ0hBSU4gbXVzdCBiZSBkaWZmZXJlbnQgdGhhbiBjdXJyZW50IGNoYWluIGlkLiBcXFxcXFxuICAgICAgICAgIFxcXFwgRmlyc3Qgc3RlcCBkZWJpdHMgQU1PVU5UIGNvaW5zIGluIFNFTkRFUiBhY2NvdW50IGFuZCB5aWVsZHMgXFxcXFxcbiAgICAgICAgICBcXFxcIFJFQ0VJVkVSLCBSRUNFSVZFUl9HVUFSRCBhbmQgQU1PVU5UIHRvIFRBUkdFVC1DSEFJTi4gXFxcXFxcbiAgICAgICAgICBcXFxcIFNlY29uZCBzdGVwIGNvbnRpbnVhdGlvbiBpcyBzZW50IGludG8gVEFSR0VULUNIQUlOIHdpdGggcHJvb2YgXFxcXFxcbiAgICAgICAgICBcXFxcIG9idGFpbmVkIGZyb20gdGhlIHNwdiAnb3V0cHV0JyBlbmRwb2ludCBvZiBDaGFpbndlYi4gXFxcXFxcbiAgICAgICAgICBcXFxcIFByb29mIGlzIHZhbGlkYXRlZCBhbmQgUkVDRUlWRVIgaXMgY3JlZGl0ZWQgd2l0aCBBTU9VTlQgXFxcXFxcbiAgICAgICAgICBcXFxcIGNyZWF0aW5nIGFjY291bnQgd2l0aCBSRUNFSVZFUl9HVUFSRCBhcyBuZWNlc3NhcnkuXFxcIlxcbiAgICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSByZWNlaXZlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHRhcmdldC1jaGFpbiBcXFwiXFxcIikpXFxuICAgICAgICAgICAgXVxcbiAgICAgKVxcblxcbiAgIChkZWZ1biBnZXQtYmFsYW5jZTpkZWNpbWFsXFxuICAgICAoIGFjY291bnQ6c3RyaW5nIClcXG4gICAgIFxcXCIgR2V0IGJhbGFuY2UgZm9yIEFDQ09VTlQuIEZhaWxzIGlmIGFjY291bnQgZG9lcyBub3QgZXhpc3QuXFxcIlxcbiAgICAgKVxcblxcbiAgIChkZWZ1biBkZXRhaWxzOm9iamVjdHthY2NvdW50LWRldGFpbHN9XFxuICAgICAoIGFjY291bnQ6IHN0cmluZyApXFxuICAgICBcXFwiIEdldCBhbiBvYmplY3Qgd2l0aCBkZXRhaWxzIG9mIEFDQ09VTlQuIFxcXFxcXG4gICAgIFxcXFwgRmFpbHMgaWYgYWNjb3VudCBkb2VzIG5vdCBleGlzdC5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIHByZWNpc2lvbjppbnRlZ2VyXFxuICAgICAoKVxcbiAgICAgXFxcIlJldHVybiB0aGUgbWF4aW11bSBhbGxvd2VkIGRlY2ltYWwgcHJlY2lzaW9uLlxcXCJcXG4gICAgIClcXG5cXG4gICAoZGVmdW4gZW5mb3JjZS11bml0OmJvb2xcXG4gICAgICggYW1vdW50OmRlY2ltYWwgKVxcbiAgICAgXFxcIiBFbmZvcmNlIG1pbmltdW0gcHJlY2lzaW9uIGFsbG93ZWQgZm9yIHRyYW5zYWN0aW9ucy5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIGNyZWF0ZS1hY2NvdW50OnN0cmluZ1xcbiAgICAgKCBhY2NvdW50OnN0cmluZ1xcbiAgICAgICBndWFyZDpndWFyZFxcbiAgICAgKVxcbiAgICAgXFxcIiBDcmVhdGUgQUNDT1VOVCB3aXRoIDAuMCBiYWxhbmNlLCB3aXRoIEdVQVJEIGNvbnRyb2xsaW5nIGFjY2Vzcy5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIHJvdGF0ZTpzdHJpbmdcXG4gICAgICggYWNjb3VudDpzdHJpbmdcXG4gICAgICAgbmV3LWd1YXJkOmd1YXJkXFxuICAgICApXFxuICAgICBcXFwiIFJvdGF0ZSBndWFyZCBmb3IgQUNDT1VOVC4gVHJhbnNhY3Rpb24gaXMgdmFsaWRhdGVkIGFnYWluc3QgXFxcXFxcbiAgICAgXFxcXCBleGlzdGluZyBndWFyZCBiZWZvcmUgaW5zdGFsbGluZyBuZXcgZ3VhcmQuIFxcXCJcXG4gICAgIClcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJmdW5naWJsZS1hc3NldC12MlwifSJ9" , "eyJoYXNoIjoibVZzMjNxNnJyUjZrWDFGX0ItamNCX05hLXdZdmR3dnRwa1cwQVNaZExjRSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihtb2R1bGUgY29pbiBHT1ZFUk5BTkNFXFxuXFxuICBAZG9jIFxcXCInY29pbicgcmVwcmVzZW50cyB0aGUgS2FkZW5hIENvaW4gQ29udHJhY3QuIFRoaXMgY29udHJhY3QgcHJvdmlkZXMgYm90aCB0aGUgXFxcXFxcbiAgXFxcXGJ1eS9yZWRlZW0gZ2FzIHN1cHBvcnQgaW4gdGhlIGZvcm0gb2YgJ2Z1bmQtdHgnLCBhcyB3ZWxsIGFzIHRyYW5zZmVyLCAgICAgICBcXFxcXFxuICBcXFxcY3JlZGl0LCBkZWJpdCwgY29pbmJhc2UsIGFjY291bnQgY3JlYXRpb24gYW5kIHF1ZXJ5LCBhcyB3ZWxsIGFzIFNQViBidXJuICAgIFxcXFxcXG4gIFxcXFxjcmVhdGUuIFRvIGFjY2VzcyB0aGUgY29pbiBjb250cmFjdCwgeW91IG1heSB1c2UgaXRzIGZ1bGx5LXF1YWxpZmllZCBuYW1lLCAgXFxcXFxcbiAgXFxcXG9yIGlzc3VlIHRoZSAnKHVzZSBjb2luKScgY29tbWFuZCBpbiB0aGUgYm9keSBvZiBhIG1vZHVsZSBkZWNsYXJhdGlvbi5cXFwiXFxuXFxuICBAbW9kZWxcXG4gICAgWyAoZGVmcHJvcGVydHkgY29uc2VydmVzLW1hc3NcXG4gICAgICAgICg9IChjb2x1bW4tZGVsdGEgY29pbi10YWJsZSAnYmFsYW5jZSkgMC4wKSlcXG5cXG4gICAgICAoZGVmcHJvcGVydHkgdmFsaWQtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgICAgICAoYW5kXFxuICAgICAgICAgICg-PSAobGVuZ3RoIGFjY291bnQpIDMpXFxuICAgICAgICAgICg8PSAobGVuZ3RoIGFjY291bnQpIDI1NikpKVxcbiAgICBdXFxuXFxuICAoaW1wbGVtZW50cyBmdW5naWJsZS12MilcXG5cXG4gIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cXG4gIDsgU2NoZW1hcyBhbmQgVGFibGVzXFxuXFxuICAoZGVmc2NoZW1hIGNvaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlRoZSBjb2luIGNvbnRyYWN0IHRva2VuIHNjaGVtYVxcXCJcXG4gICAgQG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBndWFyZDpndWFyZClcXG5cXG4gIChkZWZ0YWJsZSBjb2luLXRhYmxlOntjb2luLXNjaGVtYX0pXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENhcGFiaWxpdGllc1xcblxcbiAgKGRlZmNhcCBHT1ZFUk5BTkNFICgpXFxuICAgIChlbmZvcmNlIGZhbHNlIFxcXCJFbmZvcmNlIG5vbi11cGdyYWRlYWJpbGl0eVxcXCIpKVxcblxcbiAgKGRlZmNhcCBHQVMgKClcXG4gICAgXFxcIk1hZ2ljIGNhcGFiaWxpdHkgdG8gcHJvdGVjdCBnYXMgYnV5IGFuZCByZWRlZW1cXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIENPSU5CQVNFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IHRvIHByb3RlY3QgbWluZXIgcmV3YXJkXFxcIlxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBHRU5FU0lTICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGNvbnN0cmFpbmluZyBnZW5lc2lzIHRyYW5zYWN0aW9uc1xcXCJcXG4gICAgdHJ1ZSlcXG5cXG4gIChkZWZjYXAgUkVNRURJQVRFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnNcXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIERFQklUIChzZW5kZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgZGViaXRpbmcgb3BlcmF0aW9uc1xcXCJcXG4gICAgKGVuZm9yY2UtZ3VhcmQgKGF0ICdndWFyZCAocmVhZCBjb2luLXRhYmxlIHNlbmRlcikpKVxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIFxcXCJcXFwiKSBcXFwidmFsaWQgc2VuZGVyXFxcIikpXFxuXFxuICAoZGVmY2FwIENSRURJVCAocmVjZWl2ZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgY3JlZGl0aW5nIG9wZXJhdGlvbnNcXFwiXFxuICAgIChlbmZvcmNlICghPSByZWNlaXZlciBcXFwiXFxcIikgXFxcInZhbGlkIHJlY2VpdmVyXFxcIikpXFxuXFxuICAoZGVmY2FwIFJPVEFURSAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkF1dG9ub21vdXNseSBtYW5hZ2VkIGNhcGFiaWxpdHkgZm9yIGd1YXJkIHJvdGF0aW9uXFxcIlxcbiAgICBAbWFuYWdlZFxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBUUkFOU0ZFUjpib29sXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsXFxuICAgIClcXG4gICAgQG1hbmFnZWQgYW1vdW50IFRSQU5TRkVSLW1nclxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIHJlY2VpdmVyKSBcXFwic2FtZSBzZW5kZXIgYW5kIHJlY2VpdmVyXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApIFxcXCJQb3NpdGl2ZSBhbW91bnRcXFwiKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChDUkVESVQgcmVjZWl2ZXIpKVxcbiAgKVxcblxcbiAgKGRlZnVuIFRSQU5TRkVSLW1ncjpkZWNpbWFsXFxuICAgICggbWFuYWdlZDpkZWNpbWFsXFxuICAgICAgcmVxdWVzdGVkOmRlY2ltYWxcXG4gICAgKVxcblxcbiAgICAobGV0ICgobmV3YmFsICgtIG1hbmFnZWQgcmVxdWVzdGVkKSkpXFxuICAgICAgKGVuZm9yY2UgKD49IG5ld2JhbCAwLjApXFxuICAgICAgICAoZm9ybWF0IFxcXCJUUkFOU0ZFUiBleGNlZWRlZCBmb3IgYmFsYW5jZSB7fVxcXCIgW21hbmFnZWRdKSlcXG4gICAgICBuZXdiYWwpXFxuICApXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvbnN0YW50c1xcblxcbiAgKGRlZmNvbnN0IENPSU5fQ0hBUlNFVCBDSEFSU0VUX0xBVElOMVxcbiAgICBcXFwiVGhlIGRlZmF1bHQgY29pbiBjb250cmFjdCBjaGFyYWN0ZXIgc2V0XFxcIilcXG5cXG4gIChkZWZjb25zdCBNSU5JTVVNX1BSRUNJU0lPTiAxMlxcbiAgICBcXFwiTWluaW11bSBhbGxvd2VkIHByZWNpc2lvbiBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiKVxcblxcbiAgKGRlZmNvbnN0IE1JTklNVU1fQUNDT1VOVF9MRU5HVEggM1xcbiAgICBcXFwiTWluaW11bSBhY2NvdW50IGxlbmd0aCBhZG1pc3NpYmxlIGZvciBjb2luIGFjY291bnRzXFxcIilcXG5cXG4gIChkZWZjb25zdCBNQVhJTVVNX0FDQ09VTlRfTEVOR1RIIDI1NlxcbiAgICBcXFwiTWF4aW11bSBhY2NvdW50IG5hbWUgbGVuZ3RoIGFkbWlzc2libGUgZm9yIGNvaW4gYWNjb3VudHNcXFwiKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBVdGlsaXRpZXNcXG5cXG4gIChkZWZ1biBlbmZvcmNlLXVuaXQ6Ym9vbCAoYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgbWluaW11bSBwcmVjaXNpb24gYWxsb3dlZCBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiXFxuXFxuICAgIChlbmZvcmNlXFxuICAgICAgKD0gKGZsb29yIGFtb3VudCBNSU5JTVVNX1BSRUNJU0lPTilcXG4gICAgICAgICBhbW91bnQpXFxuICAgICAgKGZvcm1hdCBcXFwiQW1vdW50IHZpb2xhdGVzIG1pbmltdW0gcHJlY2lzaW9uOiB7fVxcXCIgW2Ftb3VudF0pKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdmFsaWRhdGUtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgdGhhdCBhbiBhY2NvdW50IG5hbWUgY29uZm9ybXMgdG8gdGhlIGNvaW4gY29udHJhY3QgXFxcXFxcbiAgICAgICAgIFxcXFxtaW5pbXVtIGFuZCBtYXhpbXVtIGxlbmd0aCByZXF1aXJlbWVudHMsIGFzIHdlbGwgYXMgdGhlICAgIFxcXFxcXG4gICAgICAgICBcXFxcbGF0aW4tMSBjaGFyYWN0ZXIgc2V0LlxcXCJcXG5cXG4gICAgKGVuZm9yY2VcXG4gICAgICAoaXMtY2hhcnNldCBDT0lOX0NIQVJTRVQgYWNjb3VudClcXG4gICAgICAoZm9ybWF0XFxuICAgICAgICBcXFwiQWNjb3VudCBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBjb2luIGNvbnRyYWN0IGNoYXJzZXQ6IHt9XFxcIlxcbiAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgKGxldCAoKGFjY291bnQtbGVuZ3RoIChsZW5ndGggYWNjb3VudCkpKVxcblxcbiAgICAgIChlbmZvcmNlXFxuICAgICAgICAoPj0gYWNjb3VudC1sZW5ndGggTUlOSU1VTV9BQ0NPVU5UX0xFTkdUSClcXG4gICAgICAgIChmb3JtYXRcXG4gICAgICAgICAgXFxcIkFjY291bnQgbmFtZSBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBtaW4gbGVuZ3RoIHJlcXVpcmVtZW50OiB7fVxcXCJcXG4gICAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgICAoZW5mb3JjZVxcbiAgICAgICAgKDw9IGFjY291bnQtbGVuZ3RoIE1BWElNVU1fQUNDT1VOVF9MRU5HVEgpXFxuICAgICAgICAoZm9ybWF0XFxuICAgICAgICAgIFxcXCJBY2NvdW50IG5hbWUgZG9lcyBub3QgY29uZm9ybSB0byB0aGUgbWF4IGxlbmd0aCByZXF1aXJlbWVudDoge31cXFwiXFxuICAgICAgICAgIFthY2NvdW50XSkpXFxuICAgICAgKVxcbiAgKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBDb2luIENvbnRyYWN0XFxuXFxuICAoZGVmdW4gZ2FzLW9ubHkgKClcXG4gICAgXFxcIlByZWRpY2F0ZSBmb3IgZ2FzLW9ubHkgdXNlciBndWFyZHMuXFxcIlxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKSlcXG5cXG4gIChkZWZ1biBnYXMtZ3VhcmQgKGd1YXJkOmd1YXJkKVxcbiAgICBcXFwiUHJlZGljYXRlIGZvciBnYXMgKyBzaW5nbGUga2V5IHVzZXIgZ3VhcmRzXFxcIlxcbiAgICAoZW5mb3JjZS1vbmVcXG4gICAgICBcXFwiRW5mb3JjZSBlaXRoZXIgdGhlIHByZXNlbmNlIG9mIGEgR0FTIGNhcCBvciBrZXlzZXRcXFwiXFxuICAgICAgWyAoZ2FzLW9ubHkpXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG4gICAgICBdKSlcXG5cXG4gIChkZWZ1biBidXktZ2FzOnN0cmluZyAoc2VuZGVyOnN0cmluZyB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCJUaGlzIGZ1bmN0aW9uIGRlc2NyaWJlcyB0aGUgbWFpbiAnZ2FzIGJ1eScgb3BlcmF0aW9uLiBBdCB0aGlzIHBvaW50IFxcXFxcXG4gICAgXFxcXE1JTkVSIGhhcyBiZWVuIGNob3NlbiBmcm9tIHRoZSBwb29sLCBhbmQgd2lsbCBiZSB2YWxpZGF0ZWQuIFRoZSBTRU5ERVIgICBcXFxcXFxuICAgIFxcXFxvZiB0aGlzIHRyYW5zYWN0aW9uIGhhcyBzcGVjaWZpZWQgYSBnYXMgbGltaXQgTElNSVQgKG1heGltdW0gZ2FzKSBmb3IgICAgXFxcXFxcbiAgICBcXFxcdGhlIHRyYW5zYWN0aW9uLCBhbmQgdGhlIHByaWNlIGlzIHRoZSBzcG90IHByaWNlIG9mIGdhcyBhdCB0aGF0IHRpbWUuICAgIFxcXFxcXG4gICAgXFxcXFRoZSBnYXMgYnV5IHdpbGwgYmUgZXhlY3V0ZWQgcHJpb3IgdG8gZXhlY3V0aW5nIFNFTkRFUidzIGNvZGUuXFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCB0b3RhbClcXG4gICAgKGVuZm9yY2UgKD4gdG90YWwgMC4wKSBcXFwiZ2FzIHN1cHBseSBtdXN0IGJlIGEgcG9zaXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuICAgICAgKGRlYml0IHNlbmRlciB0b3RhbCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZWRlZW0tZ2FzOnN0cmluZyAobWluZXI6c3RyaW5nIG1pbmVyLWd1YXJkOmd1YXJkIHNlbmRlcjpzdHJpbmcgdG90YWw6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiVGhpcyBmdW5jdGlvbiBkZXNjcmliZXMgdGhlIG1haW4gJ3JlZGVlbSBnYXMnIG9wZXJhdGlvbi4gQXQgdGhpcyAgICBcXFxcXFxuICAgIFxcXFxwb2ludCwgdGhlIFNFTkRFUidzIHRyYW5zYWN0aW9uIGhhcyBiZWVuIGV4ZWN1dGVkLCBhbmQgdGhlIGdhcyB0aGF0ICAgICAgXFxcXFxcbiAgICBcXFxcd2FzIGNoYXJnZWQgaGFzIGJlZW4gY2FsY3VsYXRlZC4gTUlORVIgd2lsbCBiZSBjcmVkaXRlZCB0aGUgZ2FzIGNvc3QsICAgIFxcXFxcXG4gICAgXFxcXGFuZCBTRU5ERVIgd2lsbCByZWNlaXZlIHRoZSByZW1haW5kZXIgdXAgdG8gdGhlIGxpbWl0XFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBtaW5lcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG4gICAgKHZhbGlkYXRlLWFjY291bnQgbWluZXIpXFxuICAgIChlbmZvcmNlLXVuaXQgdG90YWwpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKEdBUykpXFxuICAgIChsZXQqXFxuICAgICAgKChmZWUgKHJlYWQtZGVjaW1hbCBcXFwiZmVlXFxcIikpXFxuICAgICAgIChyZWZ1bmQgKC0gdG90YWwgZmVlKSkpXFxuXFxuICAgICAgKGVuZm9yY2UtdW5pdCBmZWUpXFxuICAgICAgKGVuZm9yY2UgKD49IGZlZSAwLjApXFxuICAgICAgICBcXFwiZmVlIG11c3QgYmUgYSBub24tbmVnYXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAgIChlbmZvcmNlICg-PSByZWZ1bmQgMC4wKVxcbiAgICAgICAgXFxcInJlZnVuZCBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIHF1YW50aXR5XFxcIilcXG5cXG4gICAgICAgIDsgZGlyZWN0bHkgdXBkYXRlIGluc3RlYWQgb2YgY3JlZGl0XFxuICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHNlbmRlcilcXG4gICAgICAgIChpZiAoPiByZWZ1bmQgMC4wKVxcbiAgICAgICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgc2VuZGVyXFxuICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOj0gYmFsYW5jZSB9XFxuICAgICAgICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIHNlbmRlclxcbiAgICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCI6ICgrIGJhbGFuY2UgcmVmdW5kKSB9KSlcXG5cXG4gICAgICAgICAgXFxcIm5vb3BcXFwiKSlcXG5cXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChDUkVESVQgbWluZXIpXFxuICAgICAgICAoaWYgKD4gZmVlIDAuMClcXG4gICAgICAgICAgKGNyZWRpdCBtaW5lciBtaW5lci1ndWFyZCBmZWUpXFxuICAgICAgICAgIFxcXCJub29wXFxcIikpXFxuICAgICAgKVxcblxcbiAgICApXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFjY291bnQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZClcXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKSBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChpbnNlcnQgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgICA6IGd1YXJkXFxuICAgICAgfSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGdldC1iYWxhbmNlOmRlY2ltYWwgKGFjY291bnQ6c3RyaW5nKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcbiAgICAgIGJhbGFuY2VcXG4gICAgICApXFxuICAgIClcXG5cXG4gIChkZWZ1biBkZXRhaWxzOm9iamVjdHtmdW5naWJsZS12Mi5hY2NvdW50LWRldGFpbHN9XFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIiA6PSBnIH1cXG4gICAgICB7IFxcXCJhY2NvdW50XFxcIiA6IGFjY291bnRcXG4gICAgICAsIFxcXCJiYWxhbmNlXFxcIiA6IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIjogZyB9KVxcbiAgICApXFxuXFxuICAoZGVmdW4gcm90YXRlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgbmV3LWd1YXJkOmd1YXJkKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChST1RBVEUgYWNjb3VudClcXG4gICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IG9sZC1ndWFyZCB9XFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBvbGQtZ3VhcmQpXFxuXFxuICAgICAgICAodXBkYXRlIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgICB7IFxcXCJndWFyZFxcXCIgOiBuZXctZ3VhcmQgfVxcbiAgICAgICAgICApKSlcXG4gICAgKVxcblxcblxcbiAgKGRlZnVuIHByZWNpc2lvbjppbnRlZ2VyXFxuICAgICgpXFxuICAgIE1JTklNVU1fUFJFQ0lTSU9OKVxcblxcbiAgKGRlZnVuIHRyYW5zZmVyOnN0cmluZyAoc2VuZGVyOnN0cmluZyByZWNlaXZlcjpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcylcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgcmVjZWl2ZXIpKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgICh3aXRoLXJlYWQgY29pbi10YWJsZSByZWNlaXZlclxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IGcgfVxcblxcbiAgICAgICAgKGNyZWRpdCByZWNlaXZlciBnIGFtb3VudCkpXFxuICAgICAgKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdHJhbnNmZXItY3JlYXRlOnN0cmluZ1xcbiAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5IGNvbnNlcnZlcy1tYXNzKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgIChjcmVkaXQgcmVjZWl2ZXIgcmVjZWl2ZXItZ3VhcmQgYW1vdW50KSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGNvaW5iYXNlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYWNjb3VudC1ndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiSW50ZXJuYWwgZnVuY3Rpb24gZm9yIHRoZSBpbml0aWFsIGNyZWF0aW9uIG9mIGNvaW5zLiAgVGhpcyBmdW5jdGlvbiBcXFxcXFxuICAgIFxcXFxjYW5ub3QgYmUgdXNlZCBvdXRzaWRlIG9mIHRoZSBjb2luIGNvbnRyYWN0LlxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKD4gYW1vdW50IDAuMCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChDT0lOQkFTRSkpXFxuICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgIChjcmVkaXQgYWNjb3VudCBhY2NvdW50LWd1YXJkIGFtb3VudCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZW1lZGlhdGU6c3RyaW5nIChhY2NvdW50OnN0cmluZyBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQWxsb3dzIGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnMuIFRoaXMgZnVuY3Rpb24gXFxcXFxcbiAgICAgICAgIFxcXFxpcyBwcm90ZWN0ZWQgYnkgdGhlIFJFTUVESUFURSBjYXBhYmlsaXR5XFxcIlxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG5cXG4gICAgKGVuZm9yY2UgKD4gYW1vdW50IDAuMClcXG4gICAgICBcXFwiUmVtZWRpYXRpb24gYW1vdW50IG11c3QgYmUgcG9zaXRpdmVcXFwiKVxcblxcbiAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgKHJlcXVpcmUtY2FwYWJpbGl0eSAoUkVNRURJQVRFKSlcXG4gICAgKHdpdGgtcmVhZCBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6PSBiYWxhbmNlIH1cXG5cXG4gICAgICAoZW5mb3JjZSAoPD0gYW1vdW50IGJhbGFuY2UpIFxcXCJJbnN1ZmZpY2llbnQgZnVuZHNcXFwiKVxcblxcbiAgICAgICh1cGRhdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgtIGJhbGFuY2UgYW1vdW50KSB9XFxuICAgICAgICApKVxcbiAgICApXFxuXFxuICAoZGVmcGFjdCBmdW5kLXR4IChzZW5kZXI6c3RyaW5nIG1pbmVyOnN0cmluZyBtaW5lci1ndWFyZDpndWFyZCB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCInZnVuZC10eCcgaXMgYSBzcGVjaWFsIHBhY3QgdG8gZnVuZCBhIHRyYW5zYWN0aW9uIGluIHR3byBzdGVwcywgICAgIFxcXFxcXG4gICAgXFxcXHdpdGggdGhlIGFjdHVhbCB0cmFuc2FjdGlvbiB0cmFuc3BpcmluZyBpbiB0aGUgbWlkZGxlOiAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXFxcXFxcbiAgICBcXFxcICAxKSBBIGJ1eWluZyBwaGFzZSwgZGViaXRpbmcgdGhlIHNlbmRlciBmb3IgdG90YWwgZ2FzIGFuZCBmZWUsIHlpZWxkaW5nIFxcXFxcXG4gICAgXFxcXCAgICAgVFhfTUFYX0NIQVJHRS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgIDIpIEEgc2V0dGxlbWVudCBwaGFzZSwgcmVzdW1pbmcgVFhfTUFYX0NIQVJHRSwgYW5kIGFsbG9jYXRpbmcgdG8gdGhlICAgXFxcXFxcbiAgICBcXFxcICAgICBjb2luYmFzZSBhY2NvdW50IGZvciB1c2VkIGdhcyBhbmQgZmVlLCBhbmQgc2VuZGVyIGFjY291bnQgZm9yIGJhbC0gIFxcXFxcXG4gICAgXFxcXCAgICAgYW5jZSAodW51c2VkIGdhcywgaWYgYW55KS5cXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiB0b3RhbCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IG1pbmVyKSlcXG4gICAgICAgICAgICAgOyhwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcykgbm90IHN1cHBvcnRlZCB5ZXRcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXAgKGJ1eS1nYXMgc2VuZGVyIHRvdGFsKSlcXG4gICAgKHN0ZXAgKHJlZGVlbS1nYXMgbWluZXIgbWluZXItZ3VhcmQgc2VuZGVyIHRvdGFsKSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGRlYml0OnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkRlYml0IEFNT1VOVCBmcm9tIEFDQ09VTlQgYmFsYW5jZVxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApXFxuICAgICAgXFxcImRlYml0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKERFQklUIGFjY291bnQpKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcblxcbiAgICAgIChlbmZvcmNlICg8PSBhbW91bnQgYmFsYW5jZSkgXFxcIkluc3VmZmljaWVudCBmdW5kc1xcXCIpXFxuXFxuICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogKC0gYmFsYW5jZSBhbW91bnQpIH1cXG4gICAgICAgICkpXFxuICAgIClcXG5cXG5cXG4gIChkZWZ1biBjcmVkaXQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQ3JlZGl0IEFNT1VOVCB0byBBQ0NPVU5UIGJhbGFuY2VcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKSBcXFwiY3JlZGl0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KSlcXG4gICAgKHdpdGgtZGVmYXVsdC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogMC4wLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmQgfVxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UsIFxcXCJndWFyZFxcXCIgOj0gcmV0ZyB9XFxuICAgICAgOyB3ZSBkb24ndCB3YW50IHRvIG92ZXJ3cml0ZSBhbiBleGlzdGluZyBndWFyZCB3aXRoIHRoZSB1c2VyLXN1cHBsaWVkIG9uZVxcbiAgICAgIChlbmZvcmNlICg9IHJldGcgZ3VhcmQpXFxuICAgICAgICBcXFwiYWNjb3VudCBndWFyZHMgZG8gbm90IG1hdGNoXFxcIilcXG5cXG4gICAgICAod3JpdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgrIGJhbGFuY2UgYW1vdW50KVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiICAgOiByZXRnXFxuICAgICAgICB9KVxcbiAgICAgICkpXFxuXFxuXFxuICAoZGVmc2NoZW1hIGNyb3NzY2hhaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlNjaGVtYSBmb3IgeWllbGRlZCB2YWx1ZSBpbiBjcm9zcy1jaGFpbiB0cmFuc2ZlcnNcXFwiXFxuICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICBhbW91bnQ6ZGVjaW1hbClcXG5cXG4gIChkZWZwYWN0IHRyYW5zZmVyLWNyb3NzY2hhaW46c3RyaW5nXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyLWd1YXJkOmd1YXJkXFxuICAgICAgdGFyZ2V0LWNoYWluOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXBcXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCByZWNlaXZlcilcXG5cXG4gICAgICAgIChlbmZvcmNlICghPSBcXFwiXFxcIiB0YXJnZXQtY2hhaW4pIFxcXCJlbXB0eSB0YXJnZXQtY2hhaW5cXFwiKVxcbiAgICAgICAgKGVuZm9yY2UgKCE9IChhdCAnY2hhaW4taWQgKGNoYWluLWRhdGEpKSB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgIFxcXCJjYW5ub3QgcnVuIGNyb3NzLWNoYWluIHRyYW5zZmVycyB0byB0aGUgc2FtZSBjaGFpblxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgICAgICBcXFwidHJhbnNmZXIgcXVhbnRpdHkgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgICAgIDs7IHN0ZXAgMSAtIGRlYml0IGRlbGV0ZS1hY2NvdW50IG9uIGN1cnJlbnQgY2hhaW5cXG4gICAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcblxcbiAgICAgICAgKGxldFxcbiAgICAgICAgICAoKGNyb3NzY2hhaW4tZGV0YWlsczpvYmplY3R7Y3Jvc3NjaGFpbi1zY2hlbWF9XFxuICAgICAgICAgICAgeyBcXFwicmVjZWl2ZXJcXFwiIDogcmVjZWl2ZXJcXG4gICAgICAgICAgICAsIFxcXCJyZWNlaXZlci1ndWFyZFxcXCIgOiByZWNlaXZlci1ndWFyZFxcbiAgICAgICAgICAgICwgXFxcImFtb3VudFxcXCIgOiBhbW91bnRcXG4gICAgICAgICAgICB9KSlcXG4gICAgICAgICAgKHlpZWxkIGNyb3NzY2hhaW4tZGV0YWlscyB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgICkpKVxcblxcbiAgICAoc3RlcFxcbiAgICAgIChyZXN1bWVcXG4gICAgICAgIHsgXFxcInJlY2VpdmVyXFxcIiA6PSByZWNlaXZlclxcbiAgICAgICAgLCBcXFwicmVjZWl2ZXItZ3VhcmRcXFwiIDo9IHJlY2VpdmVyLWd1YXJkXFxuICAgICAgICAsIFxcXCJhbW91bnRcXFwiIDo9IGFtb3VudFxcbiAgICAgICAgfVxcblxcbiAgICAgICAgOzsgc3RlcCAyIC0gY3JlZGl0IGNyZWF0ZSBhY2NvdW50IG9uIHRhcmdldCBjaGFpblxcbiAgICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHJlY2VpdmVyKVxcbiAgICAgICAgICAoY3JlZGl0IHJlY2VpdmVyIHJlY2VpdmVyLWd1YXJkIGFtb3VudCkpXFxuICAgICAgICApKVxcbiAgICApXFxuXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvaW4gYWxsb2NhdGlvbnNcXG5cXG4gIChkZWZzY2hlbWEgYWxsb2NhdGlvbi1zY2hlbWFcXG4gICAgQGRvYyBcXFwiR2VuZXNpcyBhbGxvY2F0aW9uIHJlZ2lzdHJ5XFxcIlxcbiAgICA7QG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBkYXRlOnRpbWVcXG4gICAgZ3VhcmQ6Z3VhcmRcXG4gICAgcmVkZWVtZWQ6Ym9vbClcXG5cXG4gIChkZWZ0YWJsZSBhbGxvY2F0aW9uLXRhYmxlOnthbGxvY2F0aW9uLXNjaGVtYX0pXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFsbG9jYXRpb24tYWNjb3VudFxcbiAgICAoIGFjY291bnQ6c3RyaW5nXFxuICAgICAgZGF0ZTp0aW1lXFxuICAgICAga2V5c2V0LXJlZjpzdHJpbmdcXG4gICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICApXFxuXFxuICAgIEBkb2MgXFxcIkFkZCBhbiBlbnRyeSB0byB0aGUgY29pbiBhbGxvY2F0aW9uIHRhYmxlLiBUaGlzIGZ1bmN0aW9uIFxcXFxcXG4gICAgICAgICBcXFxcYWxzbyBjcmVhdGVzIGEgY29ycmVzcG9uZGluZyBlbXB0eSBjb2luIGNvbnRyYWN0IGFjY291bnQgXFxcXFxcbiAgICAgICAgIFxcXFxvZiB0aGUgc2FtZSBuYW1lIGFuZCBndWFyZC4gUmVxdWlyZXMgR0VORVNJUyBjYXBhYmlsaXR5LiBcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHRU5FU0lTKSlcXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG4gICAgKGVuZm9yY2UgKD49IGFtb3VudCAwLjApXFxuICAgICAgXFxcImFsbG9jYXRpb24gYW1vdW50IG11c3QgYmUgbm9uLW5lZ2F0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChsZXRcXG4gICAgICAoKGd1YXJkOmd1YXJkIChrZXlzZXQtcmVmLWd1YXJkIGtleXNldC1yZWYpKSlcXG5cXG4gICAgICAoY3JlYXRlLWFjY291bnQgYWNjb3VudCBndWFyZClcXG5cXG4gICAgICAoaW5zZXJ0IGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiBhbW91bnRcXG4gICAgICAgICwgXFxcImRhdGVcXFwiIDogZGF0ZVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmRcXG4gICAgICAgICwgXFxcInJlZGVlbWVkXFxcIiA6IGZhbHNlXFxuICAgICAgICB9KSkpXFxuXFxuICAoZGVmdW4gcmVsZWFzZS1hbGxvY2F0aW9uXFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcblxcbiAgICBAZG9jIFxcXCJSZWxlYXNlIGZ1bmRzIGFzc29jaWF0ZWQgd2l0aCBhbGxvY2F0aW9uIEFDQ09VTlQgaW50byBtYWluIGxlZGdlci4gICBcXFxcXFxuICAgICAgICAgXFxcXEFDQ09VTlQgbXVzdCBhbHJlYWR5IGV4aXN0IGluIG1haW4gbGVkZ2VyLiBBbGxvY2F0aW9uIGlzIGRlYWN0aXZhdGVkIFxcXFxcXG4gICAgICAgICBcXFxcYWZ0ZXIgcmVsZWFzZS5cXFwiXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAod2l0aC1yZWFkIGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2VcXG4gICAgICAsIFxcXCJkYXRlXFxcIiA6PSByZWxlYXNlLXRpbWVcXG4gICAgICAsIFxcXCJyZWRlZW1lZFxcXCIgOj0gcmVkZWVtZWRcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgOj0gZ3VhcmRcXG4gICAgICB9XFxuXFxuICAgICAgKGxldCAoKGN1cnItdGltZTp0aW1lIChhdCAnYmxvY2stdGltZSAoY2hhaW4tZGF0YSkpKSlcXG5cXG4gICAgICAgIChlbmZvcmNlIChub3QgcmVkZWVtZWQpXFxuICAgICAgICAgIFxcXCJhbGxvY2F0aW9uIGZ1bmRzIGhhdmUgYWxyZWFkeSBiZWVuIHJlZGVlbWVkXFxcIilcXG5cXG4gICAgICAgIChlbmZvcmNlXFxuICAgICAgICAgICg-PSBjdXJyLXRpbWUgcmVsZWFzZS10aW1lKVxcbiAgICAgICAgICAoZm9ybWF0IFxcXCJmdW5kcyBsb2NrZWQgdW50aWwge30uIGN1cnJlbnQgdGltZToge31cXFwiIFtyZWxlYXNlLXRpbWUgY3Vyci10aW1lXSkpXFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG5cXG4gICAgICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgICAgICAoY3JlZGl0IGFjY291bnQgZ3VhcmQgYmFsYW5jZSlcXG5cXG4gICAgICAgICAgKHVwZGF0ZSBhbGxvY2F0aW9uLXRhYmxlIGFjY291bnRcXG4gICAgICAgICAgICB7IFxcXCJyZWRlZW1lZFxcXCIgOiB0cnVlXFxuICAgICAgICAgICAgLCBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAgICAgICB9KVxcblxcbiAgICAgICAgICBcXFwiQWxsb2NhdGlvbiBzdWNjZXNzZnVsbHkgcmVsZWFzZWQgdG8gbWFpbiBsZWRnZXJcXFwiKVxcbiAgICApKSlcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJjb2luLWNvbnRyYWN0LXYyXCJ9In0" + , + "eyJoYXNoIjoiS1BleXNfYndLeHpGV1M4cEdrWVg0QmZSWkh6MXhiVm43MkVTSk9PRGs0WSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihjb2luLnJlbWVkaWF0ZSBcXFwic2VuZGVyMDdcXFwiIDEzMzcuNylcXG4oY29pbi5yZW1lZGlhdGUgXFxcInNlbmRlcjA5XFxcIiAxMzM3LjkpXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJkZXZuZXQtb3RoZXItcmVtZWRpYXRpb25zXCJ9In0" ] diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 3c6196e657..bbe5edcbfe 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -232,8 +232,6 @@ blockTests tio envIo = after AllSucceed "Block Transaction Tests" $ validateBlock $ _blockResp_block resp - - -- | Rosetta construction submit endpoint tests (i.e. tx submission directly to mempool) -- constructionSubmitTests :: RosettaTest @@ -241,7 +239,7 @@ constructionSubmitTests tio envIo = testCaseSteps "Construction Submit Tests" $ cenv <- envIo step "build one-off construction submit request" - SubmitBatch (c NEL.:| []) <- mkTransfer tio + SubmitBatch (c NEL.:| []) <- mkTransfer "sender00" "sender01" sender00 tio let rk = cmdToRequestKey c req = ConstructionSubmitReq nid (encodeToText c) @@ -432,21 +430,26 @@ validateOp idx amount opType acct o = do -- | Build a simple transfer from sender00 to sender01 -- -mkTransfer :: IO (Time Micros) -> IO SubmitBatch -mkTransfer tio = do +mkTransfer + :: Text + -> Text + -> SimpleKeyPair + -> IO (Time Micros) + -> IO SubmitBatch +mkTransfer sender receiver keys tio = do t <- toTxCreationTime <$> tio n <- readIORef nonceRef c <- buildTextCmd $ set cbSigners - [ mkSigner' sender00 - [ mkTransferCap "sender00" "sender01" 1.0 + [ mkSigner' keys + [ mkTransferCap sender receiver 1.0 , mkGasCap ] ] $ set cbCreationTime t $ set cbNetworkId (Just v) $ mkCmd ("nonce-transfer-" <> sshow t <> "-" <> sshow n) - $ mkExec' "(coin.transfer \"sender00\" \"sender01\" 1.0)" + $ mkExec' ("(coin.transfer \"" <> sender <> "\" \"" <> receiver <> "\" 1.0)") modifyIORef' nonceRef (+1) return $ SubmitBatch (pure c) @@ -461,7 +464,7 @@ transferOneAsync -> (RequestKeys -> IO ()) -> IO PollResponses transferOneAsync tio cenv callback = do - batch0 <- mkTransfer tio + batch0 <- mkTransfer "sender00" "sender01" sender00 tio void $! callback (f batch0) rks <- sending cid cenv batch0 prs <- polling cid cenv rks ExpectPactResult diff --git a/tools/ea/Ea.hs b/tools/ea/Ea.hs index 1e15bb079e..5b4cd9c91f 100644 --- a/tools/ea/Ea.hs +++ b/tools/ea/Ea.hs @@ -234,10 +234,12 @@ genTxModules = void $ do putStrLn "Done." where gen tag remeds = genTxModule tag $ upgrades <> remeds - genOtherTxs = gen "Other" [] - genDevTxs = gen "Development" + genOtherTxs = gen "Other" ["pact/coin-contract/remediations/devother/remediations.yaml"] + genDevTxs = gen "Development" + ["pact/coin-contract/remediations/devnet/remediations.yaml"] + genMain :: Int -> IO () genMain chain = gen ("Mainnet" <> sshow chain) ["pact/coin-contract/remediations/mainnet/remediations" <> show chain <> ".yaml"] From 8e15889055c7c065a22979bc4dd29f71d5744db3 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Mon, 6 Jul 2020 17:12:51 -0400 Subject: [PATCH 31/48] remove fasttimed cpm payload --- .../remediations/testnet/remediations.yaml | 6 ----- .../Transactions/FastTimedCPMTransactions.hs | 22 ------------------- 2 files changed, 28 deletions(-) delete mode 100644 pact/coin-contract/remediations/testnet/remediations.yaml delete mode 100644 src/Chainweb/Pact/Transactions/FastTimedCPMTransactions.hs diff --git a/pact/coin-contract/remediations/testnet/remediations.yaml b/pact/coin-contract/remediations/testnet/remediations.yaml deleted file mode 100644 index c435a0a1b1..0000000000 --- a/pact/coin-contract/remediations/testnet/remediations.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# testnet remediations - -code: |- - (coin.remediate "sender00" 1337.7) -nonce: testnet-other-remediations -keyPairs: [] \ No newline at end of file diff --git a/src/Chainweb/Pact/Transactions/FastTimedCPMTransactions.hs b/src/Chainweb/Pact/Transactions/FastTimedCPMTransactions.hs deleted file mode 100644 index f6a3a45827..0000000000 --- a/src/Chainweb/Pact/Transactions/FastTimedCPMTransactions.hs +++ /dev/null @@ -1,22 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} - --- This module is auto-generated. DO NOT EDIT IT MANUALLY. - -module Chainweb.Pact.Transactions.FastTimedCPMTransactions ( transactions ) where - -import Data.Bifunctor (first) - -import Chainweb.Transaction -import Chainweb.Utils - -transactions :: IO [ChainwebTransaction] -transactions = - let decodeTx t = - fromEitherM . (first (userError . show)) . codecDecode chainwebPayloadCodec =<< decodeB64UrlNoPaddingText t - in mapM decodeTx [ - "eyJoYXNoIjoiMDVCdGo3ZUJaQlc3by1TYUxvVmhBaWNNVVBaVUJiRzZRVDhfTEFrQ3hIcyIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihpbnRlcmZhY2UgZnVuZ2libGUtdjJcXG5cXG4gIFxcXCIgU3RhbmRhcmQgZm9yIGZ1bmdpYmxlIGNvaW5zIGFuZCB0b2tlbnMgYXMgc3BlY2lmaWVkIGluIEtJUC0wMDAyLiBcXFwiXFxuXFxuICAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICAgOyBTY2hlbWFcXG5cXG4gICAoZGVmc2NoZW1hIGFjY291bnQtZGV0YWlsc1xcbiAgICBAZG9jIFxcXCJTY2hlbWEgZm9yIHJlc3VsdHMgb2YgJ2FjY291bnQnIG9wZXJhdGlvbi5cXFwiXFxuICAgIEBtb2RlbCBbIChpbnZhcmlhbnQgKCE9IFxcXCJcXFwiIHNlbmRlcikpIF1cXG5cXG4gICAgYWNjb3VudDpzdHJpbmdcXG4gICAgYmFsYW5jZTpkZWNpbWFsXFxuICAgIGd1YXJkOmd1YXJkKVxcblxcblxcbiAgIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgIDsgQ2Fwc1xcblxcbiAgIChkZWZjYXAgVFJBTlNGRVI6Ym9vbFxcbiAgICAgKCBzZW5kZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIE1hbmFnZWQgY2FwYWJpbGl0eSBzZWFsaW5nIEFNT1VOVCBmb3IgdHJhbnNmZXIgZnJvbSBTRU5ERVIgdG8gXFxcXFxcbiAgICAgICAgICBcXFxcIFJFQ0VJVkVSLiBQZXJtaXRzIGFueSBudW1iZXIgb2YgdHJhbnNmZXJzIHVwIHRvIEFNT1VOVC5cXFwiXFxuICAgICBAbWFuYWdlZCBhbW91bnQgVFJBTlNGRVItbWdyXFxuICAgICApXFxuXFxuICAgKGRlZnVuIFRSQU5TRkVSLW1ncjpkZWNpbWFsXFxuICAgICAoIG1hbmFnZWQ6ZGVjaW1hbFxcbiAgICAgICByZXF1ZXN0ZWQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIE1hbmFnZXMgVFJBTlNGRVIgQU1PVU5UIGxpbmVhcmx5LCBcXFxcXFxuICAgICAgICAgIFxcXFwgc3VjaCB0aGF0IGEgcmVxdWVzdCBmb3IgMS4wIGFtb3VudCBvbiBhIDMuMCBcXFxcXFxuICAgICAgICAgIFxcXFwgbWFuYWdlZCBxdWFudGl0eSBlbWl0cyB1cGRhdGVkIGFtb3VudCAyLjAuXFxcIlxcbiAgICAgKVxcblxcbiAgIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgIDsgRnVuY3Rpb25hbGl0eVxcblxcblxcbiAgKGRlZnVuIHRyYW5zZmVyOnN0cmluZ1xcbiAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlcjpzdHJpbmdcXG4gICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICApXFxuICAgIEBkb2MgXFxcIiBUcmFuc2ZlciBBTU9VTlQgYmV0d2VlbiBhY2NvdW50cyBTRU5ERVIgYW5kIFJFQ0VJVkVSLiBcXFxcXFxuICAgICAgICAgXFxcXCBGYWlscyBpZiBlaXRoZXIgU0VOREVSIG9yIFJFQ0VJVkVSIGRvZXMgbm90IGV4aXN0LlxcXCJcXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAoIT0gcmVjZWl2ZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICBdXFxuICAgIClcXG5cXG4gICAoZGVmdW4gdHJhbnNmZXItY3JlYXRlOnN0cmluZ1xcbiAgICAgKCBzZW5kZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIFRyYW5zZmVyIEFNT1VOVCBiZXR3ZWVuIGFjY291bnRzIFNFTkRFUiBhbmQgUkVDRUlWRVIuIFxcXFxcXG4gICAgICAgICAgXFxcXCBGYWlscyBpZiBTRU5ERVIgZG9lcyBub3QgZXhpc3QuIElmIFJFQ0VJVkVSIGV4aXN0cywgZ3VhcmQgXFxcXFxcbiAgICAgICAgICBcXFxcIG11c3QgbWF0Y2ggZXhpc3RpbmcgdmFsdWUuIElmIFJFQ0VJVkVSIGRvZXMgbm90IGV4aXN0LCBcXFxcXFxuICAgICAgICAgIFxcXFwgUkVDRUlWRVIgYWNjb3VudCBpcyBjcmVhdGVkIHVzaW5nIFJFQ0VJVkVSLUdVQVJELiBcXFxcXFxuICAgICAgICAgIFxcXFwgU3ViamVjdCB0byBtYW5hZ2VtZW50IGJ5IFRSQU5TRkVSIGNhcGFiaWxpdHkuXFxcIlxcbiAgICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSByZWNlaXZlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICAgXVxcbiAgICAgKVxcblxcbiAgIChkZWZwYWN0IHRyYW5zZmVyLWNyb3NzY2hhaW46c3RyaW5nXFxuICAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICAgcmVjZWl2ZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyLWd1YXJkOmd1YXJkXFxuICAgICAgIHRhcmdldC1jaGFpbjpzdHJpbmdcXG4gICAgICAgYW1vdW50OmRlY2ltYWxcXG4gICAgIClcXG4gICAgIEBkb2MgXFxcIiAyLXN0ZXAgcGFjdCB0byB0cmFuc2ZlciBBTU9VTlQgZnJvbSBTRU5ERVIgb24gY3VycmVudCBjaGFpbiBcXFxcXFxuICAgICAgICAgIFxcXFwgdG8gUkVDRUlWRVIgb24gVEFSR0VULUNIQUlOIHZpYSBTUFYgcHJvb2YuIFxcXFxcXG4gICAgICAgICAgXFxcXCBUQVJHRVQtQ0hBSU4gbXVzdCBiZSBkaWZmZXJlbnQgdGhhbiBjdXJyZW50IGNoYWluIGlkLiBcXFxcXFxuICAgICAgICAgIFxcXFwgRmlyc3Qgc3RlcCBkZWJpdHMgQU1PVU5UIGNvaW5zIGluIFNFTkRFUiBhY2NvdW50IGFuZCB5aWVsZHMgXFxcXFxcbiAgICAgICAgICBcXFxcIFJFQ0VJVkVSLCBSRUNFSVZFUl9HVUFSRCBhbmQgQU1PVU5UIHRvIFRBUkdFVC1DSEFJTi4gXFxcXFxcbiAgICAgICAgICBcXFxcIFNlY29uZCBzdGVwIGNvbnRpbnVhdGlvbiBpcyBzZW50IGludG8gVEFSR0VULUNIQUlOIHdpdGggcHJvb2YgXFxcXFxcbiAgICAgICAgICBcXFxcIG9idGFpbmVkIGZyb20gdGhlIHNwdiAnb3V0cHV0JyBlbmRwb2ludCBvZiBDaGFpbndlYi4gXFxcXFxcbiAgICAgICAgICBcXFxcIFByb29mIGlzIHZhbGlkYXRlZCBhbmQgUkVDRUlWRVIgaXMgY3JlZGl0ZWQgd2l0aCBBTU9VTlQgXFxcXFxcbiAgICAgICAgICBcXFxcIGNyZWF0aW5nIGFjY291bnQgd2l0aCBSRUNFSVZFUl9HVUFSRCBhcyBuZWNlc3NhcnkuXFxcIlxcbiAgICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSByZWNlaXZlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHRhcmdldC1jaGFpbiBcXFwiXFxcIikpXFxuICAgICAgICAgICAgXVxcbiAgICAgKVxcblxcbiAgIChkZWZ1biBnZXQtYmFsYW5jZTpkZWNpbWFsXFxuICAgICAoIGFjY291bnQ6c3RyaW5nIClcXG4gICAgIFxcXCIgR2V0IGJhbGFuY2UgZm9yIEFDQ09VTlQuIEZhaWxzIGlmIGFjY291bnQgZG9lcyBub3QgZXhpc3QuXFxcIlxcbiAgICAgKVxcblxcbiAgIChkZWZ1biBkZXRhaWxzOm9iamVjdHthY2NvdW50LWRldGFpbHN9XFxuICAgICAoIGFjY291bnQ6IHN0cmluZyApXFxuICAgICBcXFwiIEdldCBhbiBvYmplY3Qgd2l0aCBkZXRhaWxzIG9mIEFDQ09VTlQuIFxcXFxcXG4gICAgIFxcXFwgRmFpbHMgaWYgYWNjb3VudCBkb2VzIG5vdCBleGlzdC5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIHByZWNpc2lvbjppbnRlZ2VyXFxuICAgICAoKVxcbiAgICAgXFxcIlJldHVybiB0aGUgbWF4aW11bSBhbGxvd2VkIGRlY2ltYWwgcHJlY2lzaW9uLlxcXCJcXG4gICAgIClcXG5cXG4gICAoZGVmdW4gZW5mb3JjZS11bml0OmJvb2xcXG4gICAgICggYW1vdW50OmRlY2ltYWwgKVxcbiAgICAgXFxcIiBFbmZvcmNlIG1pbmltdW0gcHJlY2lzaW9uIGFsbG93ZWQgZm9yIHRyYW5zYWN0aW9ucy5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIGNyZWF0ZS1hY2NvdW50OnN0cmluZ1xcbiAgICAgKCBhY2NvdW50OnN0cmluZ1xcbiAgICAgICBndWFyZDpndWFyZFxcbiAgICAgKVxcbiAgICAgXFxcIiBDcmVhdGUgQUNDT1VOVCB3aXRoIDAuMCBiYWxhbmNlLCB3aXRoIEdVQVJEIGNvbnRyb2xsaW5nIGFjY2Vzcy5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIHJvdGF0ZTpzdHJpbmdcXG4gICAgICggYWNjb3VudDpzdHJpbmdcXG4gICAgICAgbmV3LWd1YXJkOmd1YXJkXFxuICAgICApXFxuICAgICBcXFwiIFJvdGF0ZSBndWFyZCBmb3IgQUNDT1VOVC4gVHJhbnNhY3Rpb24gaXMgdmFsaWRhdGVkIGFnYWluc3QgXFxcXFxcbiAgICAgXFxcXCBleGlzdGluZyBndWFyZCBiZWZvcmUgaW5zdGFsbGluZyBuZXcgZ3VhcmQuIFxcXCJcXG4gICAgIClcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJmdW5naWJsZS1hc3NldC12MlwifSJ9" - , - "eyJoYXNoIjoibVZzMjNxNnJyUjZrWDFGX0ItamNCX05hLXdZdmR3dnRwa1cwQVNaZExjRSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihtb2R1bGUgY29pbiBHT1ZFUk5BTkNFXFxuXFxuICBAZG9jIFxcXCInY29pbicgcmVwcmVzZW50cyB0aGUgS2FkZW5hIENvaW4gQ29udHJhY3QuIFRoaXMgY29udHJhY3QgcHJvdmlkZXMgYm90aCB0aGUgXFxcXFxcbiAgXFxcXGJ1eS9yZWRlZW0gZ2FzIHN1cHBvcnQgaW4gdGhlIGZvcm0gb2YgJ2Z1bmQtdHgnLCBhcyB3ZWxsIGFzIHRyYW5zZmVyLCAgICAgICBcXFxcXFxuICBcXFxcY3JlZGl0LCBkZWJpdCwgY29pbmJhc2UsIGFjY291bnQgY3JlYXRpb24gYW5kIHF1ZXJ5LCBhcyB3ZWxsIGFzIFNQViBidXJuICAgIFxcXFxcXG4gIFxcXFxjcmVhdGUuIFRvIGFjY2VzcyB0aGUgY29pbiBjb250cmFjdCwgeW91IG1heSB1c2UgaXRzIGZ1bGx5LXF1YWxpZmllZCBuYW1lLCAgXFxcXFxcbiAgXFxcXG9yIGlzc3VlIHRoZSAnKHVzZSBjb2luKScgY29tbWFuZCBpbiB0aGUgYm9keSBvZiBhIG1vZHVsZSBkZWNsYXJhdGlvbi5cXFwiXFxuXFxuICBAbW9kZWxcXG4gICAgWyAoZGVmcHJvcGVydHkgY29uc2VydmVzLW1hc3NcXG4gICAgICAgICg9IChjb2x1bW4tZGVsdGEgY29pbi10YWJsZSAnYmFsYW5jZSkgMC4wKSlcXG5cXG4gICAgICAoZGVmcHJvcGVydHkgdmFsaWQtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgICAgICAoYW5kXFxuICAgICAgICAgICg-PSAobGVuZ3RoIGFjY291bnQpIDMpXFxuICAgICAgICAgICg8PSAobGVuZ3RoIGFjY291bnQpIDI1NikpKVxcbiAgICBdXFxuXFxuICAoaW1wbGVtZW50cyBmdW5naWJsZS12MilcXG5cXG4gIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cXG4gIDsgU2NoZW1hcyBhbmQgVGFibGVzXFxuXFxuICAoZGVmc2NoZW1hIGNvaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlRoZSBjb2luIGNvbnRyYWN0IHRva2VuIHNjaGVtYVxcXCJcXG4gICAgQG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBndWFyZDpndWFyZClcXG5cXG4gIChkZWZ0YWJsZSBjb2luLXRhYmxlOntjb2luLXNjaGVtYX0pXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENhcGFiaWxpdGllc1xcblxcbiAgKGRlZmNhcCBHT1ZFUk5BTkNFICgpXFxuICAgIChlbmZvcmNlIGZhbHNlIFxcXCJFbmZvcmNlIG5vbi11cGdyYWRlYWJpbGl0eVxcXCIpKVxcblxcbiAgKGRlZmNhcCBHQVMgKClcXG4gICAgXFxcIk1hZ2ljIGNhcGFiaWxpdHkgdG8gcHJvdGVjdCBnYXMgYnV5IGFuZCByZWRlZW1cXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIENPSU5CQVNFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IHRvIHByb3RlY3QgbWluZXIgcmV3YXJkXFxcIlxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBHRU5FU0lTICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGNvbnN0cmFpbmluZyBnZW5lc2lzIHRyYW5zYWN0aW9uc1xcXCJcXG4gICAgdHJ1ZSlcXG5cXG4gIChkZWZjYXAgUkVNRURJQVRFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnNcXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIERFQklUIChzZW5kZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgZGViaXRpbmcgb3BlcmF0aW9uc1xcXCJcXG4gICAgKGVuZm9yY2UtZ3VhcmQgKGF0ICdndWFyZCAocmVhZCBjb2luLXRhYmxlIHNlbmRlcikpKVxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIFxcXCJcXFwiKSBcXFwidmFsaWQgc2VuZGVyXFxcIikpXFxuXFxuICAoZGVmY2FwIENSRURJVCAocmVjZWl2ZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgY3JlZGl0aW5nIG9wZXJhdGlvbnNcXFwiXFxuICAgIChlbmZvcmNlICghPSByZWNlaXZlciBcXFwiXFxcIikgXFxcInZhbGlkIHJlY2VpdmVyXFxcIikpXFxuXFxuICAoZGVmY2FwIFJPVEFURSAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkF1dG9ub21vdXNseSBtYW5hZ2VkIGNhcGFiaWxpdHkgZm9yIGd1YXJkIHJvdGF0aW9uXFxcIlxcbiAgICBAbWFuYWdlZFxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBUUkFOU0ZFUjpib29sXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsXFxuICAgIClcXG4gICAgQG1hbmFnZWQgYW1vdW50IFRSQU5TRkVSLW1nclxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIHJlY2VpdmVyKSBcXFwic2FtZSBzZW5kZXIgYW5kIHJlY2VpdmVyXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApIFxcXCJQb3NpdGl2ZSBhbW91bnRcXFwiKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChDUkVESVQgcmVjZWl2ZXIpKVxcbiAgKVxcblxcbiAgKGRlZnVuIFRSQU5TRkVSLW1ncjpkZWNpbWFsXFxuICAgICggbWFuYWdlZDpkZWNpbWFsXFxuICAgICAgcmVxdWVzdGVkOmRlY2ltYWxcXG4gICAgKVxcblxcbiAgICAobGV0ICgobmV3YmFsICgtIG1hbmFnZWQgcmVxdWVzdGVkKSkpXFxuICAgICAgKGVuZm9yY2UgKD49IG5ld2JhbCAwLjApXFxuICAgICAgICAoZm9ybWF0IFxcXCJUUkFOU0ZFUiBleGNlZWRlZCBmb3IgYmFsYW5jZSB7fVxcXCIgW21hbmFnZWRdKSlcXG4gICAgICBuZXdiYWwpXFxuICApXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvbnN0YW50c1xcblxcbiAgKGRlZmNvbnN0IENPSU5fQ0hBUlNFVCBDSEFSU0VUX0xBVElOMVxcbiAgICBcXFwiVGhlIGRlZmF1bHQgY29pbiBjb250cmFjdCBjaGFyYWN0ZXIgc2V0XFxcIilcXG5cXG4gIChkZWZjb25zdCBNSU5JTVVNX1BSRUNJU0lPTiAxMlxcbiAgICBcXFwiTWluaW11bSBhbGxvd2VkIHByZWNpc2lvbiBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiKVxcblxcbiAgKGRlZmNvbnN0IE1JTklNVU1fQUNDT1VOVF9MRU5HVEggM1xcbiAgICBcXFwiTWluaW11bSBhY2NvdW50IGxlbmd0aCBhZG1pc3NpYmxlIGZvciBjb2luIGFjY291bnRzXFxcIilcXG5cXG4gIChkZWZjb25zdCBNQVhJTVVNX0FDQ09VTlRfTEVOR1RIIDI1NlxcbiAgICBcXFwiTWF4aW11bSBhY2NvdW50IG5hbWUgbGVuZ3RoIGFkbWlzc2libGUgZm9yIGNvaW4gYWNjb3VudHNcXFwiKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBVdGlsaXRpZXNcXG5cXG4gIChkZWZ1biBlbmZvcmNlLXVuaXQ6Ym9vbCAoYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgbWluaW11bSBwcmVjaXNpb24gYWxsb3dlZCBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiXFxuXFxuICAgIChlbmZvcmNlXFxuICAgICAgKD0gKGZsb29yIGFtb3VudCBNSU5JTVVNX1BSRUNJU0lPTilcXG4gICAgICAgICBhbW91bnQpXFxuICAgICAgKGZvcm1hdCBcXFwiQW1vdW50IHZpb2xhdGVzIG1pbmltdW0gcHJlY2lzaW9uOiB7fVxcXCIgW2Ftb3VudF0pKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdmFsaWRhdGUtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgdGhhdCBhbiBhY2NvdW50IG5hbWUgY29uZm9ybXMgdG8gdGhlIGNvaW4gY29udHJhY3QgXFxcXFxcbiAgICAgICAgIFxcXFxtaW5pbXVtIGFuZCBtYXhpbXVtIGxlbmd0aCByZXF1aXJlbWVudHMsIGFzIHdlbGwgYXMgdGhlICAgIFxcXFxcXG4gICAgICAgICBcXFxcbGF0aW4tMSBjaGFyYWN0ZXIgc2V0LlxcXCJcXG5cXG4gICAgKGVuZm9yY2VcXG4gICAgICAoaXMtY2hhcnNldCBDT0lOX0NIQVJTRVQgYWNjb3VudClcXG4gICAgICAoZm9ybWF0XFxuICAgICAgICBcXFwiQWNjb3VudCBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBjb2luIGNvbnRyYWN0IGNoYXJzZXQ6IHt9XFxcIlxcbiAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgKGxldCAoKGFjY291bnQtbGVuZ3RoIChsZW5ndGggYWNjb3VudCkpKVxcblxcbiAgICAgIChlbmZvcmNlXFxuICAgICAgICAoPj0gYWNjb3VudC1sZW5ndGggTUlOSU1VTV9BQ0NPVU5UX0xFTkdUSClcXG4gICAgICAgIChmb3JtYXRcXG4gICAgICAgICAgXFxcIkFjY291bnQgbmFtZSBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBtaW4gbGVuZ3RoIHJlcXVpcmVtZW50OiB7fVxcXCJcXG4gICAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgICAoZW5mb3JjZVxcbiAgICAgICAgKDw9IGFjY291bnQtbGVuZ3RoIE1BWElNVU1fQUNDT1VOVF9MRU5HVEgpXFxuICAgICAgICAoZm9ybWF0XFxuICAgICAgICAgIFxcXCJBY2NvdW50IG5hbWUgZG9lcyBub3QgY29uZm9ybSB0byB0aGUgbWF4IGxlbmd0aCByZXF1aXJlbWVudDoge31cXFwiXFxuICAgICAgICAgIFthY2NvdW50XSkpXFxuICAgICAgKVxcbiAgKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBDb2luIENvbnRyYWN0XFxuXFxuICAoZGVmdW4gZ2FzLW9ubHkgKClcXG4gICAgXFxcIlByZWRpY2F0ZSBmb3IgZ2FzLW9ubHkgdXNlciBndWFyZHMuXFxcIlxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKSlcXG5cXG4gIChkZWZ1biBnYXMtZ3VhcmQgKGd1YXJkOmd1YXJkKVxcbiAgICBcXFwiUHJlZGljYXRlIGZvciBnYXMgKyBzaW5nbGUga2V5IHVzZXIgZ3VhcmRzXFxcIlxcbiAgICAoZW5mb3JjZS1vbmVcXG4gICAgICBcXFwiRW5mb3JjZSBlaXRoZXIgdGhlIHByZXNlbmNlIG9mIGEgR0FTIGNhcCBvciBrZXlzZXRcXFwiXFxuICAgICAgWyAoZ2FzLW9ubHkpXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG4gICAgICBdKSlcXG5cXG4gIChkZWZ1biBidXktZ2FzOnN0cmluZyAoc2VuZGVyOnN0cmluZyB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCJUaGlzIGZ1bmN0aW9uIGRlc2NyaWJlcyB0aGUgbWFpbiAnZ2FzIGJ1eScgb3BlcmF0aW9uLiBBdCB0aGlzIHBvaW50IFxcXFxcXG4gICAgXFxcXE1JTkVSIGhhcyBiZWVuIGNob3NlbiBmcm9tIHRoZSBwb29sLCBhbmQgd2lsbCBiZSB2YWxpZGF0ZWQuIFRoZSBTRU5ERVIgICBcXFxcXFxuICAgIFxcXFxvZiB0aGlzIHRyYW5zYWN0aW9uIGhhcyBzcGVjaWZpZWQgYSBnYXMgbGltaXQgTElNSVQgKG1heGltdW0gZ2FzKSBmb3IgICAgXFxcXFxcbiAgICBcXFxcdGhlIHRyYW5zYWN0aW9uLCBhbmQgdGhlIHByaWNlIGlzIHRoZSBzcG90IHByaWNlIG9mIGdhcyBhdCB0aGF0IHRpbWUuICAgIFxcXFxcXG4gICAgXFxcXFRoZSBnYXMgYnV5IHdpbGwgYmUgZXhlY3V0ZWQgcHJpb3IgdG8gZXhlY3V0aW5nIFNFTkRFUidzIGNvZGUuXFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCB0b3RhbClcXG4gICAgKGVuZm9yY2UgKD4gdG90YWwgMC4wKSBcXFwiZ2FzIHN1cHBseSBtdXN0IGJlIGEgcG9zaXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuICAgICAgKGRlYml0IHNlbmRlciB0b3RhbCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZWRlZW0tZ2FzOnN0cmluZyAobWluZXI6c3RyaW5nIG1pbmVyLWd1YXJkOmd1YXJkIHNlbmRlcjpzdHJpbmcgdG90YWw6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiVGhpcyBmdW5jdGlvbiBkZXNjcmliZXMgdGhlIG1haW4gJ3JlZGVlbSBnYXMnIG9wZXJhdGlvbi4gQXQgdGhpcyAgICBcXFxcXFxuICAgIFxcXFxwb2ludCwgdGhlIFNFTkRFUidzIHRyYW5zYWN0aW9uIGhhcyBiZWVuIGV4ZWN1dGVkLCBhbmQgdGhlIGdhcyB0aGF0ICAgICAgXFxcXFxcbiAgICBcXFxcd2FzIGNoYXJnZWQgaGFzIGJlZW4gY2FsY3VsYXRlZC4gTUlORVIgd2lsbCBiZSBjcmVkaXRlZCB0aGUgZ2FzIGNvc3QsICAgIFxcXFxcXG4gICAgXFxcXGFuZCBTRU5ERVIgd2lsbCByZWNlaXZlIHRoZSByZW1haW5kZXIgdXAgdG8gdGhlIGxpbWl0XFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBtaW5lcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG4gICAgKHZhbGlkYXRlLWFjY291bnQgbWluZXIpXFxuICAgIChlbmZvcmNlLXVuaXQgdG90YWwpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKEdBUykpXFxuICAgIChsZXQqXFxuICAgICAgKChmZWUgKHJlYWQtZGVjaW1hbCBcXFwiZmVlXFxcIikpXFxuICAgICAgIChyZWZ1bmQgKC0gdG90YWwgZmVlKSkpXFxuXFxuICAgICAgKGVuZm9yY2UtdW5pdCBmZWUpXFxuICAgICAgKGVuZm9yY2UgKD49IGZlZSAwLjApXFxuICAgICAgICBcXFwiZmVlIG11c3QgYmUgYSBub24tbmVnYXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAgIChlbmZvcmNlICg-PSByZWZ1bmQgMC4wKVxcbiAgICAgICAgXFxcInJlZnVuZCBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIHF1YW50aXR5XFxcIilcXG5cXG4gICAgICAgIDsgZGlyZWN0bHkgdXBkYXRlIGluc3RlYWQgb2YgY3JlZGl0XFxuICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHNlbmRlcilcXG4gICAgICAgIChpZiAoPiByZWZ1bmQgMC4wKVxcbiAgICAgICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgc2VuZGVyXFxuICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOj0gYmFsYW5jZSB9XFxuICAgICAgICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIHNlbmRlclxcbiAgICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCI6ICgrIGJhbGFuY2UgcmVmdW5kKSB9KSlcXG5cXG4gICAgICAgICAgXFxcIm5vb3BcXFwiKSlcXG5cXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChDUkVESVQgbWluZXIpXFxuICAgICAgICAoaWYgKD4gZmVlIDAuMClcXG4gICAgICAgICAgKGNyZWRpdCBtaW5lciBtaW5lci1ndWFyZCBmZWUpXFxuICAgICAgICAgIFxcXCJub29wXFxcIikpXFxuICAgICAgKVxcblxcbiAgICApXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFjY291bnQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZClcXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKSBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChpbnNlcnQgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgICA6IGd1YXJkXFxuICAgICAgfSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGdldC1iYWxhbmNlOmRlY2ltYWwgKGFjY291bnQ6c3RyaW5nKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcbiAgICAgIGJhbGFuY2VcXG4gICAgICApXFxuICAgIClcXG5cXG4gIChkZWZ1biBkZXRhaWxzOm9iamVjdHtmdW5naWJsZS12Mi5hY2NvdW50LWRldGFpbHN9XFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIiA6PSBnIH1cXG4gICAgICB7IFxcXCJhY2NvdW50XFxcIiA6IGFjY291bnRcXG4gICAgICAsIFxcXCJiYWxhbmNlXFxcIiA6IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIjogZyB9KVxcbiAgICApXFxuXFxuICAoZGVmdW4gcm90YXRlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgbmV3LWd1YXJkOmd1YXJkKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChST1RBVEUgYWNjb3VudClcXG4gICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IG9sZC1ndWFyZCB9XFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBvbGQtZ3VhcmQpXFxuXFxuICAgICAgICAodXBkYXRlIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgICB7IFxcXCJndWFyZFxcXCIgOiBuZXctZ3VhcmQgfVxcbiAgICAgICAgICApKSlcXG4gICAgKVxcblxcblxcbiAgKGRlZnVuIHByZWNpc2lvbjppbnRlZ2VyXFxuICAgICgpXFxuICAgIE1JTklNVU1fUFJFQ0lTSU9OKVxcblxcbiAgKGRlZnVuIHRyYW5zZmVyOnN0cmluZyAoc2VuZGVyOnN0cmluZyByZWNlaXZlcjpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcylcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgcmVjZWl2ZXIpKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgICh3aXRoLXJlYWQgY29pbi10YWJsZSByZWNlaXZlclxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IGcgfVxcblxcbiAgICAgICAgKGNyZWRpdCByZWNlaXZlciBnIGFtb3VudCkpXFxuICAgICAgKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdHJhbnNmZXItY3JlYXRlOnN0cmluZ1xcbiAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5IGNvbnNlcnZlcy1tYXNzKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgIChjcmVkaXQgcmVjZWl2ZXIgcmVjZWl2ZXItZ3VhcmQgYW1vdW50KSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGNvaW5iYXNlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYWNjb3VudC1ndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiSW50ZXJuYWwgZnVuY3Rpb24gZm9yIHRoZSBpbml0aWFsIGNyZWF0aW9uIG9mIGNvaW5zLiAgVGhpcyBmdW5jdGlvbiBcXFxcXFxuICAgIFxcXFxjYW5ub3QgYmUgdXNlZCBvdXRzaWRlIG9mIHRoZSBjb2luIGNvbnRyYWN0LlxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKD4gYW1vdW50IDAuMCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChDT0lOQkFTRSkpXFxuICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgIChjcmVkaXQgYWNjb3VudCBhY2NvdW50LWd1YXJkIGFtb3VudCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZW1lZGlhdGU6c3RyaW5nIChhY2NvdW50OnN0cmluZyBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQWxsb3dzIGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnMuIFRoaXMgZnVuY3Rpb24gXFxcXFxcbiAgICAgICAgIFxcXFxpcyBwcm90ZWN0ZWQgYnkgdGhlIFJFTUVESUFURSBjYXBhYmlsaXR5XFxcIlxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG5cXG4gICAgKGVuZm9yY2UgKD4gYW1vdW50IDAuMClcXG4gICAgICBcXFwiUmVtZWRpYXRpb24gYW1vdW50IG11c3QgYmUgcG9zaXRpdmVcXFwiKVxcblxcbiAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgKHJlcXVpcmUtY2FwYWJpbGl0eSAoUkVNRURJQVRFKSlcXG4gICAgKHdpdGgtcmVhZCBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6PSBiYWxhbmNlIH1cXG5cXG4gICAgICAoZW5mb3JjZSAoPD0gYW1vdW50IGJhbGFuY2UpIFxcXCJJbnN1ZmZpY2llbnQgZnVuZHNcXFwiKVxcblxcbiAgICAgICh1cGRhdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgtIGJhbGFuY2UgYW1vdW50KSB9XFxuICAgICAgICApKVxcbiAgICApXFxuXFxuICAoZGVmcGFjdCBmdW5kLXR4IChzZW5kZXI6c3RyaW5nIG1pbmVyOnN0cmluZyBtaW5lci1ndWFyZDpndWFyZCB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCInZnVuZC10eCcgaXMgYSBzcGVjaWFsIHBhY3QgdG8gZnVuZCBhIHRyYW5zYWN0aW9uIGluIHR3byBzdGVwcywgICAgIFxcXFxcXG4gICAgXFxcXHdpdGggdGhlIGFjdHVhbCB0cmFuc2FjdGlvbiB0cmFuc3BpcmluZyBpbiB0aGUgbWlkZGxlOiAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXFxcXFxcbiAgICBcXFxcICAxKSBBIGJ1eWluZyBwaGFzZSwgZGViaXRpbmcgdGhlIHNlbmRlciBmb3IgdG90YWwgZ2FzIGFuZCBmZWUsIHlpZWxkaW5nIFxcXFxcXG4gICAgXFxcXCAgICAgVFhfTUFYX0NIQVJHRS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgIDIpIEEgc2V0dGxlbWVudCBwaGFzZSwgcmVzdW1pbmcgVFhfTUFYX0NIQVJHRSwgYW5kIGFsbG9jYXRpbmcgdG8gdGhlICAgXFxcXFxcbiAgICBcXFxcICAgICBjb2luYmFzZSBhY2NvdW50IGZvciB1c2VkIGdhcyBhbmQgZmVlLCBhbmQgc2VuZGVyIGFjY291bnQgZm9yIGJhbC0gIFxcXFxcXG4gICAgXFxcXCAgICAgYW5jZSAodW51c2VkIGdhcywgaWYgYW55KS5cXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiB0b3RhbCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IG1pbmVyKSlcXG4gICAgICAgICAgICAgOyhwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcykgbm90IHN1cHBvcnRlZCB5ZXRcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXAgKGJ1eS1nYXMgc2VuZGVyIHRvdGFsKSlcXG4gICAgKHN0ZXAgKHJlZGVlbS1nYXMgbWluZXIgbWluZXItZ3VhcmQgc2VuZGVyIHRvdGFsKSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGRlYml0OnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkRlYml0IEFNT1VOVCBmcm9tIEFDQ09VTlQgYmFsYW5jZVxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApXFxuICAgICAgXFxcImRlYml0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKERFQklUIGFjY291bnQpKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcblxcbiAgICAgIChlbmZvcmNlICg8PSBhbW91bnQgYmFsYW5jZSkgXFxcIkluc3VmZmljaWVudCBmdW5kc1xcXCIpXFxuXFxuICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogKC0gYmFsYW5jZSBhbW91bnQpIH1cXG4gICAgICAgICkpXFxuICAgIClcXG5cXG5cXG4gIChkZWZ1biBjcmVkaXQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQ3JlZGl0IEFNT1VOVCB0byBBQ0NPVU5UIGJhbGFuY2VcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKSBcXFwiY3JlZGl0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KSlcXG4gICAgKHdpdGgtZGVmYXVsdC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogMC4wLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmQgfVxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UsIFxcXCJndWFyZFxcXCIgOj0gcmV0ZyB9XFxuICAgICAgOyB3ZSBkb24ndCB3YW50IHRvIG92ZXJ3cml0ZSBhbiBleGlzdGluZyBndWFyZCB3aXRoIHRoZSB1c2VyLXN1cHBsaWVkIG9uZVxcbiAgICAgIChlbmZvcmNlICg9IHJldGcgZ3VhcmQpXFxuICAgICAgICBcXFwiYWNjb3VudCBndWFyZHMgZG8gbm90IG1hdGNoXFxcIilcXG5cXG4gICAgICAod3JpdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgrIGJhbGFuY2UgYW1vdW50KVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiICAgOiByZXRnXFxuICAgICAgICB9KVxcbiAgICAgICkpXFxuXFxuXFxuICAoZGVmc2NoZW1hIGNyb3NzY2hhaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlNjaGVtYSBmb3IgeWllbGRlZCB2YWx1ZSBpbiBjcm9zcy1jaGFpbiB0cmFuc2ZlcnNcXFwiXFxuICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICBhbW91bnQ6ZGVjaW1hbClcXG5cXG4gIChkZWZwYWN0IHRyYW5zZmVyLWNyb3NzY2hhaW46c3RyaW5nXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyLWd1YXJkOmd1YXJkXFxuICAgICAgdGFyZ2V0LWNoYWluOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXBcXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCByZWNlaXZlcilcXG5cXG4gICAgICAgIChlbmZvcmNlICghPSBcXFwiXFxcIiB0YXJnZXQtY2hhaW4pIFxcXCJlbXB0eSB0YXJnZXQtY2hhaW5cXFwiKVxcbiAgICAgICAgKGVuZm9yY2UgKCE9IChhdCAnY2hhaW4taWQgKGNoYWluLWRhdGEpKSB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgIFxcXCJjYW5ub3QgcnVuIGNyb3NzLWNoYWluIHRyYW5zZmVycyB0byB0aGUgc2FtZSBjaGFpblxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgICAgICBcXFwidHJhbnNmZXIgcXVhbnRpdHkgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgICAgIDs7IHN0ZXAgMSAtIGRlYml0IGRlbGV0ZS1hY2NvdW50IG9uIGN1cnJlbnQgY2hhaW5cXG4gICAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcblxcbiAgICAgICAgKGxldFxcbiAgICAgICAgICAoKGNyb3NzY2hhaW4tZGV0YWlsczpvYmplY3R7Y3Jvc3NjaGFpbi1zY2hlbWF9XFxuICAgICAgICAgICAgeyBcXFwicmVjZWl2ZXJcXFwiIDogcmVjZWl2ZXJcXG4gICAgICAgICAgICAsIFxcXCJyZWNlaXZlci1ndWFyZFxcXCIgOiByZWNlaXZlci1ndWFyZFxcbiAgICAgICAgICAgICwgXFxcImFtb3VudFxcXCIgOiBhbW91bnRcXG4gICAgICAgICAgICB9KSlcXG4gICAgICAgICAgKHlpZWxkIGNyb3NzY2hhaW4tZGV0YWlscyB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgICkpKVxcblxcbiAgICAoc3RlcFxcbiAgICAgIChyZXN1bWVcXG4gICAgICAgIHsgXFxcInJlY2VpdmVyXFxcIiA6PSByZWNlaXZlclxcbiAgICAgICAgLCBcXFwicmVjZWl2ZXItZ3VhcmRcXFwiIDo9IHJlY2VpdmVyLWd1YXJkXFxuICAgICAgICAsIFxcXCJhbW91bnRcXFwiIDo9IGFtb3VudFxcbiAgICAgICAgfVxcblxcbiAgICAgICAgOzsgc3RlcCAyIC0gY3JlZGl0IGNyZWF0ZSBhY2NvdW50IG9uIHRhcmdldCBjaGFpblxcbiAgICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHJlY2VpdmVyKVxcbiAgICAgICAgICAoY3JlZGl0IHJlY2VpdmVyIHJlY2VpdmVyLWd1YXJkIGFtb3VudCkpXFxuICAgICAgICApKVxcbiAgICApXFxuXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvaW4gYWxsb2NhdGlvbnNcXG5cXG4gIChkZWZzY2hlbWEgYWxsb2NhdGlvbi1zY2hlbWFcXG4gICAgQGRvYyBcXFwiR2VuZXNpcyBhbGxvY2F0aW9uIHJlZ2lzdHJ5XFxcIlxcbiAgICA7QG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBkYXRlOnRpbWVcXG4gICAgZ3VhcmQ6Z3VhcmRcXG4gICAgcmVkZWVtZWQ6Ym9vbClcXG5cXG4gIChkZWZ0YWJsZSBhbGxvY2F0aW9uLXRhYmxlOnthbGxvY2F0aW9uLXNjaGVtYX0pXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFsbG9jYXRpb24tYWNjb3VudFxcbiAgICAoIGFjY291bnQ6c3RyaW5nXFxuICAgICAgZGF0ZTp0aW1lXFxuICAgICAga2V5c2V0LXJlZjpzdHJpbmdcXG4gICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICApXFxuXFxuICAgIEBkb2MgXFxcIkFkZCBhbiBlbnRyeSB0byB0aGUgY29pbiBhbGxvY2F0aW9uIHRhYmxlLiBUaGlzIGZ1bmN0aW9uIFxcXFxcXG4gICAgICAgICBcXFxcYWxzbyBjcmVhdGVzIGEgY29ycmVzcG9uZGluZyBlbXB0eSBjb2luIGNvbnRyYWN0IGFjY291bnQgXFxcXFxcbiAgICAgICAgIFxcXFxvZiB0aGUgc2FtZSBuYW1lIGFuZCBndWFyZC4gUmVxdWlyZXMgR0VORVNJUyBjYXBhYmlsaXR5LiBcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHRU5FU0lTKSlcXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG4gICAgKGVuZm9yY2UgKD49IGFtb3VudCAwLjApXFxuICAgICAgXFxcImFsbG9jYXRpb24gYW1vdW50IG11c3QgYmUgbm9uLW5lZ2F0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChsZXRcXG4gICAgICAoKGd1YXJkOmd1YXJkIChrZXlzZXQtcmVmLWd1YXJkIGtleXNldC1yZWYpKSlcXG5cXG4gICAgICAoY3JlYXRlLWFjY291bnQgYWNjb3VudCBndWFyZClcXG5cXG4gICAgICAoaW5zZXJ0IGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiBhbW91bnRcXG4gICAgICAgICwgXFxcImRhdGVcXFwiIDogZGF0ZVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmRcXG4gICAgICAgICwgXFxcInJlZGVlbWVkXFxcIiA6IGZhbHNlXFxuICAgICAgICB9KSkpXFxuXFxuICAoZGVmdW4gcmVsZWFzZS1hbGxvY2F0aW9uXFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcblxcbiAgICBAZG9jIFxcXCJSZWxlYXNlIGZ1bmRzIGFzc29jaWF0ZWQgd2l0aCBhbGxvY2F0aW9uIEFDQ09VTlQgaW50byBtYWluIGxlZGdlci4gICBcXFxcXFxuICAgICAgICAgXFxcXEFDQ09VTlQgbXVzdCBhbHJlYWR5IGV4aXN0IGluIG1haW4gbGVkZ2VyLiBBbGxvY2F0aW9uIGlzIGRlYWN0aXZhdGVkIFxcXFxcXG4gICAgICAgICBcXFxcYWZ0ZXIgcmVsZWFzZS5cXFwiXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAod2l0aC1yZWFkIGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2VcXG4gICAgICAsIFxcXCJkYXRlXFxcIiA6PSByZWxlYXNlLXRpbWVcXG4gICAgICAsIFxcXCJyZWRlZW1lZFxcXCIgOj0gcmVkZWVtZWRcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgOj0gZ3VhcmRcXG4gICAgICB9XFxuXFxuICAgICAgKGxldCAoKGN1cnItdGltZTp0aW1lIChhdCAnYmxvY2stdGltZSAoY2hhaW4tZGF0YSkpKSlcXG5cXG4gICAgICAgIChlbmZvcmNlIChub3QgcmVkZWVtZWQpXFxuICAgICAgICAgIFxcXCJhbGxvY2F0aW9uIGZ1bmRzIGhhdmUgYWxyZWFkeSBiZWVuIHJlZGVlbWVkXFxcIilcXG5cXG4gICAgICAgIChlbmZvcmNlXFxuICAgICAgICAgICg-PSBjdXJyLXRpbWUgcmVsZWFzZS10aW1lKVxcbiAgICAgICAgICAoZm9ybWF0IFxcXCJmdW5kcyBsb2NrZWQgdW50aWwge30uIGN1cnJlbnQgdGltZToge31cXFwiIFtyZWxlYXNlLXRpbWUgY3Vyci10aW1lXSkpXFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG5cXG4gICAgICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgICAgICAoY3JlZGl0IGFjY291bnQgZ3VhcmQgYmFsYW5jZSlcXG5cXG4gICAgICAgICAgKHVwZGF0ZSBhbGxvY2F0aW9uLXRhYmxlIGFjY291bnRcXG4gICAgICAgICAgICB7IFxcXCJyZWRlZW1lZFxcXCIgOiB0cnVlXFxuICAgICAgICAgICAgLCBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAgICAgICB9KVxcblxcbiAgICAgICAgICBcXFwiQWxsb2NhdGlvbiBzdWNjZXNzZnVsbHkgcmVsZWFzZWQgdG8gbWFpbiBsZWRnZXJcXFwiKVxcbiAgICApKSlcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJjb2luLWNvbnRyYWN0LXYyXCJ9In0" - , - "eyJoYXNoIjoiaFYyZ21vdERCV0U5ZnlZS29JRW4zZm5YRlhBWjBhWHFTVmtlYWJma0ptRSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihjb2luLnJlbWVkaWF0ZSBcXFwic2VuZGVyMDBcXFwiIDEzMzcuNylcIn19LFwic2lnbmVyc1wiOltdLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjoxNzI4MDAsXCJnYXNMaW1pdFwiOjAsXCJjaGFpbklkXCI6XCJcIixcImdhc1ByaWNlXCI6MCxcInNlbmRlclwiOlwiXCJ9LFwibm9uY2VcIjpcInRlc3RuZXQtb3RoZXItcmVtZWRpYXRpb25zXCJ9In0" - ] From a099c52a626525a5267447503ae19634cc4e2444 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Mon, 6 Jul 2020 22:08:10 -0400 Subject: [PATCH 32/48] rosetta tests done, TODO: fix the tests broken by using actual remediations --- test/Chainweb/Test/Rosetta/RestAPI.hs | 220 ++++++++++++++------------ test/Chainweb/Test/Utils.hs | 4 + 2 files changed, 123 insertions(+), 101 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index bbe5edcbfe..724e2cc850 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE BangPatterns #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE ScopedTypeVariables #-} @@ -74,7 +75,7 @@ cids = chainIds v ^.. folded . to chainIdInt . to (sshow @Int) nonceRef :: IORef Natural nonceRef = unsafePerformIO $ newIORef 0 -type RosettaTest = IO (Time Micros) -> IO ClientEnv -> TestTree +type RosettaTest = IO (Time Micros) -> IO ClientEnv -> ScheduledTest -- -------------------------------------------------------------------------- -- -- Test Tree @@ -84,7 +85,8 @@ tests rdb = testGroupSch "Chainweb.Test.Rosetta.RestAPI" go where go = return $ withNodes v "rosettaRemoteTests-" rdb nodes $ \envIo -> - withTime $ \tio -> testGroup "Rosetta API tests" (tgroup tio envIo) + withTime $ \tio -> testGroup "Rosetta Api tests" $ + schedule Sequential (tgroup tio envIo) -- Not supported: -- @@ -106,18 +108,19 @@ tests rdb = testGroupSch "Chainweb.Test.Rosetta.RestAPI" go -- | Rosetta account balance endpoint tests -- accountBalanceTests :: RosettaTest -accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step -> do - step "check initial balance" - cenv <- envIo - resp0 <- accountBalance cenv req - checkBalance resp0 100000000.000 +accountBalanceTests tio envIo = + testCaseSchSteps "Account Balance Tests" $ \step -> do + step "check initial balance" + cenv <- envIo + resp0 <- accountBalance cenv req + checkBalance resp0 100000000.000 - step "send 1.0 tokens to sender00 from sender01" - transferOneAsync_ tio cenv (void . return) + step "send 1.0 tokens to sender00 from sender01" + void $! transferOneAsync_ tio cenv (void . return) - step "check post-transfer balance" - resp1 <- accountBalance cenv req - checkBalance resp1 99999997.8906 + step "check post-transfer balance" + resp1 <- accountBalance cenv req + checkBalance resp1 99999998.9453 where req = AccountBalanceReq nid aid Nothing @@ -132,8 +135,8 @@ accountBalanceTests tio envIo = testCaseSteps "Account Balance Lookup" $ \step - -- | Rosetta block transaction endpoint tests -- blockTransactionTests :: RosettaTest -blockTransactionTests tio envIo = after AllSucceed "Account Balance" $ - testCaseSteps "Block Transaction Tests" $ \step -> do +blockTransactionTests tio envIo = + testCaseSchSteps "Block Transaction Tests" $ \step -> do cenv <- envIo rkmv <- newEmptyMVar @RequestKeys @@ -149,20 +152,21 @@ blockTransactionTests tio envIo = after AllSucceed "Account Balance" $ [a,b,c,d,e] -> return (a,b,c,d,e) _ -> assertFailure "every transfer should result in 5 transactions" + step "validate initial gas buy at index 0" - validateOp 0 "99999996890600000000" "FundTx" "sender00" fundtx + validateOp 0 "FundTx" "sender00" fundtx step "validate sender01 credit at index 1" - validateOp 1 "110000003000000000000" "TransferOrCreateAcct" "sender01" cred + validateOp 1 "TransferOrCreateAcct" "sender01" cred step "validate sender00 debit at index 2" - validateOp 2 "99999995890600000000" "TransferOrCreateAcct" "sender00" deb + validateOp 2 "TransferOrCreateAcct" "sender00" deb step "validate sender00 gas redemption at index 3" - validateOp 3 "99999996835900000000" "GasPayment" "sender00" redeem + validateOp 3 "GasPayment" "sender00" redeem step "validate miner gas reward at index 4" - validateOp 4 "7077669000000" "GasPayment" "NoMiner" reward + validateOp 4 "GasPayment" "NoMiner" reward where mkTxReq rkmv prs = do @@ -180,30 +184,27 @@ blockTransactionTests tio envIo = after AllSucceed "Account Balance" $ -- | Rosetta block endpoint tests -- blockTests :: RosettaTest -blockTests tio envIo = after AllSucceed "Block Transaction Tests" $ - testCaseSteps "Block Tests" $ \step -> do - cenv <- envIo - rkmv <- newEmptyMVar @RequestKeys +blockTests tio envIo = testCaseSchSteps "Block Tests" $ \step -> do + cenv <- envIo + rkmv <- newEmptyMVar @RequestKeys - step "fetch genesis block" - resp0 <- block cenv (req 0) - (_block_blockId $ _blockResp_block resp0) @?= genesisId + step "fetch genesis block" + resp0 <- block cenv (req 0) + (_block_blockId $ _blockResp_block resp0) @?= genesisId - step "send transaction" - prs <- transferOneAsync tio cenv (putMVar rkmv) - rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv - cmdMeta <- extractMetadata rk prs - bh <- cmdMeta ^?! mix "blockHeight" - - step "check tx at block height matches sent tx" - resp1 <- block cenv (req bh) - validateTransferResp bh resp1 + step "send transaction" + !prs <- transferOneAsync tio cenv (putMVar rkmv) + rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv + cmdMeta <- extractMetadata rk prs + bh <- cmdMeta ^?! mix "blockHeight" - step "validate remediations at block height 1" - remResp <- block cenv (req 1) + step "check tx at block height matches sent tx" + resp1 <- block cenv (req bh) + validateTransferResp bh resp1 - print remResp - return () + step "validate remediations at block height 1" + remResp <- block cenv (req 1) + validateRemediations remResp where req h = BlockReq nid $ PartialBlockId (Just h) Nothing @@ -221,21 +222,40 @@ blockTests tio envIo = after AllSucceed "Block Transaction Tests" $ [a,b',c,d,e,f] -> return (a,b',c,d,e,f) _ -> assertFailure "total tx # should be 6: coinbase + 5 for every tx" _ -> assertFailure "every block should result in at least 2 transactions: coinbase + txs" + -- coinbase is considered a separate tx list + validateOp 0 "CoinbaseReward" "NoMiner" cbase - validateOp 0 "4609046000000" "CoinbaseReward" "NoMiner" cbase - validateOp 0 "99999999000000000000" "FundTx" "sender00" fundtx - validateOp 1 "110000001000000000000" "TransferOrCreateAcct" "sender01" cred - validateOp 2 "99999998000000000000" "TransferOrCreateAcct" "sender00" deb - validateOp 3 "99999998945300000000" "GasPayment" "sender00" redeem - validateOp 4 "4663746000000" "GasPayment" "NoMiner" reward + -- transfers form their own tx list + validateOp 0 "FundTx" "sender00" fundtx + validateOp 1 "TransferOrCreateAcct" "sender01" cred + validateOp 2 "TransferOrCreateAcct" "sender00" deb + validateOp 3 "GasPayment" "sender00" redeem + validateOp 4 "GasPayment" "NoMiner" reward validateBlock $ _blockResp_block resp + validateRemediations resp = do + _blockResp_otherTransactions resp @?= Nothing + + let b = _blockResp_block resp + + (cbase,rem1,rem2) <- + case _block_transactions b of + [x,y] -> case _transaction_operations x <> _transaction_operations y of + [a,b',c] -> return (a,b',c) + _ -> assertFailure "total tx # should be 3: coinbase + remediations" + _ -> assertFailure "remediation block should have 3 txs" + + validateOp 0 "CoinbaseReward" "NoMiner" cbase + + validateOp 0 "TransferOrCreateAcct" "sender09" rem1 + validateOp 1 "TransferOrCreateAcct" "sender07" rem2 -- | Rosetta construction submit endpoint tests (i.e. tx submission directly to mempool) -- constructionSubmitTests :: RosettaTest -constructionSubmitTests tio envIo = testCaseSteps "Construction Submit Tests" $ \step -> do +constructionSubmitTests tio envIo = + testCaseSchSteps "Construction Submit Tests" $ \step -> do cenv <- envIo step "build one-off construction submit request" @@ -260,68 +280,68 @@ constructionSubmitTests tio envIo = testCaseSteps "Construction Submit Tests" $ -- | Rosetta mempool endpoint tests -- mempoolTests :: RosettaTest -mempoolTests tio envIo = after AllSucceed "Construction Submit Tests" $ - testCaseSteps "Mempool Tests" $ \step -> do - cenv <- envIo - rkmv <- newEmptyMVar @RequestKeys +mempoolTests tio envIo = testCaseSchSteps "Mempool Tests" $ \step -> do + cenv <- envIo + rkmv <- newEmptyMVar @RequestKeys - step "execute transfer and wait on mempool data" - void $! async $ transferOneAsync_ tio cenv (putMVar rkmv) - rk NEL.:| [] <- _rkRequestKeys <$> takeMVar rkmv + step "execute transfer and wait on mempool data" + void $! async $ transferOneAsync_ tio cenv (putMVar rkmv) + rk NEL.:| [] <- _rkRequestKeys <$> takeMVar rkmv - let tid = rkToTransactionId rk - let test (MempoolResp ts) = return $ elem tid ts + let tid = rkToTransactionId rk + let test (MempoolResp ts) = return $ elem tid ts - step "compare requestkey against mempool responses" - void $! repeatUntil test $ mempool cenv req + step "compare requestkey against mempool responses" + void $! repeatUntil test $ mempool cenv req where req = MempoolReq nid -- | Rosetta network list endpoint tests -- networkListTests :: RosettaTest -networkListTests _ envIo = testCaseSteps "Network List Tests" $ \step -> do - cenv <- envIo +networkListTests _ envIo = + testCaseSchSteps "Network List Tests" $ \step -> do + cenv <- envIo - step "send network list request" - resp <- networkList cenv req + step "send network list request" + resp <- networkList cenv req - for_ (_networkListResp_networkIds resp) $ \n -> do - _networkId_blockchain n @=? "kadena" - _networkId_network n @=? "fastTimedCPM-peterson" - assertBool "chain id of subnetwork is valid" - $ maybe False (\a -> elem (_subNetworkId_network a) cids) - $ _networkId_subNetworkId n + for_ (_networkListResp_networkIds resp) $ \n -> do + _networkId_blockchain n @=? "kadena" + _networkId_network n @=? "fastTimedCPM-peterson" + assertBool "chain id of subnetwork is valid" + $ maybe False (\a -> elem (_subNetworkId_network a) cids) + $ _networkId_subNetworkId n where req = MetadataReq Nothing -- | Rosetta network options tests -- networkOptionsTests :: RosettaTest -networkOptionsTests _ envIo = testCaseSteps "Network Options Tests" $ \step -> do - cenv <- envIo - - step "send network options request" - resp <- networkOptions cenv req0 +networkOptionsTests _ envIo = + testCaseSchSteps "Network Options Tests" $ \step -> do + cenv <- envIo - let allow = _networkOptionsResp_allow resp - version = _networkOptionsResp_version resp + step "send network options request" + resp <- networkOptions cenv req0 - step "check options responses against allowable data and versions" - version @=? rosettaVersion + let allow = _networkOptionsResp_allow resp + version = _networkOptionsResp_version resp - step "Check that response errors are a subset of valid errors" - (respErrors resp `subset` rosettaFailures) @? - "allowable errors must coincide with failure list" + step "check options responses against allowable data and versions" + version @=? rosettaVersion - step "Check that response statuses are a subset of valid statuses" - (_allow_operationStatuses allow `subset` operationStatuses) @? - "allowed operation statuses coincide" + step "Check that response errors are a subset of valid errors" + (respErrors resp `subset` rosettaFailures) @? + "allowable errors must coincide with failure list" - step "Check that response op types are a subset of op types" - (_allow_operationTypes allow `subset` allowedOperations) @? - "allowed operations coincide" + step "Check that response statuses are a subset of valid statuses" + (_allow_operationStatuses allow `subset` operationStatuses) @? + "allowed operation statuses coincide" + step "Check that response op types are a subset of op types" + (_allow_operationTypes allow `subset` allowedOperations) @? + "allowed operations coincide" where req0 = NetworkReq nid Nothing respErrors = _allow_errors . _networkOptionsResp_allow @@ -330,22 +350,23 @@ networkOptionsTests _ envIo = testCaseSteps "Network Options Tests" $ \step -> d -- | Rosetta network status tests -- networkStatusTests :: RosettaTest -networkStatusTests tio envIo = testCaseSteps "Network Status Tests" $ \step -> do - cenv <- envIo +networkStatusTests tio envIo = + testCaseSchSteps "Network Status Tests" $ \step -> do + cenv <- envIo - step "send network status request" - resp0 <- networkStatus cenv req + step "send network status request" + resp0 <- networkStatus cenv req - step "check status response against genesis" - genesisId @=? _networkStatusResp_genesisBlockId resp0 + step "check status response against genesis" + genesisId @=? _networkStatusResp_genesisBlockId resp0 - step "send in a transaction and update current block" - transferOneAsync_ tio cenv (void . return) - resp1 <- networkStatus cenv req + step "send in a transaction and update current block" + transferOneAsync_ tio cenv (void . return) + resp1 <- networkStatus cenv req - step "check status response genesis and block height" - genesisId @=? _networkStatusResp_genesisBlockId resp1 - (blockIdOf resp1 > blockIdOf resp0) @? "current block id heights must increment" + step "check status response genesis and block height" + genesisId @=? _networkStatusResp_genesisBlockId resp1 + (blockIdOf resp1 > blockIdOf resp0) @? "current block id heights must increment" where req = NetworkReq nid Nothing @@ -409,8 +430,6 @@ operationStatuses = validateOp :: Word64 -- ^ tx idx - -> Text - -- ^ operation amount -> Text -- ^ operation type -> Text @@ -418,11 +437,10 @@ validateOp -> Operation -- ^ the op -> Assertion -validateOp idx amount opType acct o = do +validateOp idx opType acct o = do _operation_operationId o @?= OperationId idx Nothing _operation_type o @?= opType _operation_status o @?= "Successful" - _operation_amount o @?= Just (Amount amount kda Nothing) _operation_account o @?= Just (AccountId acct Nothing Nothing) -- ------------------------------------------------------------------ -- diff --git a/test/Chainweb/Test/Utils.hs b/test/Chainweb/Test/Utils.hs index b9c34b291b..93dfe42d20 100644 --- a/test/Chainweb/Test/Utils.hs +++ b/test/Chainweb/Test/Utils.hs @@ -92,6 +92,7 @@ module Chainweb.Test.Utils , ScheduledTest(..) , schedule , testCaseSch +, testCaseSchSteps , testGroupSch , testPropertySch @@ -849,6 +850,9 @@ data ScheduledTest = ScheduledTest { _schLabel :: String , _schTest :: TestTree testCaseSch :: String -> Assertion -> ScheduledTest testCaseSch l a = ScheduledTest l $ testCase l a +testCaseSchSteps :: String -> ((String -> IO ()) -> Assertion) -> ScheduledTest +testCaseSchSteps l a = ScheduledTest l $ testCaseSteps l a + testGroupSch :: String -> [TestTree] -> ScheduledTest testGroupSch l ts = ScheduledTest l $ testGroup l ts From 1c7e37168d1cbd6a5b9e6e60230056f3adea0f57 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Mon, 6 Jul 2020 22:26:50 -0400 Subject: [PATCH 33/48] fix pact in proc api test --- test/Chainweb/Test/Pact/PactInProcApi.hs | 33 +++++++++++++++------- test/golden/create-accounts-expected.txt | 2 +- test/golden/create-table-expected.txt | 2 +- test/golden/empty-block-tests-expected.txt | 6 ++-- test/golden/new-block-0-expected.txt | 28 +++++++++--------- test/golden/transfer-accounts-expected.txt | 2 +- 6 files changed, 43 insertions(+), 30 deletions(-) diff --git a/test/Chainweb/Test/Pact/PactInProcApi.hs b/test/Chainweb/Test/Pact/PactInProcApi.hs index ebfbddb557..218e6cca11 100644 --- a/test/Chainweb/Test/Pact/PactInProcApi.hs +++ b/test/Chainweb/Test/Pact/PactInProcApi.hs @@ -145,19 +145,32 @@ getHistory refIO reqIO = testCase "getHistory" $ do (BlockTxHistory hist) <- forSuccess "getHistory" (return mv) -- just check first one here assertEqual "check first entry of history" - (Just [TxLog "coin_coin-table" "sender00" - (object - [ "guard" .= object - [ "pred" .= ("keys-all" :: T.Text) - , "keys" .= - ["368820f80c324bbc7c2b0610688a7da43e39f91d118732671cd9c7500ff43cca" :: T.Text] - ] - , "balance" .= (Number 99999900.0) - ])]) + (Just + [ TxLog "coin_coin-table" "sender09" + ( object + [ "guard" .= object + [ "pred" .= ("keys-all" :: T.Text) + , "keys" .= ["c59d9840b0b66090836546b7eb4a73606257527ec8c2b482300fd229264b07e6" :: T.Text] + ] + , "balance" .= (Number 189998662.1) + ] + ) + , TxLog "coin_coin-table" "sender07" + ( object + [ "guard" .= object + [ "pred" .= ("keys-all" :: T.Text) + , "keys" .= ["4c31dc9ee7f24177f78b6f518012a208326e2af1f37bb0a2405b5056d0cad628" :: T.Text] + ] + , "balance" .= (Number 169998662.3) + ] + ) + ] + ) + (M.lookup 10 hist) -- and transaction txids assertEqual "check txids" - [7,10,12,13,15,16,18,19,21,22,24,25,27,28,30,31,33,34,36,37,39,40,42] + [7,10,11,13,14,16,17,19,20,22,23,25,26,28,29,31,32,34,35,37,38,40,41,43] (M.keys hist) getHistoricalLookupNoTxs diff --git a/test/golden/create-accounts-expected.txt b/test/golden/create-accounts-expected.txt index 4385fec173..96b27fcc48 100644 --- a/test/golden/create-accounts-expected.txt +++ b/test/golden/create-accounts-expected.txt @@ -1,4 +1,4 @@ -- output: s0GHumQ2cht2jXZZYlcqPhNcNtAUsP4zVU_R9MXuq-g +- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs cmd: coinbase - output: G15srpFoJgfoVchKV2ilyjMGtscxfNFlxwV0tvUC6bE cmd: diff --git a/test/golden/create-table-expected.txt b/test/golden/create-table-expected.txt index c4a54a6949..20ad191c5c 100644 --- a/test/golden/create-table-expected.txt +++ b/test/golden/create-table-expected.txt @@ -1,4 +1,4 @@ -- output: s0GHumQ2cht2jXZZYlcqPhNcNtAUsP4zVU_R9MXuq-g +- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs cmd: coinbase - output: ExfKxPyfW_VnvUXfZva1taP6-woqfIYlNcnlFnKv5wQ cmd: diff --git a/test/golden/empty-block-tests-expected.txt b/test/golden/empty-block-tests-expected.txt index c69cd98eb9..68c8037c6b 100644 --- a/test/golden/empty-block-tests-expected.txt +++ b/test/golden/empty-block-tests-expected.txt @@ -3,6 +3,6 @@ results: transactions: [] minerData: eyJhY2NvdW50IjoiTm9NaW5lciIsInByZWRpY2F0ZSI6IjwiLCJwdWJsaWMta2V5cyI6W119 transactionsHash: lL9ztEiU-NwzrlTpBbvhT4M1l5Shsht94OwFyhBaFD0 - outputsHash: GSbZgTYq99iKlwligYOyB5nG4FnBE03Fscp1FQUOL2I - payloadHash: Vclgdw9i9rvv06CENBaSlMylLE92Xp3786S9pX1o2wk - coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoibFdaVWZjX0dKdGxUUy1LeDAtYm00aXRfSWE5bnNGZG5jZ2NwSE0td091OCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 + outputsHash: mY63CaLW5zc6z3pyqAQzHt68b0aGaZOhqfXYXzAXLxc + payloadHash: nqycG99dCoGv7tYDaUzTCPXr5fNUQZyPrspb26ydhHk + coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoidG9fdGsyTzltM2lvblJyU1IwQ1dCY2tScGliS0NQbWpWSnRsS2daZVUxdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 diff --git a/test/golden/new-block-0-expected.txt b/test/golden/new-block-0-expected.txt index c0ced25d2b..5d336d2a67 100644 --- a/test/golden/new-block-0-expected.txt +++ b/test/golden/new-block-0-expected.txt @@ -2,29 +2,29 @@ test-group: new-block results: transactions: - - eyJoYXNoIjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsInNpZ3MiOlt7InNpZyI6ImYzZTc5Mjc4MGRmNTIwZmVkMjg5MDc3MjllMjI1NTA4NTk2MzJhMzNiMTQzMTM0MDlkOTkyZmRmMjJjNTZlZDEwMzdiZTcxNDYyNWRkMTZmYWI5MmVlNjZhZmQ1MjhiNWViZjEwYWNhZjY2ZjRlZGVmMWM2ZjZjY2Q4OTkxMjA0In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihkZWZpbmUta2V5c2V0ICd0ZXN0LWFkbWluIChyZWFkLWtleXNldCBcXFwidGVzdC1hZG1pbi1rZXlzZXRcXFwiKSlcXG5cXG4obmFtZXNwYWNlICdmcmVlKVxcblxcbihtb2R1bGUgdGVzdDEgJ3Rlc3QtYWRtaW5cXG5cXG4gIChkZWZzY2hlbWEgYWNjb3VudFxcbiAgICBiYWxhbmNlOmRlY2ltYWxcXG4gICAgYW1vdW50OmRlY2ltYWxcXG4gICAgZGF0YSlcXG5cXG4gIChkZWZ0YWJsZSBhY2NvdW50czp7YWNjb3VudH0pXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFjY291bnQgKGlkIGluaXQtYmFsKVxcbiAgICAoaW5zZXJ0IGFjY291bnRzIGlkXFxuICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCI6IGluaXQtYmFsLCBcXFwiYW1vdW50XFxcIjogaW5pdC1iYWwsIFxcXCJkYXRhXFxcIjogXFxcIkNyZWF0ZWQgYWNjb3VudFxcXCIgfSkpXFxuXFxuICAoZGVmdW4gdHJhbnNmZXIgKHNyYyBkZXN0IGFtb3VudClcXG4gICAgXFxcInRyYW5zZmVyIEFNT1VOVCBmcm9tIFNSQyB0byBERVNUIGZvciB1bmVuY3J5cHRlZCBhY2NvdW50c1xcXCJcXG4gICAgKGRlYml0IHNyYyBhbW91bnQgeyBcXFwidHJhbnNmZXItdG9cXFwiOiBkZXN0IH0pXFxuICAgIChjcmVkaXQgZGVzdCBhbW91bnQgeyBcXFwidHJhbnNmZXItZnJvbVxcXCI6IHNyYyB9KSlcXG5cXG4gIChkZWZwYWN0IHBheW1lbnQgKHNyYy1lbnRpdHkgc3JjIGRlc3QtZW50aXR5IGRlc3QgYW1vdW50KVxcbiAgICBcXFwiVHdvLXBoYXNlIGNvbmZpZGVudGlhbCBwYXltZW50LCBzZW5kaW5nIG1vbmV5IGZyb20gU1JDIGF0IFNSQy1FTlRJVFkgdG8gREVTVCBhdCBERVNULUVOVElUWS5cXFwiXFxuXFxuICAgIChzdGVwLXdpdGgtcm9sbGJhY2tcXG4gICAgIHNyYy1lbnRpdHlcXG4gICAgIChsZXQgKChyZXN1bHQgKGRlYml0IHNyYyBhbW91bnQgeyBcXFwidHJhbnNmZXItdG9cXFwiOiBkZXN0LCBcXFwibWVzc2FnZVxcXCI6IFxcXCJTdGFydGluZyBwYWN0XFxcIiB9KSkpXFxuICAgICAgICh5aWVsZCB7IFxcXCJyZXN1bHRcXFwiOiByZXN1bHQsIFxcXCJhbW91bnRcXFwiOiBhbW91bnQsIFxcXCJ0eFxcXCI6IChwYWN0LWlkKSB9KSlcXG4gICAgIChjcmVkaXQgc3JjIGFtb3VudCB7IFxcXCJyb2xsYmFja1xcXCI6IChwYWN0LWlkKSB9KSlcXG5cXG4gICAgKHN0ZXBcXG4gICAgIGRlc3QtZW50aXR5XFxuICAgICAocmVzdW1lIHsgXFxcInJlc3VsdFxcXCI6PSByZXN1bHQsIFxcXCJhbW91bnRcXFwiOj0gZGViaXQtYW1vdW50IH1cXG4gICAgICAgKGNyZWRpdCBkZXN0IGRlYml0LWFtb3VudFxcbiAgICAgICAgICAgICAgIHsgXFxcInRyYW5zZmVyLWZyb21cXFwiOiBzcmMsIFxcXCJkZWJpdC1yZXN1bHRcXFwiOiByZXN1bHQsIFxcXCJ0eFxcXCI6IChwYWN0LWlkKSB9KSkpKVxcblxcbiAgKGRlZnVuIGRlYml0IChhY2N0IGFtb3VudCBkYXRhKVxcbiAgICBcXFwiRGViaXQgQUNDVCBmb3IgQU1PVU5ULCBlbmZvcmNpbmcgcG9zaXRpdmUgYW1vdW50IGFuZCBzdWZmaWNpZW50IGZ1bmRzLCBhbm5vdGF0aW5nIHdpdGggREFUQVxcXCJcXG4gICAgKGVuZm9yY2UtcG9zaXRpdmUgYW1vdW50KVxcbiAgICAod2l0aC1yZWFkIGFjY291bnRzIGFjY3QgeyBcXFwiYmFsYW5jZVxcXCI6PSBiYWxhbmNlIH1cXG4gICAgICAoY2hlY2stYmFsYW5jZSBiYWxhbmNlIGFtb3VudClcXG4gICAgICAodXBkYXRlIGFjY291bnRzIGFjY3RcXG4gICAgICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIjogKC0gYmFsYW5jZSBhbW91bnQpLCBcXFwiYW1vdW50XFxcIjogKC0gYW1vdW50KVxcbiAgICAgICAgICAgICwgXFxcImRhdGFcXFwiOiBkYXRhIH0pKSlcXG5cXG4gIChkZWZ1biBjcmVkaXQgKGFjY3QgYW1vdW50IGRhdGEpXFxuICAgIFxcXCJDcmVkaXQgQUNDVCBmb3IgQU1PVU5ULCBlbmZvcmNpbmcgcG9zaXRpdmUgYW1vdW50XFxcIlxcbiAgICAoZW5mb3JjZS1wb3NpdGl2ZSBhbW91bnQpXFxuICAgICh3aXRoLXJlYWQgYWNjb3VudHMgYWNjdCB7IFxcXCJiYWxhbmNlXFxcIjo9IGJhbGFuY2UgfVxcbiAgICAgICh1cGRhdGUgYWNjb3VudHMgYWNjdFxcbiAgICAgICAgICAgIHsgXFxcImJhbGFuY2VcXFwiOiAoKyBiYWxhbmNlIGFtb3VudCksIFxcXCJhbW91bnRcXFwiOiBhbW91bnRcXG4gICAgICAgICAgICAsIFxcXCJkYXRhXFxcIjogZGF0YSB9KSkpXFxuXFxuXFxuICAoZGVmdW4gcmVhZC1hY2NvdW50IChpZClcXG4gICAgXFxcIlJlYWQgZGF0YSBmb3IgYWNjb3VudCBJRFxcXCJcXG4gICAgKCsgeyBcXFwiYWNjb3VudFxcXCI6IGlkIH0gKHJlYWQgYWNjb3VudHMgaWQpKSlcXG5cXG4gIChkZWZ1biBjaGVjay1iYWxhbmNlIChiYWxhbmNlIGFtb3VudClcXG4gICAgKGVuZm9yY2UgKDw9IGFtb3VudCBiYWxhbmNlKSBcXFwiSW5zdWZmaWNpZW50IGZ1bmRzXFxcIikpXFxuXFxuICAoZGVmdW4gZW5mb3JjZS1wb3NpdGl2ZSAoYW1vdW50KVxcbiAgICAoZW5mb3JjZSAoPj0gYW1vdW50IDAuMCkgXFxcImFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIikpXFxuXFxuIChkZWZ1biByZWFkLWFsbCAoKVxcbiAgIChtYXAgKHJlYWQtYWNjb3VudCkgKGtleXMgYWNjb3VudHMpKSlcXG5cXG4gKGRlZnVuIHJlYWQtYWxsLWdsb2JhbCAoKVxcbiAgIChtYXAgKHJlYWQtYWNjb3VudCkgW1xcXCJBY2N0MVxcXCIgXFxcIkFjY3QyXFxcIl0pKVxcblxcbiAoZGVmdW4gY3JlYXRlLWdsb2JhbC1hY2NvdW50cyAoKVxcbiAgIChjcmVhdGUtYWNjb3VudCBcXFwiQWNjdDFcXFwiIDEwMDAwMDAuMClcXG4gICAoY3JlYXRlLWFjY291bnQgXFxcIkFjY3QyXFxcIiAwLjApXFxuICAgKHJlYWQtYWxsKSlcXG5cXG4gKGRlZnBhY3QgY3JlYXRlLXByaXZhdGUtYWNjb3VudHMgKClcXG4gICAoc3RlcCBcXFwiQWxpY2VcXFwiIChjcmVhdGUtYWNjb3VudCBcXFwiQVxcXCIgMTAwMC4wKSlcXG4gICAoc3RlcCBcXFwiQm9iXFxcIiAoY3JlYXRlLWFjY291bnQgXFxcIkJcXFwiIDEwMDAuMCkpXFxuICAgKHN0ZXAgXFxcIkNhcm9sXFxcIiAoY3JlYXRlLWFjY291bnQgXFxcIkNcXFwiIDEwMDAuMCkpXFxuICAgKHN0ZXAgXFxcIkRpbmVzaFxcXCIgKGNyZWF0ZS1hY2NvdW50IFxcXCJEXFxcIiAxMDAwLjApKSlcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjEwXCJ9In0 - - eyJnYXMiOjY0OSwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiTG9hZGVkIG1vZHVsZSBmcmVlLnRlc3QxLCBoYXNoIEI2WkpnZldENW9iUEdtWWNfaVJLaXJETVA2LVVHbTJwVVY3bXRIRC1Sc1EifSwicmVxS2V5IjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsImxvZ3MiOiJMRm51NzRDaE4wZS1IbGI3azlqZlAzcmpmcWh6WjFweUpibXpkX1lOMFdZIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MTF9 + - eyJnYXMiOjY0OSwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiTG9hZGVkIG1vZHVsZSBmcmVlLnRlc3QxLCBoYXNoIEI2WkpnZldENW9iUEdtWWNfaVJLaXJETVA2LVVHbTJwVVY3bXRIRC1Sc1EifSwicmVxS2V5IjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsImxvZ3MiOiJMRm51NzRDaE4wZS1IbGI3azlqZlAzcmpmcWh6WjFweUpibXpkX1lOMFdZIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MTJ9 - - eyJoYXNoIjoidUFaMDFQQ21QWW43UTBrdGRMZ21abEZueVFUU2t3aXRXTmp0ZTNUQ3hOYyIsInNpZ3MiOlt7InNpZyI6IjU1Nzk3Zjk2YjEwYzY5ZjRhMGY2ZTg5ZDI4OGFjMTNlZDE1MDI4NWJkNDJmODNjZTMzNjE2M2IzYTllNmM3MjFiY2FlMGE2MzhjMTgwYTk0MTE2YjlhZDBkM2UwOWFlYmI3OGE2NjVhNTg2MzdhMmExZmE0OGU3NDZiYzU5NDA5In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihjcmVhdGUtdGFibGUgZnJlZS50ZXN0MS5hY2NvdW50cylcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTFcIn0ifQ - - eyJnYXMiOjI2NCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiVGFibGVDcmVhdGVkIn0sInJlcUtleSI6InVBWjAxUENtUFluN1Ewa3RkTGdtWmxGbnlRVFNrd2l0V05qdGUzVEN4TmMiLCJsb2dzIjoianVuYlJrd3hEMVhiUHBvTnNCZlN3NEJGYUEtcW1mempEMmhfOHhQTmczbyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE0fQ + - eyJnYXMiOjI2NCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiVGFibGVDcmVhdGVkIn0sInJlcUtleSI6InVBWjAxUENtUFluN1Ewa3RkTGdtWmxGbnlRVFNrd2l0V05qdGUzVEN4TmMiLCJsb2dzIjoianVuYlJrd3hEMVhiUHBvTnNCZlN3NEJGYUEtcW1mempEMmhfOHhQTmczbyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE1fQ - - eyJoYXNoIjoiWjZxajdIZnBSN0pnZkJFZGhsYU9BSTdjdDd1ZFM2dE5jVUF0RFZMSHNJbyIsInNpZ3MiOlt7InNpZyI6ImM5YzExMGE2MGI4M2JmMmM1OTFiMTMxMWJjOTdjNjJiNzkxZTcwNDYzM2RhY2EyMGNhYmE2MTRhNGQwYThkYmFlODJlNmQxOWQ2NDZlMWJmNGNlMWUyMDZjMTM4MmM4NGExMGI5Y2NkYWY2MzAzOGU1ZWJmMDk3ZmE3YzZjMTAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihmcmVlLnRlc3QxLmNyZWF0ZS1nbG9iYWwtYWNjb3VudHMpXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjEyXCJ9In0 - - eyJnYXMiOjU4MCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjpbeyJhbW91bnQiOjEwMDAwMDAsImRhdGEiOiJDcmVhdGVkIGFjY291bnQiLCJiYWxhbmNlIjoxMDAwMDAwLCJhY2NvdW50IjoiQWNjdDEifSx7ImFtb3VudCI6MCwiZGF0YSI6IkNyZWF0ZWQgYWNjb3VudCIsImJhbGFuY2UiOjAsImFjY291bnQiOiJBY2N0MiJ9XX0sInJlcUtleSI6Ilo2cWo3SGZwUjdKZ2ZCRWRobGFPQUk3Y3Q3dWRTNnROY1VBdERWTEhzSW8iLCJsb2dzIjoia0VIU2ZyQXRLQV9vdi1xZDV4cmpSSTFtX2phenRkSF9JbGVJWG9QNW9wNCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE3fQ + - eyJnYXMiOjU4MCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjpbeyJhbW91bnQiOjEwMDAwMDAsImRhdGEiOiJDcmVhdGVkIGFjY291bnQiLCJiYWxhbmNlIjoxMDAwMDAwLCJhY2NvdW50IjoiQWNjdDEifSx7ImFtb3VudCI6MCwiZGF0YSI6IkNyZWF0ZWQgYWNjb3VudCIsImJhbGFuY2UiOjAsImFjY291bnQiOiJBY2N0MiJ9XX0sInJlcUtleSI6Ilo2cWo3SGZwUjdKZ2ZCRWRobGFPQUk3Y3Q3dWRTNnROY1VBdERWTEhzSW8iLCJsb2dzIjoia0VIU2ZyQXRLQV9vdi1xZDV4cmpSSTFtX2phenRkSF9JbGVJWG9QNW9wNCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE4fQ - - eyJoYXNoIjoicFBrLWxFUE1jRnRDWXdXR2ZaejV2bGdzZ1ZYV3dYbXhmQVJ6bkFCbUVONCIsInNpZ3MiOlt7InNpZyI6IjM3YjI4MmY1YWQ0YWY0Yzk2YmE1NzA5YWEzOTI2NTU1YjU5MDEwYzczZmVmZTUwNzQyMGYyODVjZTI1MmQ5ZjM1YzQ5NjAxYTgwMDYxZGU2NzEzNTcxNzY2MTNmODIyODQxMDU0MjliZTVkOTEzNWMzODAxMzcyN2UyMmI3ZjA2In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihmcmVlLnRlc3QxLnRyYW5zZmVyIFxcXCJBY2N0MVxcXCIgXFxcIkFjY3QyXFxcIiAxLjAwKVwifX0sXCJzaWduZXJzXCI6W3tcInB1YktleVwiOlwiMzY4ODIwZjgwYzMyNGJiYzdjMmIwNjEwNjg4YTdkYTQzZTM5ZjkxZDExODczMjY3MWNkOWM3NTAwZmY0M2NjYVwifV0sXCJtZXRhXCI6e1wiY3JlYXRpb25UaW1lXCI6MCxcInR0bFwiOjg2NDAwLFwiZ2FzTGltaXRcIjoxMDAwMCxcImNoYWluSWRcIjpcIjBcIixcImdhc1ByaWNlXCI6MS4wZS0yLFwic2VuZGVyXCI6XCJzZW5kZXIwMFwifSxcIm5vbmNlXCI6XCIxM1wifSJ9 - - eyJnYXMiOjQwNywicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiV3JpdGUgc3VjY2VlZGVkIn0sInJlcUtleSI6InBQay1sRVBNY0Z0Q1l3V0dmWno1dmxnc2dWWFd3WG14ZkFSem5BQm1FTjQiLCJsb2dzIjoib3hWd2tvU21xM2JZeVh5aHYwT0V3ZTN2c0tGbWlkRTBtTEotQ2FZWVhRayIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjIwfQ + - eyJnYXMiOjQwNywicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiV3JpdGUgc3VjY2VlZGVkIn0sInJlcUtleSI6InBQay1sRVBNY0Z0Q1l3V0dmWno1dmxnc2dWWFd3WG14ZkFSem5BQm1FTjQiLCJsb2dzIjoib3hWd2tvU21xM2JZeVh5aHYwT0V3ZTN2c0tGbWlkRTBtTEotQ2FZWVhRayIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjIxfQ - - eyJoYXNoIjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsInNpZ3MiOlt7InNpZyI6IjZhODRiMWRkNGFkNDE5ZGY3YThhODA4NGYwNWEyZDM5YzExNTBmMjI5ZTM3OTFlM2UwY2E0OTkyZDkwNGNhOGVlMTk4MTljNTE3YTVjNjM5M2E3ZmYyNWI1NjdiNjJjOTYwZTFiYmI4ZTE2YjZiMWU2YmRkNDU1Njk3ODc1MDA5In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAncHJldi1ibG9jay1oYXNoIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTRcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNWMDlUbHhfZURIQWdYZkY1WS1jcG1MMVBTWFFsTERKRWc5MUJKczBieWMifSwicmVxS2V5IjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsImxvZ3MiOiJUVVVlWFJmRFlnQlZTdjFZU0ktU3lfRVdtcHRaWXZqQlNmY1ZMc2ZzcVpVIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MjN9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNWMDlUbHhfZURIQWdYZkY1WS1jcG1MMVBTWFFsTERKRWc5MUJKczBieWMifSwicmVxS2V5IjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsImxvZ3MiOiJUVVVlWFJmRFlnQlZTdjFZU0ktU3lfRVdtcHRaWXZqQlNmY1ZMc2ZzcVpVIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MjR9 - - eyJoYXNoIjoiTzhoWU1TVUhnSkNPRXFoTy0yRFRNRGJhTzBIZmx6VjM0UHRzM0dlUHBJUSIsInNpZ3MiOlt7InNpZyI6ImMxYjQ5OTQwNTQ0MjZmNzE2NWM2NmZjNjY0MzE0N2M1N2QxYTczYzM3NjEwMjU4OGU0M2QyMzA1ZjBhY2FhYTQyMDRkZGRmNGRhMWFiMzk0OTdkY2FiM2FjZWU1NmQ0NmQ3NzJkNDZkNjAyNmU5ZjQ4MGFmMWNiMWIyNWFmYzA3In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnYmxvY2stdGltZSAoY2hhaW4tZGF0YSkpXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjE1XCJ9In0 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJ0aW1lIjoiMTk3MC0wMS0wMVQwMDowMDowMFoifX0sInJlcUtleSI6Ik84aFlNU1VIZ0pDT0VxaE8tMkRUTURiYU8wSGZselYzNFB0czNHZVBwSVEiLCJsb2dzIjoidTdKNDU3dGdzNDJ1dGhjOU1TbWtkaTkxT2tUb2FCNFpGei1QUWtSajJhdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI2fQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJ0aW1lIjoiMTk3MC0wMS0wMVQwMDowMDowMFoifX0sInJlcUtleSI6Ik84aFlNU1VIZ0pDT0VxaE8tMkRUTURiYU8wSGZselYzNFB0czNHZVBwSVEiLCJsb2dzIjoidTdKNDU3dGdzNDJ1dGhjOU1TbWtkaTkxT2tUb2FCNFpGei1QUWtSajJhdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI3fQ - - eyJoYXNoIjoiSGFsbTJLYUV5Qm5weXJqMkxHMmJQcVZDUmZBYk8yWHZzZWlnaURaZElLOCIsInNpZ3MiOlt7InNpZyI6ImI0MDNlZWI3ODI0NzA0OWU0NjEzNGQzYWQ0MWZlMTAwNWMxM2I0NzNhNjUzZGNmNTVlN2ZmMzIzOGU5N2VkYmRmZTMyZmFmODczODViYTc0MmNmMDFmYmFkMDU2ODEwNWVjNDhhMDk1MzIyNWJmMmY0ODJjNjhiMjkyZGNmOTAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnYmxvY2staGVpZ2h0IChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTZcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MX0sInJlcUtleSI6IkhhbG0yS2FFeUJucHlyajJMRzJiUHFWQ1JmQWJPMlh2c2VpZ2lEWmRJSzgiLCJsb2dzIjoiaEtSOEZUYkhSVnhxV092TTZWXzZ1dUdMSVA3T2loV25RR3dFSnV0REF0cyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI5fQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MX0sInJlcUtleSI6IkhhbG0yS2FFeUJucHlyajJMRzJiUHFWQ1JmQWJPMlh2c2VpZ2lEWmRJSzgiLCJsb2dzIjoiaEtSOEZUYkhSVnhxV092TTZWXzZ1dUdMSVA3T2loV25RR3dFSnV0REF0cyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjMwfQ - - eyJoYXNoIjoiRVI0TlZZaFp1Z3BJeXR6TFhQWjJUZ18wUGc5T3NvTEtva1RxN0R3WGpLdyIsInNpZ3MiOlt7InNpZyI6IjJlNDZjMWMzZDQ0YTQ3YzdiZDY2ZTM1MWNhZDBmY2JjYmMyMDk1ZWJhYTk5MzY4NjRmZmZhOTVlNTJhNjE5MDlkMTBlODY3Y2RhMjFmNTcyZjMxODhmYjNmNjUxYTAzMzY3NWM5ZTk2NDFhNDBlM2EwNGNlMmUyMDk4NjQ2NjAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnZ2FzLWxpbWl0IChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTdcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MTAwMDB9LCJyZXFLZXkiOiJFUjROVlloWnVncEl5dHpMWFBaMlRnXzBQZzlPc29MS29rVHE3RHdYakt3IiwibG9ncyI6IklwcDE1S0QtdlZXS3JwanVDM0NBWHk3cTZia1hudURIbF82TmFiaGVyd1EiLCJtZXRhRGF0YSI6bnVsbCwiY29udGludWF0aW9uIjpudWxsLCJ0eElkIjozMn0 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MTAwMDB9LCJyZXFLZXkiOiJFUjROVlloWnVncEl5dHpMWFBaMlRnXzBQZzlPc29MS29rVHE3RHdYakt3IiwibG9ncyI6IklwcDE1S0QtdlZXS3JwanVDM0NBWHk3cTZia1hudURIbF82TmFiaGVyd1EiLCJtZXRhRGF0YSI6bnVsbCwiY29udGludWF0aW9uIjpudWxsLCJ0eElkIjozM30 - - eyJoYXNoIjoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsInNpZ3MiOlt7InNpZyI6IjIwNmZkMmMzYTBkMzBjMDhlN2FhY2U4ZGZmNmQ1MTIxYWZhMTA3NThhM2M3YTFhNDc2NTE1YmFlMjNiNmNiZmM5NjRiNjhkYmYxMzU5MzVhYWNiYzNlZmYzMzczZWE4YmUxMmI0OTdmOTU1NjU5MDQ3NDAxNTQ0ZTUyMDNjMjA4In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnZ2FzLXByaWNlIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMThcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MS4wZS0yfSwicmVxS2V5Ijoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsImxvZ3MiOiJaUDhDRmdiOEZQUkQ0Q3E2MFV0aUp3aU9oaDduRFU3YXFBNnQtbDFFbS1NIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MzV9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MS4wZS0yfSwicmVxS2V5Ijoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsImxvZ3MiOiJaUDhDRmdiOEZQUkQ0Q3E2MFV0aUp3aU9oaDduRFU3YXFBNnQtbDFFbS1NIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MzZ9 - - eyJoYXNoIjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsInNpZ3MiOlt7InNpZyI6IjhiNGU0MjZiMDMwMGYwOTJmMWJhZDVkYTY2MWEzYjBmZWE0ZjUwNTAyZmI3ODZjOWQyOTZhNTgwZTRmOGViMTc1Njc5YjQ4NDQwMDAyNjQ2MTc2OWRjMzI4MzkxYTQzM2E5NjAxY2ZhMzk5ZDQyNmUxYTdhMmUwOWYxNzYyNzAxIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnY2hhaW4taWQgKGNoYWluLWRhdGEpKVwifX0sXCJzaWduZXJzXCI6W3tcInB1YktleVwiOlwiMzY4ODIwZjgwYzMyNGJiYzdjMmIwNjEwNjg4YTdkYTQzZTM5ZjkxZDExODczMjY3MWNkOWM3NTAwZmY0M2NjYVwifV0sXCJtZXRhXCI6e1wiY3JlYXRpb25UaW1lXCI6MCxcInR0bFwiOjg2NDAwLFwiZ2FzTGltaXRcIjoxMDAwMCxcImNoYWluSWRcIjpcIjBcIixcImdhc1ByaWNlXCI6MS4wZS0yLFwic2VuZGVyXCI6XCJzZW5kZXIwMFwifSxcIm5vbmNlXCI6XCIxOVwifSJ9 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IjAifSwicmVxS2V5IjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsImxvZ3MiOiItNEMyR2Myc0hJWE9sREt0cFBZNGZpaEI0dndWc0NPYnpPc0JxOFAyNEQ0IiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6Mzh9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IjAifSwicmVxS2V5IjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsImxvZ3MiOiItNEMyR2Myc0hJWE9sREt0cFBZNGZpaEI0dndWc0NPYnpPc0JxOFAyNEQ0IiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6Mzl9 - - eyJoYXNoIjoiV2dudUNnNkxfbDZsemJqV3RCZk1FdVB0dHlfdUdjTnJVb2w1SEdSRU9fbyIsInNpZ3MiOlt7InNpZyI6IjgxNzAxZTJiMDQ4MzdjMDk1NDY3NGNiNWM2YzcxMGJhZGZlNzA5MjJiYTM0YTEyNDVjMWZmZDJmY2Q2NTQ4NzExZjY2Y2FmNTc1Njk2ZjU2NmQzYWQ3ZGNlMzgxZGQxN2M1Njc0OWQwM2M3OWQ5NmI1OWIxNGQ3ZjAwMTE0NjBhIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnc2VuZGVyIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTEwXCJ9In0 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNlbmRlcjAwIn0sInJlcUtleSI6IldnbnVDZzZMX2w2bHpiald0QmZNRXVQdHR5X3VHY05yVW9sNUhHUkVPX28iLCJsb2dzIjoiVl96OG10RjdtMVpNRWJiQUNtZlFLbWFLejdhZF9qWjhYbXhaYV9KMTRWWSIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjQxfQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNlbmRlcjAwIn0sInJlcUtleSI6IldnbnVDZzZMX2w2bHpiald0QmZNRXVQdHR5X3VHY05yVW9sNUhHUkVPX28iLCJsb2dzIjoiVl96OG10RjdtMVpNRWJiQUNtZlFLbWFLejdhZF9qWjhYbXhaYV9KMTRWWSIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjQyfQ minerData: eyJhY2NvdW50IjoiTm9NaW5lciIsInByZWRpY2F0ZSI6IjwiLCJwdWJsaWMta2V5cyI6W119 transactionsHash: FridPvHieVs4XE7B2Fu_wSShUOA694ZeAn1OJlZB3qw - outputsHash: vX0s27SREHzRmQtTfd7iDrV5s4b24jK05vu7aaFCz_k - payloadHash: rB-uufI8Yz1hNWJnMKvRcjBhNTLcyU2ub4JaBeo2mD0 - coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoibFdaVWZjX0dKdGxUUy1LeDAtYm00aXRfSWE5bnNGZG5jZ2NwSE0td091OCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 + outputsHash: -hLAWIRrf747i8MSDVAsRcqs7YnVV9X_17YZq57stTE + payloadHash: MbN2D7TjjwSF3CGpBMMtgm1KNd_8XRv3336M3s6X7xY + coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoidG9fdGsyTzltM2lvblJyU1IwQ1dCY2tScGliS0NQbWpWSnRsS2daZVUxdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 diff --git a/test/golden/transfer-accounts-expected.txt b/test/golden/transfer-accounts-expected.txt index 410fa34fca..07354a0aba 100644 --- a/test/golden/transfer-accounts-expected.txt +++ b/test/golden/transfer-accounts-expected.txt @@ -1,4 +1,4 @@ -- output: s0GHumQ2cht2jXZZYlcqPhNcNtAUsP4zVU_R9MXuq-g +- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs cmd: coinbase - output: noxWe0aOpl3J20QHMVJP8EvPGG8kftv63GeIjvJwrXQ cmd: From 7558a3cde64d88ccc616c71100a56d066bcc05fe Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Mon, 6 Jul 2020 22:27:16 -0400 Subject: [PATCH 34/48] unmask -Werror --- chainweb.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainweb.cabal b/chainweb.cabal index 65a6a28273..e0c02e7c1d 100644 --- a/chainweb.cabal +++ b/chainweb.cabal @@ -85,7 +85,7 @@ common debugging-flags common warning-flags ghc-options: -Wall - -- -Werror + -Werror -Wcompat -Wpartial-fields -Wincomplete-record-updates From 18bc7dc9bb6325aa358ab20978c790b30dc007f5 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Mon, 6 Jul 2020 22:43:33 -0400 Subject: [PATCH 35/48] pare back some cruft --- test/Chainweb/Test/Rosetta/RestAPI.hs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 724e2cc850..d35335cb95 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -259,7 +259,7 @@ constructionSubmitTests tio envIo = cenv <- envIo step "build one-off construction submit request" - SubmitBatch (c NEL.:| []) <- mkTransfer "sender00" "sender01" sender00 tio + SubmitBatch (c NEL.:| []) <- mkTransfer tio let rk = cmdToRequestKey c req = ConstructionSubmitReq nid (encodeToText c) @@ -448,33 +448,27 @@ validateOp idx opType acct o = do -- | Build a simple transfer from sender00 to sender01 -- -mkTransfer - :: Text - -> Text - -> SimpleKeyPair - -> IO (Time Micros) - -> IO SubmitBatch -mkTransfer sender receiver keys tio = do +mkTransfer :: IO (Time Micros) -> IO SubmitBatch +mkTransfer tio = do t <- toTxCreationTime <$> tio n <- readIORef nonceRef c <- buildTextCmd $ set cbSigners - [ mkSigner' keys - [ mkTransferCap sender receiver 1.0 + [ mkSigner' sender00 + [ mkTransferCap "sender00" "sender01" 1.0 , mkGasCap ] ] $ set cbCreationTime t $ set cbNetworkId (Just v) $ mkCmd ("nonce-transfer-" <> sshow t <> "-" <> sshow n) - $ mkExec' ("(coin.transfer \"" <> sender <> "\" \"" <> receiver <> "\" 1.0)") + $ mkExec' "(coin.transfer \"sender00\" \"sender01\" 1.0)" modifyIORef' nonceRef (+1) return $ SubmitBatch (pure c) -- | Transfer one token from sender00 to sender01, applying some callback to --- the command batch before sending. This is used for updating 'MVar's that --- require request keys for rosetta tx submission in the mempool endpoints. +-- the command batch before sending. -- transferOneAsync :: IO (Time Micros) @@ -482,7 +476,7 @@ transferOneAsync -> (RequestKeys -> IO ()) -> IO PollResponses transferOneAsync tio cenv callback = do - batch0 <- mkTransfer "sender00" "sender01" sender00 tio + batch0 <- mkTransfer tio void $! callback (f batch0) rks <- sending cid cenv batch0 prs <- polling cid cenv rks ExpectPactResult @@ -490,6 +484,11 @@ transferOneAsync tio cenv callback = do where f (SubmitBatch cs) = RequestKeys (cmdToRequestKey <$> cs) +-- | Transfer one token from sender00 to sender01 asynchronously applying some +-- callback (usually putting the requestkeys into some 'MVar'), and forgetting +-- the poll response results. We use this when we want to just execute and poll +-- and do not need the responses. +-- transferOneAsync_ :: IO (Time Micros) -> ClientEnv From cb0dd1cfc2989dbb1cdf56e9b3166859783ceaa1 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Tue, 7 Jul 2020 16:30:11 -0400 Subject: [PATCH 36/48] clean up module tests --- src/Chainweb/Version.hs | 4 +- .../Test/Pact/ModuleCacheOnRestart.hs | 91 ++++++++++++------- test/Chainweb/Test/Pact/PactInProcApi.hs | 19 +--- test/Chainweb/Test/Pact/SPV.hs | 3 - test/Chainweb/Test/Rosetta/RestAPI.hs | 64 ++++++------- test/golden/create-accounts-expected.txt | 2 +- test/golden/create-table-expected.txt | 2 +- test/golden/empty-block-tests-expected.txt | 6 +- test/golden/new-block-0-expected.txt | 28 +++--- test/golden/transfer-accounts-expected.txt | 2 +- 10 files changed, 113 insertions(+), 108 deletions(-) diff --git a/src/Chainweb/Version.hs b/src/Chainweb/Version.hs index 6f2c77093e..e4fa93ae5e 100644 --- a/src/Chainweb/Version.hs +++ b/src/Chainweb/Version.hs @@ -764,7 +764,7 @@ coinV2Upgrade Mainnet01 cid h coinV2Upgrade Development cid h | cid == unsafeChainId 0 = h == 3 | otherwise = h == 4 -coinV2Upgrade _ _ 1 = True +coinV2Upgrade _ _ 2 = True coinV2Upgrade _ _ _ = False -- | Mainnet 20-chain remediations @@ -783,7 +783,7 @@ twentyChainUpgrade -> Bool twentyChainUpgrade Mainnet01 _ h = h == maxBound -- TODO: update me with a calculated height twentyChainUpgrade Development _ h = h == 150 -twentyChainUpgrade _ _ 2 = True +twentyChainUpgrade _ _ 3 = True twentyChainUpgrade _ _ _ = False -- | Preserve Pact bugs pre 1.6 chainweb version diff --git a/test/Chainweb/Test/Pact/ModuleCacheOnRestart.hs b/test/Chainweb/Test/Pact/ModuleCacheOnRestart.hs index 8ac97d7277..e489f87d8f 100644 --- a/test/Chainweb/Test/Pact/ModuleCacheOnRestart.hs +++ b/test/Chainweb/Test/Pact/ModuleCacheOnRestart.hs @@ -1,10 +1,10 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} - module Chainweb.Test.Pact.ModuleCacheOnRestart (tests) where import Control.Concurrent.MVar.Strict @@ -34,10 +34,10 @@ import Chainweb.BlockHeader.Genesis import Chainweb.ChainId import Chainweb.Logger import Chainweb.Miner.Pact +import Chainweb.Pact.Backend.Types import Chainweb.Pact.PactService import Chainweb.Pact.Types import Chainweb.Payload -import Chainweb.Payload.PayloadStore import Chainweb.Time import Chainweb.Test.Cut import Chainweb.Test.Cut.TestBlockDb @@ -47,45 +47,59 @@ import Chainweb.Version import Chainweb.Version.Utils import Chainweb.WebBlockHeaderDB + +-- ---------------------------------------------------------------------- -- +-- Global data + +logger :: GenericLogger +logger = genericLogger Quiet T.putStrLn + testVer :: ChainwebVersion testVer = FastTimedCPM peterson testChainId :: ChainId testChainId = someChainId testVer +genblock :: BlockHeader +genblock = genesisBlockHeader testVer testChainId + +type CacheTest + = ( PactServiceM RocksDbCas () + , IO (MVar ModuleCache) -> ModuleCache -> Assertion + ) + +type CacheTestStep + = (SQLiteEnv, CacheTest -> Assertion) + +-- ---------------------------------------------------------------------- -- +-- Tests + tests :: ScheduledTest -tests = - ScheduledTest label $ - withMVarResource mempty $ \iom -> - withTestBlockDbTest testVer $ \bdbio -> - withTemporaryDir $ \dir -> - testGroup label - [ - withPact' bdbio dir iom testInitial (testCase "testInitial") +tests = ScheduledTest label $ + withMVarResource mempty $ \iom -> + withTestBlockDbTest testVer $ \bdbio -> + withTemporaryDir $ \dir -> testGroup label + [ withPactTestCase bdbio dir iom testInitial "testInitial" , after AllSucceed "testInitial" $ - withPact' bdbio dir iom testRestart (testCase "testRestart1") + withPactTestCase bdbio dir iom testRestart "testRestart1" , after AllSucceed "testRestart1" $ -- wow, Tasty thinks there's a "loop" if the following test is called "testCoinbase"!! - withPact' bdbio dir iom (testCoinbase bdbio) (testCase "testDoUpgrades") + withPactTestCase bdbio dir iom (testCoinbase bdbio) "testDoUpgrades" , after AllSucceed "testDoUpgrades" $ - withPact' bdbio dir iom testRestart (testCase "testRestart2") - + withPactTestCase bdbio dir iom testRestart "testRestart2" ] where label = "Chainweb.Test.Pact.ModuleCacheOnRestart" -type CacheTest cas = - (PactServiceM cas () - ,IO (MVar ModuleCache) -> ModuleCache -> Assertion) - -- | Do genesis load, snapshot cache. -testInitial :: PayloadCasLookup cas => CacheTest cas -testInitial = (initPayloadState,snapshotCache) - where +-- +testInitial :: CacheTest +testInitial = (initPayloadState, snapshotCache) -- | Do restart load, test results of 'initialPayloadState' against snapshotted cache. -testRestart :: PayloadCasLookup cas => CacheTest cas -testRestart = (initPayloadState,checkLoadedCache) +-- +testRestart :: CacheTest +testRestart = (initPayloadState, checkLoadedCache) where checkLoadedCache ioa initCache = do a <- ioa >>= readMVar @@ -99,7 +113,8 @@ testRestart = (initPayloadState,checkLoadedCache) assertBool msg (a' == c') -- | Run coinbase to do upgrade to v2, snapshot cache. -testCoinbase :: PayloadCasLookup cas => IO TestBlockDb -> CacheTest cas +-- +testCoinbase :: IO TestBlockDb -> CacheTest testCoinbase iobdb = (initPayloadState >> doCoinbase,snapshotCache) where doCoinbase = do @@ -109,14 +124,15 @@ testCoinbase iobdb = (initPayloadState >> doCoinbase,snapshotCache) nextH <- liftIO $ getParentTestBlockDb bdb testChainId void $ execValidateBlock nextH (payloadWithOutputsToPayloadData pwo) +-- ---------------------------------------------------------------------- -- +-- Test data + -- | Interfaces can't be upgraded, but modules can, so verify hash in that case. +-- justModuleHashes :: ModuleCache -> HM.HashMap ModuleName (Maybe ModuleHash) justModuleHashes = HM.map $ \v -> preview (_1 . mdModule . _MDModule . mHash) v -genblock :: BlockHeader -genblock = genesisBlockHeader testVer testChainId - -initPayloadState :: PayloadCasLookup cas => PactServiceM cas () +initPayloadState :: PactServiceM RocksDbCas () initPayloadState = initialPayloadState dummyLogger testVer testChainId snapshotCache :: IO (MVar ModuleCache) -> ModuleCache -> IO () @@ -124,28 +140,33 @@ snapshotCache iomcache initCache = do mcache <- iomcache modifyMVar_ mcache (const (pure initCache)) +-- ---------------------------------------------------------------------- -- +-- Test runners -withPact' +withPactTestCase :: IO TestBlockDb -> IO FilePath -> IO (MVar ModuleCache) - -> CacheTest RocksDbCas - -> (Assertion -> TestTree) + -> CacheTest + -> String -> TestTree -withPact' bdbio iodir r ctest toTestTree = +withPactTestCase bdbio iodir r ctest label = withResource startPact stopPact go where - go iof = toTestTree $ iof >>= \(_,f) -> f ctest + go :: IO CacheTestStep -> TestTree + go iof = testCase label $ iof >>= \(_,f) -> f ctest + + startPact :: IO CacheTestStep startPact = do bdb <- bdbio bhdb <- getWebBlockHeaderDb (_bdbWebBlockHeaderDb bdb) testChainId let pdb = _bdbPayloadDb bdb dir <- iodir sqlEnv <- startSqliteDb testVer testChainId logger (Just dir) Nothing False - return $ (sqlEnv,) $ \(ps,cacheTest) -> do + return $ (sqlEnv,) $ \(ps, cacheTest) -> do T2 _ pstate <- initPactService' testVer testChainId logger bhdb pdb sqlEnv defaultPactServiceConfig ps cacheTest r (_psInitCache pstate) + stopPact :: CacheTestStep -> IO () stopPact (sqlEnv, _) = stopSqliteDb sqlEnv - logger = genericLogger Quiet T.putStrLn diff --git a/test/Chainweb/Test/Pact/PactInProcApi.hs b/test/Chainweb/Test/Pact/PactInProcApi.hs index 218e6cca11..4a93e49628 100644 --- a/test/Chainweb/Test/Pact/PactInProcApi.hs +++ b/test/Chainweb/Test/Pact/PactInProcApi.hs @@ -146,31 +146,22 @@ getHistory refIO reqIO = testCase "getHistory" $ do -- just check first one here assertEqual "check first entry of history" (Just - [ TxLog "coin_coin-table" "sender09" + [ TxLog "coin_coin-table" "sender00" ( object [ "guard" .= object [ "pred" .= ("keys-all" :: T.Text) - , "keys" .= ["c59d9840b0b66090836546b7eb4a73606257527ec8c2b482300fd229264b07e6" :: T.Text] + , "keys" .= ["368820f80c324bbc7c2b0610688a7da43e39f91d118732671cd9c7500ff43cca" :: T.Text] ] - , "balance" .= (Number 189998662.1) - ] - ) - , TxLog "coin_coin-table" "sender07" - ( object - [ "guard" .= object - [ "pred" .= ("keys-all" :: T.Text) - , "keys" .= ["4c31dc9ee7f24177f78b6f518012a208326e2af1f37bb0a2405b5056d0cad628" :: T.Text] - ] - , "balance" .= (Number 169998662.3) + , "balance" .= (Number 99999900.0) ] ) ] ) - (M.lookup 10 hist) + (M.lookup 8 hist) -- and transaction txids assertEqual "check txids" - [7,10,11,13,14,16,17,19,20,22,23,25,26,28,29,31,32,34,35,37,38,40,41,43] + [7,8,10,11,13,14,16,17,19,20,22,23,25,26,28,29,31,32,34,35,37,38,40] (M.keys hist) getHistoricalLookupNoTxs diff --git a/test/Chainweb/Test/Pact/SPV.hs b/test/Chainweb/Test/Pact/SPV.hs index c17685e93d..e213aa7b85 100644 --- a/test/Chainweb/Test/Pact/SPV.hs +++ b/test/Chainweb/Test/Pact/SPV.hs @@ -301,9 +301,6 @@ burnGen time pidv sid tid = do putMVar pidv pid `finally` writeIORef ref1 True return $ Vector.singleton cmd - - - tx1Code = [text| (coin.transfer-crosschain diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index d35335cb95..a2dea7ce81 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -193,18 +193,14 @@ blockTests tio envIo = testCaseSchSteps "Block Tests" $ \step -> do (_block_blockId $ _blockResp_block resp0) @?= genesisId step "send transaction" - !prs <- transferOneAsync tio cenv (putMVar rkmv) + prs <- transferOneAsync tio cenv (putMVar rkmv) rk <- NEL.head . _rkRequestKeys <$> takeMVar rkmv cmdMeta <- extractMetadata rk prs bh <- cmdMeta ^?! mix "blockHeight" - step "check tx at block height matches sent tx" + step "check tx at block height matches sent tx + remediations" resp1 <- block cenv (req bh) validateTransferResp bh resp1 - - step "validate remediations at block height 1" - remResp <- block cenv (req 1) - validateRemediations remResp where req h = BlockReq nid $ PartialBlockId (Just h) Nothing @@ -216,40 +212,40 @@ blockTests tio envIo = testCaseSchSteps "Block Tests" $ \step -> do _blockId_index (_block_blockId b) @?= bh _blockId_index (_block_parentBlockId b) @?= (bh - 1) - (cbase,fundtx,cred,deb,redeem,reward) <- - case _block_transactions b of - [x,y] -> case _transaction_operations x <> _transaction_operations y of - [a,b',c,d,e,f] -> return (a,b',c,d,e,f) - _ -> assertFailure "total tx # should be 6: coinbase + 5 for every tx" - _ -> assertFailure "every block should result in at least 2 transactions: coinbase + txs" - -- coinbase is considered a separate tx list - validateOp 0 "CoinbaseReward" "NoMiner" cbase - - -- transfers form their own tx list - validateOp 0 "FundTx" "sender00" fundtx - validateOp 1 "TransferOrCreateAcct" "sender01" cred - validateOp 2 "TransferOrCreateAcct" "sender00" deb - validateOp 3 "GasPayment" "sender00" redeem - validateOp 4 "GasPayment" "NoMiner" reward + case _block_transactions b of + [x,y] -> case _transaction_operations x <> _transaction_operations y of + [a,r1, r2, b',c,d,e,f] -> validateTxs (Just (r1,r2)) a b' c d e f + [a,b',c,d,e,f] -> validateTxs Nothing a b' c d e f + _ -> assertFailure "total tx # should be >= 6: coinbase + possible remeds + 5 for every tx" + _ -> assertFailure "every block should result in at least 2 transactions: coinbase + txs" validateBlock $ _blockResp_block resp - validateRemediations resp = do - _blockResp_otherTransactions resp @?= Nothing - - let b = _blockResp_block resp - - (cbase,rem1,rem2) <- - case _block_transactions b of - [x,y] -> case _transaction_operations x <> _transaction_operations y of - [a,b',c] -> return (a,b',c) - _ -> assertFailure "total tx # should be 3: coinbase + remediations" - _ -> assertFailure "remediation block should have 3 txs" + validateTxs remeds cbase fundtx cred deb redeem reward = do + -- coinbase is considered a separate tx list validateOp 0 "CoinbaseReward" "NoMiner" cbase - validateOp 0 "TransferOrCreateAcct" "sender09" rem1 - validateOp 1 "TransferOrCreateAcct" "sender07" rem2 + case remeds of + Just (rem1, rem2) -> do + + -- TODO: this case preserves Linda's txlog bug when + -- txs and remeds are present + + validateOp 0 "TransferOrCreateAcct" "sender09" rem1 + validateOp 1 "TransferOrCreateAcct" "sender07" rem2 + validateOp 2 "TransferOrCreateAcct" "sender00" fundtx + validateOp 3 "TransferOrCreateAcct" "sender01" cred + validateOp 4 "TransferOrCreateAcct" "sender00" deb + validateOp 5 "TransferOrCreateAcct" "sender00" redeem + validateOp 6 "TransferOrCreateAcct" "NoMiner" reward + Nothing -> do + validateOp 0 "FundTx" "sender00" fundtx + validateOp 1 "TransferOrCreateAcct" "sender01" cred + validateOp 2 "TransferOrCreateAcct" "sender00" deb + validateOp 3 "GasPayment" "sender00" redeem + validateOp 4 "GasPayment" "NoMiner" reward + -- | Rosetta construction submit endpoint tests (i.e. tx submission directly to mempool) -- diff --git a/test/golden/create-accounts-expected.txt b/test/golden/create-accounts-expected.txt index 96b27fcc48..98c68fc53f 100644 --- a/test/golden/create-accounts-expected.txt +++ b/test/golden/create-accounts-expected.txt @@ -1,4 +1,4 @@ -- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs +- output: ot8MVGDNWISNvcQYXO98nZibj7RVnEl__ETRjplshxo cmd: coinbase - output: G15srpFoJgfoVchKV2ilyjMGtscxfNFlxwV0tvUC6bE cmd: diff --git a/test/golden/create-table-expected.txt b/test/golden/create-table-expected.txt index 20ad191c5c..9b130f3550 100644 --- a/test/golden/create-table-expected.txt +++ b/test/golden/create-table-expected.txt @@ -1,4 +1,4 @@ -- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs +- output: ot8MVGDNWISNvcQYXO98nZibj7RVnEl__ETRjplshxo cmd: coinbase - output: ExfKxPyfW_VnvUXfZva1taP6-woqfIYlNcnlFnKv5wQ cmd: diff --git a/test/golden/empty-block-tests-expected.txt b/test/golden/empty-block-tests-expected.txt index 68c8037c6b..5524eefbae 100644 --- a/test/golden/empty-block-tests-expected.txt +++ b/test/golden/empty-block-tests-expected.txt @@ -3,6 +3,6 @@ results: transactions: [] minerData: eyJhY2NvdW50IjoiTm9NaW5lciIsInByZWRpY2F0ZSI6IjwiLCJwdWJsaWMta2V5cyI6W119 transactionsHash: lL9ztEiU-NwzrlTpBbvhT4M1l5Shsht94OwFyhBaFD0 - outputsHash: mY63CaLW5zc6z3pyqAQzHt68b0aGaZOhqfXYXzAXLxc - payloadHash: nqycG99dCoGv7tYDaUzTCPXr5fNUQZyPrspb26ydhHk - coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoidG9fdGsyTzltM2lvblJyU1IwQ1dCY2tScGliS0NQbWpWSnRsS2daZVUxdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 + outputsHash: HnY72uLa1oMiv2RdnmJjFMFvHgmZyETj2CG9qpPH9As + payloadHash: OLJl_XDB0L-B3ZG4ALely106KZXh45iwZQYF1Bz_9uk + coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoiSWlvZlY0UGQwdG4zb0g3bFRId3BhempYVzdfR202RDhwdTNUa3NjZTRCcyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 diff --git a/test/golden/new-block-0-expected.txt b/test/golden/new-block-0-expected.txt index 5d336d2a67..64aabe14f3 100644 --- a/test/golden/new-block-0-expected.txt +++ b/test/golden/new-block-0-expected.txt @@ -2,29 +2,29 @@ test-group: new-block results: transactions: - - eyJoYXNoIjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsInNpZ3MiOlt7InNpZyI6ImYzZTc5Mjc4MGRmNTIwZmVkMjg5MDc3MjllMjI1NTA4NTk2MzJhMzNiMTQzMTM0MDlkOTkyZmRmMjJjNTZlZDEwMzdiZTcxNDYyNWRkMTZmYWI5MmVlNjZhZmQ1MjhiNWViZjEwYWNhZjY2ZjRlZGVmMWM2ZjZjY2Q4OTkxMjA0In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihkZWZpbmUta2V5c2V0ICd0ZXN0LWFkbWluIChyZWFkLWtleXNldCBcXFwidGVzdC1hZG1pbi1rZXlzZXRcXFwiKSlcXG5cXG4obmFtZXNwYWNlICdmcmVlKVxcblxcbihtb2R1bGUgdGVzdDEgJ3Rlc3QtYWRtaW5cXG5cXG4gIChkZWZzY2hlbWEgYWNjb3VudFxcbiAgICBiYWxhbmNlOmRlY2ltYWxcXG4gICAgYW1vdW50OmRlY2ltYWxcXG4gICAgZGF0YSlcXG5cXG4gIChkZWZ0YWJsZSBhY2NvdW50czp7YWNjb3VudH0pXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFjY291bnQgKGlkIGluaXQtYmFsKVxcbiAgICAoaW5zZXJ0IGFjY291bnRzIGlkXFxuICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCI6IGluaXQtYmFsLCBcXFwiYW1vdW50XFxcIjogaW5pdC1iYWwsIFxcXCJkYXRhXFxcIjogXFxcIkNyZWF0ZWQgYWNjb3VudFxcXCIgfSkpXFxuXFxuICAoZGVmdW4gdHJhbnNmZXIgKHNyYyBkZXN0IGFtb3VudClcXG4gICAgXFxcInRyYW5zZmVyIEFNT1VOVCBmcm9tIFNSQyB0byBERVNUIGZvciB1bmVuY3J5cHRlZCBhY2NvdW50c1xcXCJcXG4gICAgKGRlYml0IHNyYyBhbW91bnQgeyBcXFwidHJhbnNmZXItdG9cXFwiOiBkZXN0IH0pXFxuICAgIChjcmVkaXQgZGVzdCBhbW91bnQgeyBcXFwidHJhbnNmZXItZnJvbVxcXCI6IHNyYyB9KSlcXG5cXG4gIChkZWZwYWN0IHBheW1lbnQgKHNyYy1lbnRpdHkgc3JjIGRlc3QtZW50aXR5IGRlc3QgYW1vdW50KVxcbiAgICBcXFwiVHdvLXBoYXNlIGNvbmZpZGVudGlhbCBwYXltZW50LCBzZW5kaW5nIG1vbmV5IGZyb20gU1JDIGF0IFNSQy1FTlRJVFkgdG8gREVTVCBhdCBERVNULUVOVElUWS5cXFwiXFxuXFxuICAgIChzdGVwLXdpdGgtcm9sbGJhY2tcXG4gICAgIHNyYy1lbnRpdHlcXG4gICAgIChsZXQgKChyZXN1bHQgKGRlYml0IHNyYyBhbW91bnQgeyBcXFwidHJhbnNmZXItdG9cXFwiOiBkZXN0LCBcXFwibWVzc2FnZVxcXCI6IFxcXCJTdGFydGluZyBwYWN0XFxcIiB9KSkpXFxuICAgICAgICh5aWVsZCB7IFxcXCJyZXN1bHRcXFwiOiByZXN1bHQsIFxcXCJhbW91bnRcXFwiOiBhbW91bnQsIFxcXCJ0eFxcXCI6IChwYWN0LWlkKSB9KSlcXG4gICAgIChjcmVkaXQgc3JjIGFtb3VudCB7IFxcXCJyb2xsYmFja1xcXCI6IChwYWN0LWlkKSB9KSlcXG5cXG4gICAgKHN0ZXBcXG4gICAgIGRlc3QtZW50aXR5XFxuICAgICAocmVzdW1lIHsgXFxcInJlc3VsdFxcXCI6PSByZXN1bHQsIFxcXCJhbW91bnRcXFwiOj0gZGViaXQtYW1vdW50IH1cXG4gICAgICAgKGNyZWRpdCBkZXN0IGRlYml0LWFtb3VudFxcbiAgICAgICAgICAgICAgIHsgXFxcInRyYW5zZmVyLWZyb21cXFwiOiBzcmMsIFxcXCJkZWJpdC1yZXN1bHRcXFwiOiByZXN1bHQsIFxcXCJ0eFxcXCI6IChwYWN0LWlkKSB9KSkpKVxcblxcbiAgKGRlZnVuIGRlYml0IChhY2N0IGFtb3VudCBkYXRhKVxcbiAgICBcXFwiRGViaXQgQUNDVCBmb3IgQU1PVU5ULCBlbmZvcmNpbmcgcG9zaXRpdmUgYW1vdW50IGFuZCBzdWZmaWNpZW50IGZ1bmRzLCBhbm5vdGF0aW5nIHdpdGggREFUQVxcXCJcXG4gICAgKGVuZm9yY2UtcG9zaXRpdmUgYW1vdW50KVxcbiAgICAod2l0aC1yZWFkIGFjY291bnRzIGFjY3QgeyBcXFwiYmFsYW5jZVxcXCI6PSBiYWxhbmNlIH1cXG4gICAgICAoY2hlY2stYmFsYW5jZSBiYWxhbmNlIGFtb3VudClcXG4gICAgICAodXBkYXRlIGFjY291bnRzIGFjY3RcXG4gICAgICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIjogKC0gYmFsYW5jZSBhbW91bnQpLCBcXFwiYW1vdW50XFxcIjogKC0gYW1vdW50KVxcbiAgICAgICAgICAgICwgXFxcImRhdGFcXFwiOiBkYXRhIH0pKSlcXG5cXG4gIChkZWZ1biBjcmVkaXQgKGFjY3QgYW1vdW50IGRhdGEpXFxuICAgIFxcXCJDcmVkaXQgQUNDVCBmb3IgQU1PVU5ULCBlbmZvcmNpbmcgcG9zaXRpdmUgYW1vdW50XFxcIlxcbiAgICAoZW5mb3JjZS1wb3NpdGl2ZSBhbW91bnQpXFxuICAgICh3aXRoLXJlYWQgYWNjb3VudHMgYWNjdCB7IFxcXCJiYWxhbmNlXFxcIjo9IGJhbGFuY2UgfVxcbiAgICAgICh1cGRhdGUgYWNjb3VudHMgYWNjdFxcbiAgICAgICAgICAgIHsgXFxcImJhbGFuY2VcXFwiOiAoKyBiYWxhbmNlIGFtb3VudCksIFxcXCJhbW91bnRcXFwiOiBhbW91bnRcXG4gICAgICAgICAgICAsIFxcXCJkYXRhXFxcIjogZGF0YSB9KSkpXFxuXFxuXFxuICAoZGVmdW4gcmVhZC1hY2NvdW50IChpZClcXG4gICAgXFxcIlJlYWQgZGF0YSBmb3IgYWNjb3VudCBJRFxcXCJcXG4gICAgKCsgeyBcXFwiYWNjb3VudFxcXCI6IGlkIH0gKHJlYWQgYWNjb3VudHMgaWQpKSlcXG5cXG4gIChkZWZ1biBjaGVjay1iYWxhbmNlIChiYWxhbmNlIGFtb3VudClcXG4gICAgKGVuZm9yY2UgKDw9IGFtb3VudCBiYWxhbmNlKSBcXFwiSW5zdWZmaWNpZW50IGZ1bmRzXFxcIikpXFxuXFxuICAoZGVmdW4gZW5mb3JjZS1wb3NpdGl2ZSAoYW1vdW50KVxcbiAgICAoZW5mb3JjZSAoPj0gYW1vdW50IDAuMCkgXFxcImFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIikpXFxuXFxuIChkZWZ1biByZWFkLWFsbCAoKVxcbiAgIChtYXAgKHJlYWQtYWNjb3VudCkgKGtleXMgYWNjb3VudHMpKSlcXG5cXG4gKGRlZnVuIHJlYWQtYWxsLWdsb2JhbCAoKVxcbiAgIChtYXAgKHJlYWQtYWNjb3VudCkgW1xcXCJBY2N0MVxcXCIgXFxcIkFjY3QyXFxcIl0pKVxcblxcbiAoZGVmdW4gY3JlYXRlLWdsb2JhbC1hY2NvdW50cyAoKVxcbiAgIChjcmVhdGUtYWNjb3VudCBcXFwiQWNjdDFcXFwiIDEwMDAwMDAuMClcXG4gICAoY3JlYXRlLWFjY291bnQgXFxcIkFjY3QyXFxcIiAwLjApXFxuICAgKHJlYWQtYWxsKSlcXG5cXG4gKGRlZnBhY3QgY3JlYXRlLXByaXZhdGUtYWNjb3VudHMgKClcXG4gICAoc3RlcCBcXFwiQWxpY2VcXFwiIChjcmVhdGUtYWNjb3VudCBcXFwiQVxcXCIgMTAwMC4wKSlcXG4gICAoc3RlcCBcXFwiQm9iXFxcIiAoY3JlYXRlLWFjY291bnQgXFxcIkJcXFwiIDEwMDAuMCkpXFxuICAgKHN0ZXAgXFxcIkNhcm9sXFxcIiAoY3JlYXRlLWFjY291bnQgXFxcIkNcXFwiIDEwMDAuMCkpXFxuICAgKHN0ZXAgXFxcIkRpbmVzaFxcXCIgKGNyZWF0ZS1hY2NvdW50IFxcXCJEXFxcIiAxMDAwLjApKSlcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjEwXCJ9In0 - - eyJnYXMiOjY0OSwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiTG9hZGVkIG1vZHVsZSBmcmVlLnRlc3QxLCBoYXNoIEI2WkpnZldENW9iUEdtWWNfaVJLaXJETVA2LVVHbTJwVVY3bXRIRC1Sc1EifSwicmVxS2V5IjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsImxvZ3MiOiJMRm51NzRDaE4wZS1IbGI3azlqZlAzcmpmcWh6WjFweUpibXpkX1lOMFdZIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MTJ9 + - eyJnYXMiOjY0OSwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiTG9hZGVkIG1vZHVsZSBmcmVlLnRlc3QxLCBoYXNoIEI2WkpnZldENW9iUEdtWWNfaVJLaXJETVA2LVVHbTJwVVY3bXRIRC1Sc1EifSwicmVxS2V5IjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsImxvZ3MiOiJMRm51NzRDaE4wZS1IbGI3azlqZlAzcmpmcWh6WjFweUpibXpkX1lOMFdZIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6OX0 - - eyJoYXNoIjoidUFaMDFQQ21QWW43UTBrdGRMZ21abEZueVFUU2t3aXRXTmp0ZTNUQ3hOYyIsInNpZ3MiOlt7InNpZyI6IjU1Nzk3Zjk2YjEwYzY5ZjRhMGY2ZTg5ZDI4OGFjMTNlZDE1MDI4NWJkNDJmODNjZTMzNjE2M2IzYTllNmM3MjFiY2FlMGE2MzhjMTgwYTk0MTE2YjlhZDBkM2UwOWFlYmI3OGE2NjVhNTg2MzdhMmExZmE0OGU3NDZiYzU5NDA5In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihjcmVhdGUtdGFibGUgZnJlZS50ZXN0MS5hY2NvdW50cylcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTFcIn0ifQ - - eyJnYXMiOjI2NCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiVGFibGVDcmVhdGVkIn0sInJlcUtleSI6InVBWjAxUENtUFluN1Ewa3RkTGdtWmxGbnlRVFNrd2l0V05qdGUzVEN4TmMiLCJsb2dzIjoianVuYlJrd3hEMVhiUHBvTnNCZlN3NEJGYUEtcW1mempEMmhfOHhQTmczbyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE1fQ + - eyJnYXMiOjI2NCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiVGFibGVDcmVhdGVkIn0sInJlcUtleSI6InVBWjAxUENtUFluN1Ewa3RkTGdtWmxGbnlRVFNrd2l0V05qdGUzVEN4TmMiLCJsb2dzIjoianVuYlJrd3hEMVhiUHBvTnNCZlN3NEJGYUEtcW1mempEMmhfOHhQTmczbyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjEyfQ - - eyJoYXNoIjoiWjZxajdIZnBSN0pnZkJFZGhsYU9BSTdjdDd1ZFM2dE5jVUF0RFZMSHNJbyIsInNpZ3MiOlt7InNpZyI6ImM5YzExMGE2MGI4M2JmMmM1OTFiMTMxMWJjOTdjNjJiNzkxZTcwNDYzM2RhY2EyMGNhYmE2MTRhNGQwYThkYmFlODJlNmQxOWQ2NDZlMWJmNGNlMWUyMDZjMTM4MmM4NGExMGI5Y2NkYWY2MzAzOGU1ZWJmMDk3ZmE3YzZjMTAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihmcmVlLnRlc3QxLmNyZWF0ZS1nbG9iYWwtYWNjb3VudHMpXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjEyXCJ9In0 - - eyJnYXMiOjU4MCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjpbeyJhbW91bnQiOjEwMDAwMDAsImRhdGEiOiJDcmVhdGVkIGFjY291bnQiLCJiYWxhbmNlIjoxMDAwMDAwLCJhY2NvdW50IjoiQWNjdDEifSx7ImFtb3VudCI6MCwiZGF0YSI6IkNyZWF0ZWQgYWNjb3VudCIsImJhbGFuY2UiOjAsImFjY291bnQiOiJBY2N0MiJ9XX0sInJlcUtleSI6Ilo2cWo3SGZwUjdKZ2ZCRWRobGFPQUk3Y3Q3dWRTNnROY1VBdERWTEhzSW8iLCJsb2dzIjoia0VIU2ZyQXRLQV9vdi1xZDV4cmpSSTFtX2phenRkSF9JbGVJWG9QNW9wNCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE4fQ + - eyJnYXMiOjU4MCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjpbeyJhbW91bnQiOjEwMDAwMDAsImRhdGEiOiJDcmVhdGVkIGFjY291bnQiLCJiYWxhbmNlIjoxMDAwMDAwLCJhY2NvdW50IjoiQWNjdDEifSx7ImFtb3VudCI6MCwiZGF0YSI6IkNyZWF0ZWQgYWNjb3VudCIsImJhbGFuY2UiOjAsImFjY291bnQiOiJBY2N0MiJ9XX0sInJlcUtleSI6Ilo2cWo3SGZwUjdKZ2ZCRWRobGFPQUk3Y3Q3dWRTNnROY1VBdERWTEhzSW8iLCJsb2dzIjoia0VIU2ZyQXRLQV9vdi1xZDV4cmpSSTFtX2phenRkSF9JbGVJWG9QNW9wNCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE1fQ - - eyJoYXNoIjoicFBrLWxFUE1jRnRDWXdXR2ZaejV2bGdzZ1ZYV3dYbXhmQVJ6bkFCbUVONCIsInNpZ3MiOlt7InNpZyI6IjM3YjI4MmY1YWQ0YWY0Yzk2YmE1NzA5YWEzOTI2NTU1YjU5MDEwYzczZmVmZTUwNzQyMGYyODVjZTI1MmQ5ZjM1YzQ5NjAxYTgwMDYxZGU2NzEzNTcxNzY2MTNmODIyODQxMDU0MjliZTVkOTEzNWMzODAxMzcyN2UyMmI3ZjA2In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihmcmVlLnRlc3QxLnRyYW5zZmVyIFxcXCJBY2N0MVxcXCIgXFxcIkFjY3QyXFxcIiAxLjAwKVwifX0sXCJzaWduZXJzXCI6W3tcInB1YktleVwiOlwiMzY4ODIwZjgwYzMyNGJiYzdjMmIwNjEwNjg4YTdkYTQzZTM5ZjkxZDExODczMjY3MWNkOWM3NTAwZmY0M2NjYVwifV0sXCJtZXRhXCI6e1wiY3JlYXRpb25UaW1lXCI6MCxcInR0bFwiOjg2NDAwLFwiZ2FzTGltaXRcIjoxMDAwMCxcImNoYWluSWRcIjpcIjBcIixcImdhc1ByaWNlXCI6MS4wZS0yLFwic2VuZGVyXCI6XCJzZW5kZXIwMFwifSxcIm5vbmNlXCI6XCIxM1wifSJ9 - - eyJnYXMiOjQwNywicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiV3JpdGUgc3VjY2VlZGVkIn0sInJlcUtleSI6InBQay1sRVBNY0Z0Q1l3V0dmWno1dmxnc2dWWFd3WG14ZkFSem5BQm1FTjQiLCJsb2dzIjoib3hWd2tvU21xM2JZeVh5aHYwT0V3ZTN2c0tGbWlkRTBtTEotQ2FZWVhRayIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjIxfQ + - eyJnYXMiOjQwNywicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiV3JpdGUgc3VjY2VlZGVkIn0sInJlcUtleSI6InBQay1sRVBNY0Z0Q1l3V0dmWno1dmxnc2dWWFd3WG14ZkFSem5BQm1FTjQiLCJsb2dzIjoib3hWd2tvU21xM2JZeVh5aHYwT0V3ZTN2c0tGbWlkRTBtTEotQ2FZWVhRayIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE4fQ - - eyJoYXNoIjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsInNpZ3MiOlt7InNpZyI6IjZhODRiMWRkNGFkNDE5ZGY3YThhODA4NGYwNWEyZDM5YzExNTBmMjI5ZTM3OTFlM2UwY2E0OTkyZDkwNGNhOGVlMTk4MTljNTE3YTVjNjM5M2E3ZmYyNWI1NjdiNjJjOTYwZTFiYmI4ZTE2YjZiMWU2YmRkNDU1Njk3ODc1MDA5In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAncHJldi1ibG9jay1oYXNoIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTRcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNWMDlUbHhfZURIQWdYZkY1WS1jcG1MMVBTWFFsTERKRWc5MUJKczBieWMifSwicmVxS2V5IjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsImxvZ3MiOiJUVVVlWFJmRFlnQlZTdjFZU0ktU3lfRVdtcHRaWXZqQlNmY1ZMc2ZzcVpVIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MjR9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNWMDlUbHhfZURIQWdYZkY1WS1jcG1MMVBTWFFsTERKRWc5MUJKczBieWMifSwicmVxS2V5IjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsImxvZ3MiOiJUVVVlWFJmRFlnQlZTdjFZU0ktU3lfRVdtcHRaWXZqQlNmY1ZMc2ZzcVpVIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MjF9 - - eyJoYXNoIjoiTzhoWU1TVUhnSkNPRXFoTy0yRFRNRGJhTzBIZmx6VjM0UHRzM0dlUHBJUSIsInNpZ3MiOlt7InNpZyI6ImMxYjQ5OTQwNTQ0MjZmNzE2NWM2NmZjNjY0MzE0N2M1N2QxYTczYzM3NjEwMjU4OGU0M2QyMzA1ZjBhY2FhYTQyMDRkZGRmNGRhMWFiMzk0OTdkY2FiM2FjZWU1NmQ0NmQ3NzJkNDZkNjAyNmU5ZjQ4MGFmMWNiMWIyNWFmYzA3In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnYmxvY2stdGltZSAoY2hhaW4tZGF0YSkpXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjE1XCJ9In0 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJ0aW1lIjoiMTk3MC0wMS0wMVQwMDowMDowMFoifX0sInJlcUtleSI6Ik84aFlNU1VIZ0pDT0VxaE8tMkRUTURiYU8wSGZselYzNFB0czNHZVBwSVEiLCJsb2dzIjoidTdKNDU3dGdzNDJ1dGhjOU1TbWtkaTkxT2tUb2FCNFpGei1QUWtSajJhdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI3fQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJ0aW1lIjoiMTk3MC0wMS0wMVQwMDowMDowMFoifX0sInJlcUtleSI6Ik84aFlNU1VIZ0pDT0VxaE8tMkRUTURiYU8wSGZselYzNFB0czNHZVBwSVEiLCJsb2dzIjoidTdKNDU3dGdzNDJ1dGhjOU1TbWtkaTkxT2tUb2FCNFpGei1QUWtSajJhdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI0fQ - - eyJoYXNoIjoiSGFsbTJLYUV5Qm5weXJqMkxHMmJQcVZDUmZBYk8yWHZzZWlnaURaZElLOCIsInNpZ3MiOlt7InNpZyI6ImI0MDNlZWI3ODI0NzA0OWU0NjEzNGQzYWQ0MWZlMTAwNWMxM2I0NzNhNjUzZGNmNTVlN2ZmMzIzOGU5N2VkYmRmZTMyZmFmODczODViYTc0MmNmMDFmYmFkMDU2ODEwNWVjNDhhMDk1MzIyNWJmMmY0ODJjNjhiMjkyZGNmOTAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnYmxvY2staGVpZ2h0IChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTZcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MX0sInJlcUtleSI6IkhhbG0yS2FFeUJucHlyajJMRzJiUHFWQ1JmQWJPMlh2c2VpZ2lEWmRJSzgiLCJsb2dzIjoiaEtSOEZUYkhSVnhxV092TTZWXzZ1dUdMSVA3T2loV25RR3dFSnV0REF0cyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjMwfQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MX0sInJlcUtleSI6IkhhbG0yS2FFeUJucHlyajJMRzJiUHFWQ1JmQWJPMlh2c2VpZ2lEWmRJSzgiLCJsb2dzIjoiaEtSOEZUYkhSVnhxV092TTZWXzZ1dUdMSVA3T2loV25RR3dFSnV0REF0cyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI3fQ - - eyJoYXNoIjoiRVI0TlZZaFp1Z3BJeXR6TFhQWjJUZ18wUGc5T3NvTEtva1RxN0R3WGpLdyIsInNpZ3MiOlt7InNpZyI6IjJlNDZjMWMzZDQ0YTQ3YzdiZDY2ZTM1MWNhZDBmY2JjYmMyMDk1ZWJhYTk5MzY4NjRmZmZhOTVlNTJhNjE5MDlkMTBlODY3Y2RhMjFmNTcyZjMxODhmYjNmNjUxYTAzMzY3NWM5ZTk2NDFhNDBlM2EwNGNlMmUyMDk4NjQ2NjAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnZ2FzLWxpbWl0IChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTdcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MTAwMDB9LCJyZXFLZXkiOiJFUjROVlloWnVncEl5dHpMWFBaMlRnXzBQZzlPc29MS29rVHE3RHdYakt3IiwibG9ncyI6IklwcDE1S0QtdlZXS3JwanVDM0NBWHk3cTZia1hudURIbF82TmFiaGVyd1EiLCJtZXRhRGF0YSI6bnVsbCwiY29udGludWF0aW9uIjpudWxsLCJ0eElkIjozM30 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MTAwMDB9LCJyZXFLZXkiOiJFUjROVlloWnVncEl5dHpMWFBaMlRnXzBQZzlPc29MS29rVHE3RHdYakt3IiwibG9ncyI6IklwcDE1S0QtdlZXS3JwanVDM0NBWHk3cTZia1hudURIbF82TmFiaGVyd1EiLCJtZXRhRGF0YSI6bnVsbCwiY29udGludWF0aW9uIjpudWxsLCJ0eElkIjozMH0 - - eyJoYXNoIjoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsInNpZ3MiOlt7InNpZyI6IjIwNmZkMmMzYTBkMzBjMDhlN2FhY2U4ZGZmNmQ1MTIxYWZhMTA3NThhM2M3YTFhNDc2NTE1YmFlMjNiNmNiZmM5NjRiNjhkYmYxMzU5MzVhYWNiYzNlZmYzMzczZWE4YmUxMmI0OTdmOTU1NjU5MDQ3NDAxNTQ0ZTUyMDNjMjA4In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnZ2FzLXByaWNlIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMThcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MS4wZS0yfSwicmVxS2V5Ijoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsImxvZ3MiOiJaUDhDRmdiOEZQUkQ0Q3E2MFV0aUp3aU9oaDduRFU3YXFBNnQtbDFFbS1NIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MzZ9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MS4wZS0yfSwicmVxS2V5Ijoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsImxvZ3MiOiJaUDhDRmdiOEZQUkQ0Q3E2MFV0aUp3aU9oaDduRFU3YXFBNnQtbDFFbS1NIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MzN9 - - eyJoYXNoIjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsInNpZ3MiOlt7InNpZyI6IjhiNGU0MjZiMDMwMGYwOTJmMWJhZDVkYTY2MWEzYjBmZWE0ZjUwNTAyZmI3ODZjOWQyOTZhNTgwZTRmOGViMTc1Njc5YjQ4NDQwMDAyNjQ2MTc2OWRjMzI4MzkxYTQzM2E5NjAxY2ZhMzk5ZDQyNmUxYTdhMmUwOWYxNzYyNzAxIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnY2hhaW4taWQgKGNoYWluLWRhdGEpKVwifX0sXCJzaWduZXJzXCI6W3tcInB1YktleVwiOlwiMzY4ODIwZjgwYzMyNGJiYzdjMmIwNjEwNjg4YTdkYTQzZTM5ZjkxZDExODczMjY3MWNkOWM3NTAwZmY0M2NjYVwifV0sXCJtZXRhXCI6e1wiY3JlYXRpb25UaW1lXCI6MCxcInR0bFwiOjg2NDAwLFwiZ2FzTGltaXRcIjoxMDAwMCxcImNoYWluSWRcIjpcIjBcIixcImdhc1ByaWNlXCI6MS4wZS0yLFwic2VuZGVyXCI6XCJzZW5kZXIwMFwifSxcIm5vbmNlXCI6XCIxOVwifSJ9 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IjAifSwicmVxS2V5IjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsImxvZ3MiOiItNEMyR2Myc0hJWE9sREt0cFBZNGZpaEI0dndWc0NPYnpPc0JxOFAyNEQ0IiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6Mzl9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IjAifSwicmVxS2V5IjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsImxvZ3MiOiItNEMyR2Myc0hJWE9sREt0cFBZNGZpaEI0dndWc0NPYnpPc0JxOFAyNEQ0IiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MzZ9 - - eyJoYXNoIjoiV2dudUNnNkxfbDZsemJqV3RCZk1FdVB0dHlfdUdjTnJVb2w1SEdSRU9fbyIsInNpZ3MiOlt7InNpZyI6IjgxNzAxZTJiMDQ4MzdjMDk1NDY3NGNiNWM2YzcxMGJhZGZlNzA5MjJiYTM0YTEyNDVjMWZmZDJmY2Q2NTQ4NzExZjY2Y2FmNTc1Njk2ZjU2NmQzYWQ3ZGNlMzgxZGQxN2M1Njc0OWQwM2M3OWQ5NmI1OWIxNGQ3ZjAwMTE0NjBhIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnc2VuZGVyIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTEwXCJ9In0 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNlbmRlcjAwIn0sInJlcUtleSI6IldnbnVDZzZMX2w2bHpiald0QmZNRXVQdHR5X3VHY05yVW9sNUhHUkVPX28iLCJsb2dzIjoiVl96OG10RjdtMVpNRWJiQUNtZlFLbWFLejdhZF9qWjhYbXhaYV9KMTRWWSIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjQyfQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNlbmRlcjAwIn0sInJlcUtleSI6IldnbnVDZzZMX2w2bHpiald0QmZNRXVQdHR5X3VHY05yVW9sNUhHUkVPX28iLCJsb2dzIjoiVl96OG10RjdtMVpNRWJiQUNtZlFLbWFLejdhZF9qWjhYbXhaYV9KMTRWWSIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjM5fQ minerData: eyJhY2NvdW50IjoiTm9NaW5lciIsInByZWRpY2F0ZSI6IjwiLCJwdWJsaWMta2V5cyI6W119 transactionsHash: FridPvHieVs4XE7B2Fu_wSShUOA694ZeAn1OJlZB3qw - outputsHash: -hLAWIRrf747i8MSDVAsRcqs7YnVV9X_17YZq57stTE - payloadHash: MbN2D7TjjwSF3CGpBMMtgm1KNd_8XRv3336M3s6X7xY - coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoidG9fdGsyTzltM2lvblJyU1IwQ1dCY2tScGliS0NQbWpWSnRsS2daZVUxdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 + outputsHash: 9HwJn7hdJfVvEihQPUrh7NHAVaxNYQihdMMf3HJ_HzU + payloadHash: mkUmxXKN4VPcmLPBQn5iIH6QDJlUm67i91D0E3NXUVE + coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoiSWlvZlY0UGQwdG4zb0g3bFRId3BhempYVzdfR202RDhwdTNUa3NjZTRCcyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 diff --git a/test/golden/transfer-accounts-expected.txt b/test/golden/transfer-accounts-expected.txt index 07354a0aba..f83c419762 100644 --- a/test/golden/transfer-accounts-expected.txt +++ b/test/golden/transfer-accounts-expected.txt @@ -1,4 +1,4 @@ -- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs +- output: ot8MVGDNWISNvcQYXO98nZibj7RVnEl__ETRjplshxo cmd: coinbase - output: noxWe0aOpl3J20QHMVJP8EvPGG8kftv63GeIjvJwrXQ cmd: From c95e9e09ff4884a9fd411b26e92dc17f09f4dad9 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Tue, 7 Jul 2020 18:00:39 -0400 Subject: [PATCH 37/48] revert coinv2 block height increase --- src/Chainweb/Version.hs | 4 ++-- test/Chainweb/Test/Pact/PactInProcApi.hs | 4 ++-- test/golden/create-accounts-expected.txt | 2 +- test/golden/create-table-expected.txt | 2 +- test/golden/empty-block-tests-expected.txt | 6 ++--- test/golden/new-block-0-expected.txt | 28 +++++++++++----------- test/golden/transfer-accounts-expected.txt | 2 +- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Chainweb/Version.hs b/src/Chainweb/Version.hs index e4fa93ae5e..6f2c77093e 100644 --- a/src/Chainweb/Version.hs +++ b/src/Chainweb/Version.hs @@ -764,7 +764,7 @@ coinV2Upgrade Mainnet01 cid h coinV2Upgrade Development cid h | cid == unsafeChainId 0 = h == 3 | otherwise = h == 4 -coinV2Upgrade _ _ 2 = True +coinV2Upgrade _ _ 1 = True coinV2Upgrade _ _ _ = False -- | Mainnet 20-chain remediations @@ -783,7 +783,7 @@ twentyChainUpgrade -> Bool twentyChainUpgrade Mainnet01 _ h = h == maxBound -- TODO: update me with a calculated height twentyChainUpgrade Development _ h = h == 150 -twentyChainUpgrade _ _ 3 = True +twentyChainUpgrade _ _ 2 = True twentyChainUpgrade _ _ _ = False -- | Preserve Pact bugs pre 1.6 chainweb version diff --git a/test/Chainweb/Test/Pact/PactInProcApi.hs b/test/Chainweb/Test/Pact/PactInProcApi.hs index 4a93e49628..8ce1483513 100644 --- a/test/Chainweb/Test/Pact/PactInProcApi.hs +++ b/test/Chainweb/Test/Pact/PactInProcApi.hs @@ -158,10 +158,10 @@ getHistory refIO reqIO = testCase "getHistory" $ do ] ) - (M.lookup 8 hist) + (M.lookup 11 hist) -- skip remediations at 10 -- and transaction txids assertEqual "check txids" - [7,8,10,11,13,14,16,17,19,20,22,23,25,26,28,29,31,32,34,35,37,38,40] + [7,10,11,13,14,16,17,19,20,22,23,25,26,28,29,31,32,34,35,37,38,40,41,43] (M.keys hist) getHistoricalLookupNoTxs diff --git a/test/golden/create-accounts-expected.txt b/test/golden/create-accounts-expected.txt index 98c68fc53f..96b27fcc48 100644 --- a/test/golden/create-accounts-expected.txt +++ b/test/golden/create-accounts-expected.txt @@ -1,4 +1,4 @@ -- output: ot8MVGDNWISNvcQYXO98nZibj7RVnEl__ETRjplshxo +- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs cmd: coinbase - output: G15srpFoJgfoVchKV2ilyjMGtscxfNFlxwV0tvUC6bE cmd: diff --git a/test/golden/create-table-expected.txt b/test/golden/create-table-expected.txt index 9b130f3550..20ad191c5c 100644 --- a/test/golden/create-table-expected.txt +++ b/test/golden/create-table-expected.txt @@ -1,4 +1,4 @@ -- output: ot8MVGDNWISNvcQYXO98nZibj7RVnEl__ETRjplshxo +- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs cmd: coinbase - output: ExfKxPyfW_VnvUXfZva1taP6-woqfIYlNcnlFnKv5wQ cmd: diff --git a/test/golden/empty-block-tests-expected.txt b/test/golden/empty-block-tests-expected.txt index 5524eefbae..68c8037c6b 100644 --- a/test/golden/empty-block-tests-expected.txt +++ b/test/golden/empty-block-tests-expected.txt @@ -3,6 +3,6 @@ results: transactions: [] minerData: eyJhY2NvdW50IjoiTm9NaW5lciIsInByZWRpY2F0ZSI6IjwiLCJwdWJsaWMta2V5cyI6W119 transactionsHash: lL9ztEiU-NwzrlTpBbvhT4M1l5Shsht94OwFyhBaFD0 - outputsHash: HnY72uLa1oMiv2RdnmJjFMFvHgmZyETj2CG9qpPH9As - payloadHash: OLJl_XDB0L-B3ZG4ALely106KZXh45iwZQYF1Bz_9uk - coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoiSWlvZlY0UGQwdG4zb0g3bFRId3BhempYVzdfR202RDhwdTNUa3NjZTRCcyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 + outputsHash: mY63CaLW5zc6z3pyqAQzHt68b0aGaZOhqfXYXzAXLxc + payloadHash: nqycG99dCoGv7tYDaUzTCPXr5fNUQZyPrspb26ydhHk + coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoidG9fdGsyTzltM2lvblJyU1IwQ1dCY2tScGliS0NQbWpWSnRsS2daZVUxdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 diff --git a/test/golden/new-block-0-expected.txt b/test/golden/new-block-0-expected.txt index 64aabe14f3..5d336d2a67 100644 --- a/test/golden/new-block-0-expected.txt +++ b/test/golden/new-block-0-expected.txt @@ -2,29 +2,29 @@ test-group: new-block results: transactions: - - eyJoYXNoIjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsInNpZ3MiOlt7InNpZyI6ImYzZTc5Mjc4MGRmNTIwZmVkMjg5MDc3MjllMjI1NTA4NTk2MzJhMzNiMTQzMTM0MDlkOTkyZmRmMjJjNTZlZDEwMzdiZTcxNDYyNWRkMTZmYWI5MmVlNjZhZmQ1MjhiNWViZjEwYWNhZjY2ZjRlZGVmMWM2ZjZjY2Q4OTkxMjA0In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihkZWZpbmUta2V5c2V0ICd0ZXN0LWFkbWluIChyZWFkLWtleXNldCBcXFwidGVzdC1hZG1pbi1rZXlzZXRcXFwiKSlcXG5cXG4obmFtZXNwYWNlICdmcmVlKVxcblxcbihtb2R1bGUgdGVzdDEgJ3Rlc3QtYWRtaW5cXG5cXG4gIChkZWZzY2hlbWEgYWNjb3VudFxcbiAgICBiYWxhbmNlOmRlY2ltYWxcXG4gICAgYW1vdW50OmRlY2ltYWxcXG4gICAgZGF0YSlcXG5cXG4gIChkZWZ0YWJsZSBhY2NvdW50czp7YWNjb3VudH0pXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFjY291bnQgKGlkIGluaXQtYmFsKVxcbiAgICAoaW5zZXJ0IGFjY291bnRzIGlkXFxuICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCI6IGluaXQtYmFsLCBcXFwiYW1vdW50XFxcIjogaW5pdC1iYWwsIFxcXCJkYXRhXFxcIjogXFxcIkNyZWF0ZWQgYWNjb3VudFxcXCIgfSkpXFxuXFxuICAoZGVmdW4gdHJhbnNmZXIgKHNyYyBkZXN0IGFtb3VudClcXG4gICAgXFxcInRyYW5zZmVyIEFNT1VOVCBmcm9tIFNSQyB0byBERVNUIGZvciB1bmVuY3J5cHRlZCBhY2NvdW50c1xcXCJcXG4gICAgKGRlYml0IHNyYyBhbW91bnQgeyBcXFwidHJhbnNmZXItdG9cXFwiOiBkZXN0IH0pXFxuICAgIChjcmVkaXQgZGVzdCBhbW91bnQgeyBcXFwidHJhbnNmZXItZnJvbVxcXCI6IHNyYyB9KSlcXG5cXG4gIChkZWZwYWN0IHBheW1lbnQgKHNyYy1lbnRpdHkgc3JjIGRlc3QtZW50aXR5IGRlc3QgYW1vdW50KVxcbiAgICBcXFwiVHdvLXBoYXNlIGNvbmZpZGVudGlhbCBwYXltZW50LCBzZW5kaW5nIG1vbmV5IGZyb20gU1JDIGF0IFNSQy1FTlRJVFkgdG8gREVTVCBhdCBERVNULUVOVElUWS5cXFwiXFxuXFxuICAgIChzdGVwLXdpdGgtcm9sbGJhY2tcXG4gICAgIHNyYy1lbnRpdHlcXG4gICAgIChsZXQgKChyZXN1bHQgKGRlYml0IHNyYyBhbW91bnQgeyBcXFwidHJhbnNmZXItdG9cXFwiOiBkZXN0LCBcXFwibWVzc2FnZVxcXCI6IFxcXCJTdGFydGluZyBwYWN0XFxcIiB9KSkpXFxuICAgICAgICh5aWVsZCB7IFxcXCJyZXN1bHRcXFwiOiByZXN1bHQsIFxcXCJhbW91bnRcXFwiOiBhbW91bnQsIFxcXCJ0eFxcXCI6IChwYWN0LWlkKSB9KSlcXG4gICAgIChjcmVkaXQgc3JjIGFtb3VudCB7IFxcXCJyb2xsYmFja1xcXCI6IChwYWN0LWlkKSB9KSlcXG5cXG4gICAgKHN0ZXBcXG4gICAgIGRlc3QtZW50aXR5XFxuICAgICAocmVzdW1lIHsgXFxcInJlc3VsdFxcXCI6PSByZXN1bHQsIFxcXCJhbW91bnRcXFwiOj0gZGViaXQtYW1vdW50IH1cXG4gICAgICAgKGNyZWRpdCBkZXN0IGRlYml0LWFtb3VudFxcbiAgICAgICAgICAgICAgIHsgXFxcInRyYW5zZmVyLWZyb21cXFwiOiBzcmMsIFxcXCJkZWJpdC1yZXN1bHRcXFwiOiByZXN1bHQsIFxcXCJ0eFxcXCI6IChwYWN0LWlkKSB9KSkpKVxcblxcbiAgKGRlZnVuIGRlYml0IChhY2N0IGFtb3VudCBkYXRhKVxcbiAgICBcXFwiRGViaXQgQUNDVCBmb3IgQU1PVU5ULCBlbmZvcmNpbmcgcG9zaXRpdmUgYW1vdW50IGFuZCBzdWZmaWNpZW50IGZ1bmRzLCBhbm5vdGF0aW5nIHdpdGggREFUQVxcXCJcXG4gICAgKGVuZm9yY2UtcG9zaXRpdmUgYW1vdW50KVxcbiAgICAod2l0aC1yZWFkIGFjY291bnRzIGFjY3QgeyBcXFwiYmFsYW5jZVxcXCI6PSBiYWxhbmNlIH1cXG4gICAgICAoY2hlY2stYmFsYW5jZSBiYWxhbmNlIGFtb3VudClcXG4gICAgICAodXBkYXRlIGFjY291bnRzIGFjY3RcXG4gICAgICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIjogKC0gYmFsYW5jZSBhbW91bnQpLCBcXFwiYW1vdW50XFxcIjogKC0gYW1vdW50KVxcbiAgICAgICAgICAgICwgXFxcImRhdGFcXFwiOiBkYXRhIH0pKSlcXG5cXG4gIChkZWZ1biBjcmVkaXQgKGFjY3QgYW1vdW50IGRhdGEpXFxuICAgIFxcXCJDcmVkaXQgQUNDVCBmb3IgQU1PVU5ULCBlbmZvcmNpbmcgcG9zaXRpdmUgYW1vdW50XFxcIlxcbiAgICAoZW5mb3JjZS1wb3NpdGl2ZSBhbW91bnQpXFxuICAgICh3aXRoLXJlYWQgYWNjb3VudHMgYWNjdCB7IFxcXCJiYWxhbmNlXFxcIjo9IGJhbGFuY2UgfVxcbiAgICAgICh1cGRhdGUgYWNjb3VudHMgYWNjdFxcbiAgICAgICAgICAgIHsgXFxcImJhbGFuY2VcXFwiOiAoKyBiYWxhbmNlIGFtb3VudCksIFxcXCJhbW91bnRcXFwiOiBhbW91bnRcXG4gICAgICAgICAgICAsIFxcXCJkYXRhXFxcIjogZGF0YSB9KSkpXFxuXFxuXFxuICAoZGVmdW4gcmVhZC1hY2NvdW50IChpZClcXG4gICAgXFxcIlJlYWQgZGF0YSBmb3IgYWNjb3VudCBJRFxcXCJcXG4gICAgKCsgeyBcXFwiYWNjb3VudFxcXCI6IGlkIH0gKHJlYWQgYWNjb3VudHMgaWQpKSlcXG5cXG4gIChkZWZ1biBjaGVjay1iYWxhbmNlIChiYWxhbmNlIGFtb3VudClcXG4gICAgKGVuZm9yY2UgKDw9IGFtb3VudCBiYWxhbmNlKSBcXFwiSW5zdWZmaWNpZW50IGZ1bmRzXFxcIikpXFxuXFxuICAoZGVmdW4gZW5mb3JjZS1wb3NpdGl2ZSAoYW1vdW50KVxcbiAgICAoZW5mb3JjZSAoPj0gYW1vdW50IDAuMCkgXFxcImFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIikpXFxuXFxuIChkZWZ1biByZWFkLWFsbCAoKVxcbiAgIChtYXAgKHJlYWQtYWNjb3VudCkgKGtleXMgYWNjb3VudHMpKSlcXG5cXG4gKGRlZnVuIHJlYWQtYWxsLWdsb2JhbCAoKVxcbiAgIChtYXAgKHJlYWQtYWNjb3VudCkgW1xcXCJBY2N0MVxcXCIgXFxcIkFjY3QyXFxcIl0pKVxcblxcbiAoZGVmdW4gY3JlYXRlLWdsb2JhbC1hY2NvdW50cyAoKVxcbiAgIChjcmVhdGUtYWNjb3VudCBcXFwiQWNjdDFcXFwiIDEwMDAwMDAuMClcXG4gICAoY3JlYXRlLWFjY291bnQgXFxcIkFjY3QyXFxcIiAwLjApXFxuICAgKHJlYWQtYWxsKSlcXG5cXG4gKGRlZnBhY3QgY3JlYXRlLXByaXZhdGUtYWNjb3VudHMgKClcXG4gICAoc3RlcCBcXFwiQWxpY2VcXFwiIChjcmVhdGUtYWNjb3VudCBcXFwiQVxcXCIgMTAwMC4wKSlcXG4gICAoc3RlcCBcXFwiQm9iXFxcIiAoY3JlYXRlLWFjY291bnQgXFxcIkJcXFwiIDEwMDAuMCkpXFxuICAgKHN0ZXAgXFxcIkNhcm9sXFxcIiAoY3JlYXRlLWFjY291bnQgXFxcIkNcXFwiIDEwMDAuMCkpXFxuICAgKHN0ZXAgXFxcIkRpbmVzaFxcXCIgKGNyZWF0ZS1hY2NvdW50IFxcXCJEXFxcIiAxMDAwLjApKSlcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjEwXCJ9In0 - - eyJnYXMiOjY0OSwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiTG9hZGVkIG1vZHVsZSBmcmVlLnRlc3QxLCBoYXNoIEI2WkpnZldENW9iUEdtWWNfaVJLaXJETVA2LVVHbTJwVVY3bXRIRC1Sc1EifSwicmVxS2V5IjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsImxvZ3MiOiJMRm51NzRDaE4wZS1IbGI3azlqZlAzcmpmcWh6WjFweUpibXpkX1lOMFdZIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6OX0 + - eyJnYXMiOjY0OSwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiTG9hZGVkIG1vZHVsZSBmcmVlLnRlc3QxLCBoYXNoIEI2WkpnZldENW9iUEdtWWNfaVJLaXJETVA2LVVHbTJwVVY3bXRIRC1Sc1EifSwicmVxS2V5IjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsImxvZ3MiOiJMRm51NzRDaE4wZS1IbGI3azlqZlAzcmpmcWh6WjFweUpibXpkX1lOMFdZIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MTJ9 - - eyJoYXNoIjoidUFaMDFQQ21QWW43UTBrdGRMZ21abEZueVFUU2t3aXRXTmp0ZTNUQ3hOYyIsInNpZ3MiOlt7InNpZyI6IjU1Nzk3Zjk2YjEwYzY5ZjRhMGY2ZTg5ZDI4OGFjMTNlZDE1MDI4NWJkNDJmODNjZTMzNjE2M2IzYTllNmM3MjFiY2FlMGE2MzhjMTgwYTk0MTE2YjlhZDBkM2UwOWFlYmI3OGE2NjVhNTg2MzdhMmExZmE0OGU3NDZiYzU5NDA5In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihjcmVhdGUtdGFibGUgZnJlZS50ZXN0MS5hY2NvdW50cylcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTFcIn0ifQ - - eyJnYXMiOjI2NCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiVGFibGVDcmVhdGVkIn0sInJlcUtleSI6InVBWjAxUENtUFluN1Ewa3RkTGdtWmxGbnlRVFNrd2l0V05qdGUzVEN4TmMiLCJsb2dzIjoianVuYlJrd3hEMVhiUHBvTnNCZlN3NEJGYUEtcW1mempEMmhfOHhQTmczbyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjEyfQ + - eyJnYXMiOjI2NCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiVGFibGVDcmVhdGVkIn0sInJlcUtleSI6InVBWjAxUENtUFluN1Ewa3RkTGdtWmxGbnlRVFNrd2l0V05qdGUzVEN4TmMiLCJsb2dzIjoianVuYlJrd3hEMVhiUHBvTnNCZlN3NEJGYUEtcW1mempEMmhfOHhQTmczbyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE1fQ - - eyJoYXNoIjoiWjZxajdIZnBSN0pnZkJFZGhsYU9BSTdjdDd1ZFM2dE5jVUF0RFZMSHNJbyIsInNpZ3MiOlt7InNpZyI6ImM5YzExMGE2MGI4M2JmMmM1OTFiMTMxMWJjOTdjNjJiNzkxZTcwNDYzM2RhY2EyMGNhYmE2MTRhNGQwYThkYmFlODJlNmQxOWQ2NDZlMWJmNGNlMWUyMDZjMTM4MmM4NGExMGI5Y2NkYWY2MzAzOGU1ZWJmMDk3ZmE3YzZjMTAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihmcmVlLnRlc3QxLmNyZWF0ZS1nbG9iYWwtYWNjb3VudHMpXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjEyXCJ9In0 - - eyJnYXMiOjU4MCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjpbeyJhbW91bnQiOjEwMDAwMDAsImRhdGEiOiJDcmVhdGVkIGFjY291bnQiLCJiYWxhbmNlIjoxMDAwMDAwLCJhY2NvdW50IjoiQWNjdDEifSx7ImFtb3VudCI6MCwiZGF0YSI6IkNyZWF0ZWQgYWNjb3VudCIsImJhbGFuY2UiOjAsImFjY291bnQiOiJBY2N0MiJ9XX0sInJlcUtleSI6Ilo2cWo3SGZwUjdKZ2ZCRWRobGFPQUk3Y3Q3dWRTNnROY1VBdERWTEhzSW8iLCJsb2dzIjoia0VIU2ZyQXRLQV9vdi1xZDV4cmpSSTFtX2phenRkSF9JbGVJWG9QNW9wNCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE1fQ + - eyJnYXMiOjU4MCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjpbeyJhbW91bnQiOjEwMDAwMDAsImRhdGEiOiJDcmVhdGVkIGFjY291bnQiLCJiYWxhbmNlIjoxMDAwMDAwLCJhY2NvdW50IjoiQWNjdDEifSx7ImFtb3VudCI6MCwiZGF0YSI6IkNyZWF0ZWQgYWNjb3VudCIsImJhbGFuY2UiOjAsImFjY291bnQiOiJBY2N0MiJ9XX0sInJlcUtleSI6Ilo2cWo3SGZwUjdKZ2ZCRWRobGFPQUk3Y3Q3dWRTNnROY1VBdERWTEhzSW8iLCJsb2dzIjoia0VIU2ZyQXRLQV9vdi1xZDV4cmpSSTFtX2phenRkSF9JbGVJWG9QNW9wNCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE4fQ - - eyJoYXNoIjoicFBrLWxFUE1jRnRDWXdXR2ZaejV2bGdzZ1ZYV3dYbXhmQVJ6bkFCbUVONCIsInNpZ3MiOlt7InNpZyI6IjM3YjI4MmY1YWQ0YWY0Yzk2YmE1NzA5YWEzOTI2NTU1YjU5MDEwYzczZmVmZTUwNzQyMGYyODVjZTI1MmQ5ZjM1YzQ5NjAxYTgwMDYxZGU2NzEzNTcxNzY2MTNmODIyODQxMDU0MjliZTVkOTEzNWMzODAxMzcyN2UyMmI3ZjA2In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihmcmVlLnRlc3QxLnRyYW5zZmVyIFxcXCJBY2N0MVxcXCIgXFxcIkFjY3QyXFxcIiAxLjAwKVwifX0sXCJzaWduZXJzXCI6W3tcInB1YktleVwiOlwiMzY4ODIwZjgwYzMyNGJiYzdjMmIwNjEwNjg4YTdkYTQzZTM5ZjkxZDExODczMjY3MWNkOWM3NTAwZmY0M2NjYVwifV0sXCJtZXRhXCI6e1wiY3JlYXRpb25UaW1lXCI6MCxcInR0bFwiOjg2NDAwLFwiZ2FzTGltaXRcIjoxMDAwMCxcImNoYWluSWRcIjpcIjBcIixcImdhc1ByaWNlXCI6MS4wZS0yLFwic2VuZGVyXCI6XCJzZW5kZXIwMFwifSxcIm5vbmNlXCI6XCIxM1wifSJ9 - - eyJnYXMiOjQwNywicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiV3JpdGUgc3VjY2VlZGVkIn0sInJlcUtleSI6InBQay1sRVBNY0Z0Q1l3V0dmWno1dmxnc2dWWFd3WG14ZkFSem5BQm1FTjQiLCJsb2dzIjoib3hWd2tvU21xM2JZeVh5aHYwT0V3ZTN2c0tGbWlkRTBtTEotQ2FZWVhRayIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE4fQ + - eyJnYXMiOjQwNywicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiV3JpdGUgc3VjY2VlZGVkIn0sInJlcUtleSI6InBQay1sRVBNY0Z0Q1l3V0dmWno1dmxnc2dWWFd3WG14ZkFSem5BQm1FTjQiLCJsb2dzIjoib3hWd2tvU21xM2JZeVh5aHYwT0V3ZTN2c0tGbWlkRTBtTEotQ2FZWVhRayIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjIxfQ - - eyJoYXNoIjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsInNpZ3MiOlt7InNpZyI6IjZhODRiMWRkNGFkNDE5ZGY3YThhODA4NGYwNWEyZDM5YzExNTBmMjI5ZTM3OTFlM2UwY2E0OTkyZDkwNGNhOGVlMTk4MTljNTE3YTVjNjM5M2E3ZmYyNWI1NjdiNjJjOTYwZTFiYmI4ZTE2YjZiMWU2YmRkNDU1Njk3ODc1MDA5In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAncHJldi1ibG9jay1oYXNoIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTRcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNWMDlUbHhfZURIQWdYZkY1WS1jcG1MMVBTWFFsTERKRWc5MUJKczBieWMifSwicmVxS2V5IjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsImxvZ3MiOiJUVVVlWFJmRFlnQlZTdjFZU0ktU3lfRVdtcHRaWXZqQlNmY1ZMc2ZzcVpVIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MjF9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNWMDlUbHhfZURIQWdYZkY1WS1jcG1MMVBTWFFsTERKRWc5MUJKczBieWMifSwicmVxS2V5IjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsImxvZ3MiOiJUVVVlWFJmRFlnQlZTdjFZU0ktU3lfRVdtcHRaWXZqQlNmY1ZMc2ZzcVpVIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MjR9 - - eyJoYXNoIjoiTzhoWU1TVUhnSkNPRXFoTy0yRFRNRGJhTzBIZmx6VjM0UHRzM0dlUHBJUSIsInNpZ3MiOlt7InNpZyI6ImMxYjQ5OTQwNTQ0MjZmNzE2NWM2NmZjNjY0MzE0N2M1N2QxYTczYzM3NjEwMjU4OGU0M2QyMzA1ZjBhY2FhYTQyMDRkZGRmNGRhMWFiMzk0OTdkY2FiM2FjZWU1NmQ0NmQ3NzJkNDZkNjAyNmU5ZjQ4MGFmMWNiMWIyNWFmYzA3In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnYmxvY2stdGltZSAoY2hhaW4tZGF0YSkpXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjE1XCJ9In0 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJ0aW1lIjoiMTk3MC0wMS0wMVQwMDowMDowMFoifX0sInJlcUtleSI6Ik84aFlNU1VIZ0pDT0VxaE8tMkRUTURiYU8wSGZselYzNFB0czNHZVBwSVEiLCJsb2dzIjoidTdKNDU3dGdzNDJ1dGhjOU1TbWtkaTkxT2tUb2FCNFpGei1QUWtSajJhdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI0fQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJ0aW1lIjoiMTk3MC0wMS0wMVQwMDowMDowMFoifX0sInJlcUtleSI6Ik84aFlNU1VIZ0pDT0VxaE8tMkRUTURiYU8wSGZselYzNFB0czNHZVBwSVEiLCJsb2dzIjoidTdKNDU3dGdzNDJ1dGhjOU1TbWtkaTkxT2tUb2FCNFpGei1QUWtSajJhdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI3fQ - - eyJoYXNoIjoiSGFsbTJLYUV5Qm5weXJqMkxHMmJQcVZDUmZBYk8yWHZzZWlnaURaZElLOCIsInNpZ3MiOlt7InNpZyI6ImI0MDNlZWI3ODI0NzA0OWU0NjEzNGQzYWQ0MWZlMTAwNWMxM2I0NzNhNjUzZGNmNTVlN2ZmMzIzOGU5N2VkYmRmZTMyZmFmODczODViYTc0MmNmMDFmYmFkMDU2ODEwNWVjNDhhMDk1MzIyNWJmMmY0ODJjNjhiMjkyZGNmOTAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnYmxvY2staGVpZ2h0IChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTZcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MX0sInJlcUtleSI6IkhhbG0yS2FFeUJucHlyajJMRzJiUHFWQ1JmQWJPMlh2c2VpZ2lEWmRJSzgiLCJsb2dzIjoiaEtSOEZUYkhSVnhxV092TTZWXzZ1dUdMSVA3T2loV25RR3dFSnV0REF0cyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI3fQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MX0sInJlcUtleSI6IkhhbG0yS2FFeUJucHlyajJMRzJiUHFWQ1JmQWJPMlh2c2VpZ2lEWmRJSzgiLCJsb2dzIjoiaEtSOEZUYkhSVnhxV092TTZWXzZ1dUdMSVA3T2loV25RR3dFSnV0REF0cyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjMwfQ - - eyJoYXNoIjoiRVI0TlZZaFp1Z3BJeXR6TFhQWjJUZ18wUGc5T3NvTEtva1RxN0R3WGpLdyIsInNpZ3MiOlt7InNpZyI6IjJlNDZjMWMzZDQ0YTQ3YzdiZDY2ZTM1MWNhZDBmY2JjYmMyMDk1ZWJhYTk5MzY4NjRmZmZhOTVlNTJhNjE5MDlkMTBlODY3Y2RhMjFmNTcyZjMxODhmYjNmNjUxYTAzMzY3NWM5ZTk2NDFhNDBlM2EwNGNlMmUyMDk4NjQ2NjAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnZ2FzLWxpbWl0IChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTdcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MTAwMDB9LCJyZXFLZXkiOiJFUjROVlloWnVncEl5dHpMWFBaMlRnXzBQZzlPc29MS29rVHE3RHdYakt3IiwibG9ncyI6IklwcDE1S0QtdlZXS3JwanVDM0NBWHk3cTZia1hudURIbF82TmFiaGVyd1EiLCJtZXRhRGF0YSI6bnVsbCwiY29udGludWF0aW9uIjpudWxsLCJ0eElkIjozMH0 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MTAwMDB9LCJyZXFLZXkiOiJFUjROVlloWnVncEl5dHpMWFBaMlRnXzBQZzlPc29MS29rVHE3RHdYakt3IiwibG9ncyI6IklwcDE1S0QtdlZXS3JwanVDM0NBWHk3cTZia1hudURIbF82TmFiaGVyd1EiLCJtZXRhRGF0YSI6bnVsbCwiY29udGludWF0aW9uIjpudWxsLCJ0eElkIjozM30 - - eyJoYXNoIjoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsInNpZ3MiOlt7InNpZyI6IjIwNmZkMmMzYTBkMzBjMDhlN2FhY2U4ZGZmNmQ1MTIxYWZhMTA3NThhM2M3YTFhNDc2NTE1YmFlMjNiNmNiZmM5NjRiNjhkYmYxMzU5MzVhYWNiYzNlZmYzMzczZWE4YmUxMmI0OTdmOTU1NjU5MDQ3NDAxNTQ0ZTUyMDNjMjA4In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnZ2FzLXByaWNlIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMThcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MS4wZS0yfSwicmVxS2V5Ijoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsImxvZ3MiOiJaUDhDRmdiOEZQUkQ0Q3E2MFV0aUp3aU9oaDduRFU3YXFBNnQtbDFFbS1NIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MzN9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MS4wZS0yfSwicmVxS2V5Ijoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsImxvZ3MiOiJaUDhDRmdiOEZQUkQ0Q3E2MFV0aUp3aU9oaDduRFU3YXFBNnQtbDFFbS1NIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MzZ9 - - eyJoYXNoIjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsInNpZ3MiOlt7InNpZyI6IjhiNGU0MjZiMDMwMGYwOTJmMWJhZDVkYTY2MWEzYjBmZWE0ZjUwNTAyZmI3ODZjOWQyOTZhNTgwZTRmOGViMTc1Njc5YjQ4NDQwMDAyNjQ2MTc2OWRjMzI4MzkxYTQzM2E5NjAxY2ZhMzk5ZDQyNmUxYTdhMmUwOWYxNzYyNzAxIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnY2hhaW4taWQgKGNoYWluLWRhdGEpKVwifX0sXCJzaWduZXJzXCI6W3tcInB1YktleVwiOlwiMzY4ODIwZjgwYzMyNGJiYzdjMmIwNjEwNjg4YTdkYTQzZTM5ZjkxZDExODczMjY3MWNkOWM3NTAwZmY0M2NjYVwifV0sXCJtZXRhXCI6e1wiY3JlYXRpb25UaW1lXCI6MCxcInR0bFwiOjg2NDAwLFwiZ2FzTGltaXRcIjoxMDAwMCxcImNoYWluSWRcIjpcIjBcIixcImdhc1ByaWNlXCI6MS4wZS0yLFwic2VuZGVyXCI6XCJzZW5kZXIwMFwifSxcIm5vbmNlXCI6XCIxOVwifSJ9 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IjAifSwicmVxS2V5IjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsImxvZ3MiOiItNEMyR2Myc0hJWE9sREt0cFBZNGZpaEI0dndWc0NPYnpPc0JxOFAyNEQ0IiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MzZ9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IjAifSwicmVxS2V5IjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsImxvZ3MiOiItNEMyR2Myc0hJWE9sREt0cFBZNGZpaEI0dndWc0NPYnpPc0JxOFAyNEQ0IiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6Mzl9 - - eyJoYXNoIjoiV2dudUNnNkxfbDZsemJqV3RCZk1FdVB0dHlfdUdjTnJVb2w1SEdSRU9fbyIsInNpZ3MiOlt7InNpZyI6IjgxNzAxZTJiMDQ4MzdjMDk1NDY3NGNiNWM2YzcxMGJhZGZlNzA5MjJiYTM0YTEyNDVjMWZmZDJmY2Q2NTQ4NzExZjY2Y2FmNTc1Njk2ZjU2NmQzYWQ3ZGNlMzgxZGQxN2M1Njc0OWQwM2M3OWQ5NmI1OWIxNGQ3ZjAwMTE0NjBhIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnc2VuZGVyIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTEwXCJ9In0 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNlbmRlcjAwIn0sInJlcUtleSI6IldnbnVDZzZMX2w2bHpiald0QmZNRXVQdHR5X3VHY05yVW9sNUhHUkVPX28iLCJsb2dzIjoiVl96OG10RjdtMVpNRWJiQUNtZlFLbWFLejdhZF9qWjhYbXhaYV9KMTRWWSIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjM5fQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNlbmRlcjAwIn0sInJlcUtleSI6IldnbnVDZzZMX2w2bHpiald0QmZNRXVQdHR5X3VHY05yVW9sNUhHUkVPX28iLCJsb2dzIjoiVl96OG10RjdtMVpNRWJiQUNtZlFLbWFLejdhZF9qWjhYbXhaYV9KMTRWWSIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjQyfQ minerData: eyJhY2NvdW50IjoiTm9NaW5lciIsInByZWRpY2F0ZSI6IjwiLCJwdWJsaWMta2V5cyI6W119 transactionsHash: FridPvHieVs4XE7B2Fu_wSShUOA694ZeAn1OJlZB3qw - outputsHash: 9HwJn7hdJfVvEihQPUrh7NHAVaxNYQihdMMf3HJ_HzU - payloadHash: mkUmxXKN4VPcmLPBQn5iIH6QDJlUm67i91D0E3NXUVE - coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoiSWlvZlY0UGQwdG4zb0g3bFRId3BhempYVzdfR202RDhwdTNUa3NjZTRCcyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 + outputsHash: -hLAWIRrf747i8MSDVAsRcqs7YnVV9X_17YZq57stTE + payloadHash: MbN2D7TjjwSF3CGpBMMtgm1KNd_8XRv3336M3s6X7xY + coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoidG9fdGsyTzltM2lvblJyU1IwQ1dCY2tScGliS0NQbWpWSnRsS2daZVUxdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 diff --git a/test/golden/transfer-accounts-expected.txt b/test/golden/transfer-accounts-expected.txt index f83c419762..07354a0aba 100644 --- a/test/golden/transfer-accounts-expected.txt +++ b/test/golden/transfer-accounts-expected.txt @@ -1,4 +1,4 @@ -- output: ot8MVGDNWISNvcQYXO98nZibj7RVnEl__ETRjplshxo +- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs cmd: coinbase - output: noxWe0aOpl3J20QHMVJP8EvPGG8kftv63GeIjvJwrXQ cmd: From 5a1450d9bafd9236b79727bbf75cceea707d2109 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Wed, 8 Jul 2020 11:30:04 -0400 Subject: [PATCH 38/48] revert adding remediation to txs --- hie.yaml | 1 + src/Chainweb/Pact/TransactionExec.hs | 12 +++ .../Transactions/DevelopmentTransactions.hs | 2 +- .../Pact/Transactions/OtherTransactions.hs | 2 - .../Test/Pact/ModuleCacheOnRestart.hs | 91 +++++++------------ test/Chainweb/Test/Pact/PactInProcApi.hs | 26 +++--- test/golden/create-accounts-expected.txt | 2 +- test/golden/create-table-expected.txt | 2 +- test/golden/empty-block-tests-expected.txt | 6 +- test/golden/new-block-0-expected.txt | 28 +++--- test/golden/transfer-accounts-expected.txt | 2 +- tools/ea/Ea.hs | 6 +- 12 files changed, 82 insertions(+), 98 deletions(-) create mode 100644 hie.yaml diff --git a/hie.yaml b/hie.yaml new file mode 100644 index 0000000000..7b37c70587 --- /dev/null +++ b/hie.yaml @@ -0,0 +1 @@ +cradle: {cabal: {component: "chainweb:test:chainweb-tests"}} \ No newline at end of file diff --git a/src/Chainweb/Pact/TransactionExec.hs b/src/Chainweb/Pact/TransactionExec.hs index 770a02009c..30dbcf7cc8 100644 --- a/src/Chainweb/Pact/TransactionExec.hs +++ b/src/Chainweb/Pact/TransactionExec.hs @@ -431,6 +431,18 @@ applyUpgrades v cid height applyTxs txsIO = do infoLog "Applying upgrade!" txs <- map (fmap payloadObj) <$> liftIO txsIO + + -- + -- Note (emily): the historical use of 'mapM_' here means that we are not + -- threading the updated module cache from tx to tx in our upgrades. + -- This means that the outputed module cache is the set of modules + -- loaded in the /last/ tx, and that result will go into the hash. + -- + -- Whether this can be fixed in the future should be explored, but we've + -- already built fixes to address this problem that also affect the + -- hashes of later blocks. + -- + local (set txExecutionConfig def) $ mapM_ applyTx txs mc <- use txCache diff --git a/src/Chainweb/Pact/Transactions/DevelopmentTransactions.hs b/src/Chainweb/Pact/Transactions/DevelopmentTransactions.hs index bf87add20a..afa88a3f4e 100644 --- a/src/Chainweb/Pact/Transactions/DevelopmentTransactions.hs +++ b/src/Chainweb/Pact/Transactions/DevelopmentTransactions.hs @@ -18,5 +18,5 @@ transactions = , "eyJoYXNoIjoibVZzMjNxNnJyUjZrWDFGX0ItamNCX05hLXdZdmR3dnRwa1cwQVNaZExjRSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihtb2R1bGUgY29pbiBHT1ZFUk5BTkNFXFxuXFxuICBAZG9jIFxcXCInY29pbicgcmVwcmVzZW50cyB0aGUgS2FkZW5hIENvaW4gQ29udHJhY3QuIFRoaXMgY29udHJhY3QgcHJvdmlkZXMgYm90aCB0aGUgXFxcXFxcbiAgXFxcXGJ1eS9yZWRlZW0gZ2FzIHN1cHBvcnQgaW4gdGhlIGZvcm0gb2YgJ2Z1bmQtdHgnLCBhcyB3ZWxsIGFzIHRyYW5zZmVyLCAgICAgICBcXFxcXFxuICBcXFxcY3JlZGl0LCBkZWJpdCwgY29pbmJhc2UsIGFjY291bnQgY3JlYXRpb24gYW5kIHF1ZXJ5LCBhcyB3ZWxsIGFzIFNQViBidXJuICAgIFxcXFxcXG4gIFxcXFxjcmVhdGUuIFRvIGFjY2VzcyB0aGUgY29pbiBjb250cmFjdCwgeW91IG1heSB1c2UgaXRzIGZ1bGx5LXF1YWxpZmllZCBuYW1lLCAgXFxcXFxcbiAgXFxcXG9yIGlzc3VlIHRoZSAnKHVzZSBjb2luKScgY29tbWFuZCBpbiB0aGUgYm9keSBvZiBhIG1vZHVsZSBkZWNsYXJhdGlvbi5cXFwiXFxuXFxuICBAbW9kZWxcXG4gICAgWyAoZGVmcHJvcGVydHkgY29uc2VydmVzLW1hc3NcXG4gICAgICAgICg9IChjb2x1bW4tZGVsdGEgY29pbi10YWJsZSAnYmFsYW5jZSkgMC4wKSlcXG5cXG4gICAgICAoZGVmcHJvcGVydHkgdmFsaWQtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgICAgICAoYW5kXFxuICAgICAgICAgICg-PSAobGVuZ3RoIGFjY291bnQpIDMpXFxuICAgICAgICAgICg8PSAobGVuZ3RoIGFjY291bnQpIDI1NikpKVxcbiAgICBdXFxuXFxuICAoaW1wbGVtZW50cyBmdW5naWJsZS12MilcXG5cXG4gIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cXG4gIDsgU2NoZW1hcyBhbmQgVGFibGVzXFxuXFxuICAoZGVmc2NoZW1hIGNvaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlRoZSBjb2luIGNvbnRyYWN0IHRva2VuIHNjaGVtYVxcXCJcXG4gICAgQG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBndWFyZDpndWFyZClcXG5cXG4gIChkZWZ0YWJsZSBjb2luLXRhYmxlOntjb2luLXNjaGVtYX0pXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENhcGFiaWxpdGllc1xcblxcbiAgKGRlZmNhcCBHT1ZFUk5BTkNFICgpXFxuICAgIChlbmZvcmNlIGZhbHNlIFxcXCJFbmZvcmNlIG5vbi11cGdyYWRlYWJpbGl0eVxcXCIpKVxcblxcbiAgKGRlZmNhcCBHQVMgKClcXG4gICAgXFxcIk1hZ2ljIGNhcGFiaWxpdHkgdG8gcHJvdGVjdCBnYXMgYnV5IGFuZCByZWRlZW1cXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIENPSU5CQVNFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IHRvIHByb3RlY3QgbWluZXIgcmV3YXJkXFxcIlxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBHRU5FU0lTICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGNvbnN0cmFpbmluZyBnZW5lc2lzIHRyYW5zYWN0aW9uc1xcXCJcXG4gICAgdHJ1ZSlcXG5cXG4gIChkZWZjYXAgUkVNRURJQVRFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnNcXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIERFQklUIChzZW5kZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgZGViaXRpbmcgb3BlcmF0aW9uc1xcXCJcXG4gICAgKGVuZm9yY2UtZ3VhcmQgKGF0ICdndWFyZCAocmVhZCBjb2luLXRhYmxlIHNlbmRlcikpKVxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIFxcXCJcXFwiKSBcXFwidmFsaWQgc2VuZGVyXFxcIikpXFxuXFxuICAoZGVmY2FwIENSRURJVCAocmVjZWl2ZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgY3JlZGl0aW5nIG9wZXJhdGlvbnNcXFwiXFxuICAgIChlbmZvcmNlICghPSByZWNlaXZlciBcXFwiXFxcIikgXFxcInZhbGlkIHJlY2VpdmVyXFxcIikpXFxuXFxuICAoZGVmY2FwIFJPVEFURSAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkF1dG9ub21vdXNseSBtYW5hZ2VkIGNhcGFiaWxpdHkgZm9yIGd1YXJkIHJvdGF0aW9uXFxcIlxcbiAgICBAbWFuYWdlZFxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBUUkFOU0ZFUjpib29sXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsXFxuICAgIClcXG4gICAgQG1hbmFnZWQgYW1vdW50IFRSQU5TRkVSLW1nclxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIHJlY2VpdmVyKSBcXFwic2FtZSBzZW5kZXIgYW5kIHJlY2VpdmVyXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApIFxcXCJQb3NpdGl2ZSBhbW91bnRcXFwiKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChDUkVESVQgcmVjZWl2ZXIpKVxcbiAgKVxcblxcbiAgKGRlZnVuIFRSQU5TRkVSLW1ncjpkZWNpbWFsXFxuICAgICggbWFuYWdlZDpkZWNpbWFsXFxuICAgICAgcmVxdWVzdGVkOmRlY2ltYWxcXG4gICAgKVxcblxcbiAgICAobGV0ICgobmV3YmFsICgtIG1hbmFnZWQgcmVxdWVzdGVkKSkpXFxuICAgICAgKGVuZm9yY2UgKD49IG5ld2JhbCAwLjApXFxuICAgICAgICAoZm9ybWF0IFxcXCJUUkFOU0ZFUiBleGNlZWRlZCBmb3IgYmFsYW5jZSB7fVxcXCIgW21hbmFnZWRdKSlcXG4gICAgICBuZXdiYWwpXFxuICApXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvbnN0YW50c1xcblxcbiAgKGRlZmNvbnN0IENPSU5fQ0hBUlNFVCBDSEFSU0VUX0xBVElOMVxcbiAgICBcXFwiVGhlIGRlZmF1bHQgY29pbiBjb250cmFjdCBjaGFyYWN0ZXIgc2V0XFxcIilcXG5cXG4gIChkZWZjb25zdCBNSU5JTVVNX1BSRUNJU0lPTiAxMlxcbiAgICBcXFwiTWluaW11bSBhbGxvd2VkIHByZWNpc2lvbiBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiKVxcblxcbiAgKGRlZmNvbnN0IE1JTklNVU1fQUNDT1VOVF9MRU5HVEggM1xcbiAgICBcXFwiTWluaW11bSBhY2NvdW50IGxlbmd0aCBhZG1pc3NpYmxlIGZvciBjb2luIGFjY291bnRzXFxcIilcXG5cXG4gIChkZWZjb25zdCBNQVhJTVVNX0FDQ09VTlRfTEVOR1RIIDI1NlxcbiAgICBcXFwiTWF4aW11bSBhY2NvdW50IG5hbWUgbGVuZ3RoIGFkbWlzc2libGUgZm9yIGNvaW4gYWNjb3VudHNcXFwiKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBVdGlsaXRpZXNcXG5cXG4gIChkZWZ1biBlbmZvcmNlLXVuaXQ6Ym9vbCAoYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgbWluaW11bSBwcmVjaXNpb24gYWxsb3dlZCBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiXFxuXFxuICAgIChlbmZvcmNlXFxuICAgICAgKD0gKGZsb29yIGFtb3VudCBNSU5JTVVNX1BSRUNJU0lPTilcXG4gICAgICAgICBhbW91bnQpXFxuICAgICAgKGZvcm1hdCBcXFwiQW1vdW50IHZpb2xhdGVzIG1pbmltdW0gcHJlY2lzaW9uOiB7fVxcXCIgW2Ftb3VudF0pKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdmFsaWRhdGUtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgdGhhdCBhbiBhY2NvdW50IG5hbWUgY29uZm9ybXMgdG8gdGhlIGNvaW4gY29udHJhY3QgXFxcXFxcbiAgICAgICAgIFxcXFxtaW5pbXVtIGFuZCBtYXhpbXVtIGxlbmd0aCByZXF1aXJlbWVudHMsIGFzIHdlbGwgYXMgdGhlICAgIFxcXFxcXG4gICAgICAgICBcXFxcbGF0aW4tMSBjaGFyYWN0ZXIgc2V0LlxcXCJcXG5cXG4gICAgKGVuZm9yY2VcXG4gICAgICAoaXMtY2hhcnNldCBDT0lOX0NIQVJTRVQgYWNjb3VudClcXG4gICAgICAoZm9ybWF0XFxuICAgICAgICBcXFwiQWNjb3VudCBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBjb2luIGNvbnRyYWN0IGNoYXJzZXQ6IHt9XFxcIlxcbiAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgKGxldCAoKGFjY291bnQtbGVuZ3RoIChsZW5ndGggYWNjb3VudCkpKVxcblxcbiAgICAgIChlbmZvcmNlXFxuICAgICAgICAoPj0gYWNjb3VudC1sZW5ndGggTUlOSU1VTV9BQ0NPVU5UX0xFTkdUSClcXG4gICAgICAgIChmb3JtYXRcXG4gICAgICAgICAgXFxcIkFjY291bnQgbmFtZSBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBtaW4gbGVuZ3RoIHJlcXVpcmVtZW50OiB7fVxcXCJcXG4gICAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgICAoZW5mb3JjZVxcbiAgICAgICAgKDw9IGFjY291bnQtbGVuZ3RoIE1BWElNVU1fQUNDT1VOVF9MRU5HVEgpXFxuICAgICAgICAoZm9ybWF0XFxuICAgICAgICAgIFxcXCJBY2NvdW50IG5hbWUgZG9lcyBub3QgY29uZm9ybSB0byB0aGUgbWF4IGxlbmd0aCByZXF1aXJlbWVudDoge31cXFwiXFxuICAgICAgICAgIFthY2NvdW50XSkpXFxuICAgICAgKVxcbiAgKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBDb2luIENvbnRyYWN0XFxuXFxuICAoZGVmdW4gZ2FzLW9ubHkgKClcXG4gICAgXFxcIlByZWRpY2F0ZSBmb3IgZ2FzLW9ubHkgdXNlciBndWFyZHMuXFxcIlxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKSlcXG5cXG4gIChkZWZ1biBnYXMtZ3VhcmQgKGd1YXJkOmd1YXJkKVxcbiAgICBcXFwiUHJlZGljYXRlIGZvciBnYXMgKyBzaW5nbGUga2V5IHVzZXIgZ3VhcmRzXFxcIlxcbiAgICAoZW5mb3JjZS1vbmVcXG4gICAgICBcXFwiRW5mb3JjZSBlaXRoZXIgdGhlIHByZXNlbmNlIG9mIGEgR0FTIGNhcCBvciBrZXlzZXRcXFwiXFxuICAgICAgWyAoZ2FzLW9ubHkpXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG4gICAgICBdKSlcXG5cXG4gIChkZWZ1biBidXktZ2FzOnN0cmluZyAoc2VuZGVyOnN0cmluZyB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCJUaGlzIGZ1bmN0aW9uIGRlc2NyaWJlcyB0aGUgbWFpbiAnZ2FzIGJ1eScgb3BlcmF0aW9uLiBBdCB0aGlzIHBvaW50IFxcXFxcXG4gICAgXFxcXE1JTkVSIGhhcyBiZWVuIGNob3NlbiBmcm9tIHRoZSBwb29sLCBhbmQgd2lsbCBiZSB2YWxpZGF0ZWQuIFRoZSBTRU5ERVIgICBcXFxcXFxuICAgIFxcXFxvZiB0aGlzIHRyYW5zYWN0aW9uIGhhcyBzcGVjaWZpZWQgYSBnYXMgbGltaXQgTElNSVQgKG1heGltdW0gZ2FzKSBmb3IgICAgXFxcXFxcbiAgICBcXFxcdGhlIHRyYW5zYWN0aW9uLCBhbmQgdGhlIHByaWNlIGlzIHRoZSBzcG90IHByaWNlIG9mIGdhcyBhdCB0aGF0IHRpbWUuICAgIFxcXFxcXG4gICAgXFxcXFRoZSBnYXMgYnV5IHdpbGwgYmUgZXhlY3V0ZWQgcHJpb3IgdG8gZXhlY3V0aW5nIFNFTkRFUidzIGNvZGUuXFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCB0b3RhbClcXG4gICAgKGVuZm9yY2UgKD4gdG90YWwgMC4wKSBcXFwiZ2FzIHN1cHBseSBtdXN0IGJlIGEgcG9zaXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuICAgICAgKGRlYml0IHNlbmRlciB0b3RhbCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZWRlZW0tZ2FzOnN0cmluZyAobWluZXI6c3RyaW5nIG1pbmVyLWd1YXJkOmd1YXJkIHNlbmRlcjpzdHJpbmcgdG90YWw6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiVGhpcyBmdW5jdGlvbiBkZXNjcmliZXMgdGhlIG1haW4gJ3JlZGVlbSBnYXMnIG9wZXJhdGlvbi4gQXQgdGhpcyAgICBcXFxcXFxuICAgIFxcXFxwb2ludCwgdGhlIFNFTkRFUidzIHRyYW5zYWN0aW9uIGhhcyBiZWVuIGV4ZWN1dGVkLCBhbmQgdGhlIGdhcyB0aGF0ICAgICAgXFxcXFxcbiAgICBcXFxcd2FzIGNoYXJnZWQgaGFzIGJlZW4gY2FsY3VsYXRlZC4gTUlORVIgd2lsbCBiZSBjcmVkaXRlZCB0aGUgZ2FzIGNvc3QsICAgIFxcXFxcXG4gICAgXFxcXGFuZCBTRU5ERVIgd2lsbCByZWNlaXZlIHRoZSByZW1haW5kZXIgdXAgdG8gdGhlIGxpbWl0XFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBtaW5lcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG4gICAgKHZhbGlkYXRlLWFjY291bnQgbWluZXIpXFxuICAgIChlbmZvcmNlLXVuaXQgdG90YWwpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKEdBUykpXFxuICAgIChsZXQqXFxuICAgICAgKChmZWUgKHJlYWQtZGVjaW1hbCBcXFwiZmVlXFxcIikpXFxuICAgICAgIChyZWZ1bmQgKC0gdG90YWwgZmVlKSkpXFxuXFxuICAgICAgKGVuZm9yY2UtdW5pdCBmZWUpXFxuICAgICAgKGVuZm9yY2UgKD49IGZlZSAwLjApXFxuICAgICAgICBcXFwiZmVlIG11c3QgYmUgYSBub24tbmVnYXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAgIChlbmZvcmNlICg-PSByZWZ1bmQgMC4wKVxcbiAgICAgICAgXFxcInJlZnVuZCBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIHF1YW50aXR5XFxcIilcXG5cXG4gICAgICAgIDsgZGlyZWN0bHkgdXBkYXRlIGluc3RlYWQgb2YgY3JlZGl0XFxuICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHNlbmRlcilcXG4gICAgICAgIChpZiAoPiByZWZ1bmQgMC4wKVxcbiAgICAgICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgc2VuZGVyXFxuICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOj0gYmFsYW5jZSB9XFxuICAgICAgICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIHNlbmRlclxcbiAgICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCI6ICgrIGJhbGFuY2UgcmVmdW5kKSB9KSlcXG5cXG4gICAgICAgICAgXFxcIm5vb3BcXFwiKSlcXG5cXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChDUkVESVQgbWluZXIpXFxuICAgICAgICAoaWYgKD4gZmVlIDAuMClcXG4gICAgICAgICAgKGNyZWRpdCBtaW5lciBtaW5lci1ndWFyZCBmZWUpXFxuICAgICAgICAgIFxcXCJub29wXFxcIikpXFxuICAgICAgKVxcblxcbiAgICApXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFjY291bnQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZClcXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKSBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChpbnNlcnQgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgICA6IGd1YXJkXFxuICAgICAgfSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGdldC1iYWxhbmNlOmRlY2ltYWwgKGFjY291bnQ6c3RyaW5nKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcbiAgICAgIGJhbGFuY2VcXG4gICAgICApXFxuICAgIClcXG5cXG4gIChkZWZ1biBkZXRhaWxzOm9iamVjdHtmdW5naWJsZS12Mi5hY2NvdW50LWRldGFpbHN9XFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIiA6PSBnIH1cXG4gICAgICB7IFxcXCJhY2NvdW50XFxcIiA6IGFjY291bnRcXG4gICAgICAsIFxcXCJiYWxhbmNlXFxcIiA6IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIjogZyB9KVxcbiAgICApXFxuXFxuICAoZGVmdW4gcm90YXRlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgbmV3LWd1YXJkOmd1YXJkKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChST1RBVEUgYWNjb3VudClcXG4gICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IG9sZC1ndWFyZCB9XFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBvbGQtZ3VhcmQpXFxuXFxuICAgICAgICAodXBkYXRlIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgICB7IFxcXCJndWFyZFxcXCIgOiBuZXctZ3VhcmQgfVxcbiAgICAgICAgICApKSlcXG4gICAgKVxcblxcblxcbiAgKGRlZnVuIHByZWNpc2lvbjppbnRlZ2VyXFxuICAgICgpXFxuICAgIE1JTklNVU1fUFJFQ0lTSU9OKVxcblxcbiAgKGRlZnVuIHRyYW5zZmVyOnN0cmluZyAoc2VuZGVyOnN0cmluZyByZWNlaXZlcjpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcylcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgcmVjZWl2ZXIpKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgICh3aXRoLXJlYWQgY29pbi10YWJsZSByZWNlaXZlclxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IGcgfVxcblxcbiAgICAgICAgKGNyZWRpdCByZWNlaXZlciBnIGFtb3VudCkpXFxuICAgICAgKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdHJhbnNmZXItY3JlYXRlOnN0cmluZ1xcbiAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5IGNvbnNlcnZlcy1tYXNzKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgIChjcmVkaXQgcmVjZWl2ZXIgcmVjZWl2ZXItZ3VhcmQgYW1vdW50KSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGNvaW5iYXNlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYWNjb3VudC1ndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiSW50ZXJuYWwgZnVuY3Rpb24gZm9yIHRoZSBpbml0aWFsIGNyZWF0aW9uIG9mIGNvaW5zLiAgVGhpcyBmdW5jdGlvbiBcXFxcXFxuICAgIFxcXFxjYW5ub3QgYmUgdXNlZCBvdXRzaWRlIG9mIHRoZSBjb2luIGNvbnRyYWN0LlxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKD4gYW1vdW50IDAuMCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChDT0lOQkFTRSkpXFxuICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgIChjcmVkaXQgYWNjb3VudCBhY2NvdW50LWd1YXJkIGFtb3VudCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZW1lZGlhdGU6c3RyaW5nIChhY2NvdW50OnN0cmluZyBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQWxsb3dzIGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnMuIFRoaXMgZnVuY3Rpb24gXFxcXFxcbiAgICAgICAgIFxcXFxpcyBwcm90ZWN0ZWQgYnkgdGhlIFJFTUVESUFURSBjYXBhYmlsaXR5XFxcIlxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG5cXG4gICAgKGVuZm9yY2UgKD4gYW1vdW50IDAuMClcXG4gICAgICBcXFwiUmVtZWRpYXRpb24gYW1vdW50IG11c3QgYmUgcG9zaXRpdmVcXFwiKVxcblxcbiAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgKHJlcXVpcmUtY2FwYWJpbGl0eSAoUkVNRURJQVRFKSlcXG4gICAgKHdpdGgtcmVhZCBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6PSBiYWxhbmNlIH1cXG5cXG4gICAgICAoZW5mb3JjZSAoPD0gYW1vdW50IGJhbGFuY2UpIFxcXCJJbnN1ZmZpY2llbnQgZnVuZHNcXFwiKVxcblxcbiAgICAgICh1cGRhdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgtIGJhbGFuY2UgYW1vdW50KSB9XFxuICAgICAgICApKVxcbiAgICApXFxuXFxuICAoZGVmcGFjdCBmdW5kLXR4IChzZW5kZXI6c3RyaW5nIG1pbmVyOnN0cmluZyBtaW5lci1ndWFyZDpndWFyZCB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCInZnVuZC10eCcgaXMgYSBzcGVjaWFsIHBhY3QgdG8gZnVuZCBhIHRyYW5zYWN0aW9uIGluIHR3byBzdGVwcywgICAgIFxcXFxcXG4gICAgXFxcXHdpdGggdGhlIGFjdHVhbCB0cmFuc2FjdGlvbiB0cmFuc3BpcmluZyBpbiB0aGUgbWlkZGxlOiAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXFxcXFxcbiAgICBcXFxcICAxKSBBIGJ1eWluZyBwaGFzZSwgZGViaXRpbmcgdGhlIHNlbmRlciBmb3IgdG90YWwgZ2FzIGFuZCBmZWUsIHlpZWxkaW5nIFxcXFxcXG4gICAgXFxcXCAgICAgVFhfTUFYX0NIQVJHRS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgIDIpIEEgc2V0dGxlbWVudCBwaGFzZSwgcmVzdW1pbmcgVFhfTUFYX0NIQVJHRSwgYW5kIGFsbG9jYXRpbmcgdG8gdGhlICAgXFxcXFxcbiAgICBcXFxcICAgICBjb2luYmFzZSBhY2NvdW50IGZvciB1c2VkIGdhcyBhbmQgZmVlLCBhbmQgc2VuZGVyIGFjY291bnQgZm9yIGJhbC0gIFxcXFxcXG4gICAgXFxcXCAgICAgYW5jZSAodW51c2VkIGdhcywgaWYgYW55KS5cXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiB0b3RhbCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IG1pbmVyKSlcXG4gICAgICAgICAgICAgOyhwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcykgbm90IHN1cHBvcnRlZCB5ZXRcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXAgKGJ1eS1nYXMgc2VuZGVyIHRvdGFsKSlcXG4gICAgKHN0ZXAgKHJlZGVlbS1nYXMgbWluZXIgbWluZXItZ3VhcmQgc2VuZGVyIHRvdGFsKSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGRlYml0OnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkRlYml0IEFNT1VOVCBmcm9tIEFDQ09VTlQgYmFsYW5jZVxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApXFxuICAgICAgXFxcImRlYml0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKERFQklUIGFjY291bnQpKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcblxcbiAgICAgIChlbmZvcmNlICg8PSBhbW91bnQgYmFsYW5jZSkgXFxcIkluc3VmZmljaWVudCBmdW5kc1xcXCIpXFxuXFxuICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogKC0gYmFsYW5jZSBhbW91bnQpIH1cXG4gICAgICAgICkpXFxuICAgIClcXG5cXG5cXG4gIChkZWZ1biBjcmVkaXQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQ3JlZGl0IEFNT1VOVCB0byBBQ0NPVU5UIGJhbGFuY2VcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKSBcXFwiY3JlZGl0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KSlcXG4gICAgKHdpdGgtZGVmYXVsdC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogMC4wLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmQgfVxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UsIFxcXCJndWFyZFxcXCIgOj0gcmV0ZyB9XFxuICAgICAgOyB3ZSBkb24ndCB3YW50IHRvIG92ZXJ3cml0ZSBhbiBleGlzdGluZyBndWFyZCB3aXRoIHRoZSB1c2VyLXN1cHBsaWVkIG9uZVxcbiAgICAgIChlbmZvcmNlICg9IHJldGcgZ3VhcmQpXFxuICAgICAgICBcXFwiYWNjb3VudCBndWFyZHMgZG8gbm90IG1hdGNoXFxcIilcXG5cXG4gICAgICAod3JpdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgrIGJhbGFuY2UgYW1vdW50KVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiICAgOiByZXRnXFxuICAgICAgICB9KVxcbiAgICAgICkpXFxuXFxuXFxuICAoZGVmc2NoZW1hIGNyb3NzY2hhaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlNjaGVtYSBmb3IgeWllbGRlZCB2YWx1ZSBpbiBjcm9zcy1jaGFpbiB0cmFuc2ZlcnNcXFwiXFxuICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICBhbW91bnQ6ZGVjaW1hbClcXG5cXG4gIChkZWZwYWN0IHRyYW5zZmVyLWNyb3NzY2hhaW46c3RyaW5nXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyLWd1YXJkOmd1YXJkXFxuICAgICAgdGFyZ2V0LWNoYWluOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXBcXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCByZWNlaXZlcilcXG5cXG4gICAgICAgIChlbmZvcmNlICghPSBcXFwiXFxcIiB0YXJnZXQtY2hhaW4pIFxcXCJlbXB0eSB0YXJnZXQtY2hhaW5cXFwiKVxcbiAgICAgICAgKGVuZm9yY2UgKCE9IChhdCAnY2hhaW4taWQgKGNoYWluLWRhdGEpKSB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgIFxcXCJjYW5ub3QgcnVuIGNyb3NzLWNoYWluIHRyYW5zZmVycyB0byB0aGUgc2FtZSBjaGFpblxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgICAgICBcXFwidHJhbnNmZXIgcXVhbnRpdHkgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgICAgIDs7IHN0ZXAgMSAtIGRlYml0IGRlbGV0ZS1hY2NvdW50IG9uIGN1cnJlbnQgY2hhaW5cXG4gICAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcblxcbiAgICAgICAgKGxldFxcbiAgICAgICAgICAoKGNyb3NzY2hhaW4tZGV0YWlsczpvYmplY3R7Y3Jvc3NjaGFpbi1zY2hlbWF9XFxuICAgICAgICAgICAgeyBcXFwicmVjZWl2ZXJcXFwiIDogcmVjZWl2ZXJcXG4gICAgICAgICAgICAsIFxcXCJyZWNlaXZlci1ndWFyZFxcXCIgOiByZWNlaXZlci1ndWFyZFxcbiAgICAgICAgICAgICwgXFxcImFtb3VudFxcXCIgOiBhbW91bnRcXG4gICAgICAgICAgICB9KSlcXG4gICAgICAgICAgKHlpZWxkIGNyb3NzY2hhaW4tZGV0YWlscyB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgICkpKVxcblxcbiAgICAoc3RlcFxcbiAgICAgIChyZXN1bWVcXG4gICAgICAgIHsgXFxcInJlY2VpdmVyXFxcIiA6PSByZWNlaXZlclxcbiAgICAgICAgLCBcXFwicmVjZWl2ZXItZ3VhcmRcXFwiIDo9IHJlY2VpdmVyLWd1YXJkXFxuICAgICAgICAsIFxcXCJhbW91bnRcXFwiIDo9IGFtb3VudFxcbiAgICAgICAgfVxcblxcbiAgICAgICAgOzsgc3RlcCAyIC0gY3JlZGl0IGNyZWF0ZSBhY2NvdW50IG9uIHRhcmdldCBjaGFpblxcbiAgICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHJlY2VpdmVyKVxcbiAgICAgICAgICAoY3JlZGl0IHJlY2VpdmVyIHJlY2VpdmVyLWd1YXJkIGFtb3VudCkpXFxuICAgICAgICApKVxcbiAgICApXFxuXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvaW4gYWxsb2NhdGlvbnNcXG5cXG4gIChkZWZzY2hlbWEgYWxsb2NhdGlvbi1zY2hlbWFcXG4gICAgQGRvYyBcXFwiR2VuZXNpcyBhbGxvY2F0aW9uIHJlZ2lzdHJ5XFxcIlxcbiAgICA7QG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBkYXRlOnRpbWVcXG4gICAgZ3VhcmQ6Z3VhcmRcXG4gICAgcmVkZWVtZWQ6Ym9vbClcXG5cXG4gIChkZWZ0YWJsZSBhbGxvY2F0aW9uLXRhYmxlOnthbGxvY2F0aW9uLXNjaGVtYX0pXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFsbG9jYXRpb24tYWNjb3VudFxcbiAgICAoIGFjY291bnQ6c3RyaW5nXFxuICAgICAgZGF0ZTp0aW1lXFxuICAgICAga2V5c2V0LXJlZjpzdHJpbmdcXG4gICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICApXFxuXFxuICAgIEBkb2MgXFxcIkFkZCBhbiBlbnRyeSB0byB0aGUgY29pbiBhbGxvY2F0aW9uIHRhYmxlLiBUaGlzIGZ1bmN0aW9uIFxcXFxcXG4gICAgICAgICBcXFxcYWxzbyBjcmVhdGVzIGEgY29ycmVzcG9uZGluZyBlbXB0eSBjb2luIGNvbnRyYWN0IGFjY291bnQgXFxcXFxcbiAgICAgICAgIFxcXFxvZiB0aGUgc2FtZSBuYW1lIGFuZCBndWFyZC4gUmVxdWlyZXMgR0VORVNJUyBjYXBhYmlsaXR5LiBcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHRU5FU0lTKSlcXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG4gICAgKGVuZm9yY2UgKD49IGFtb3VudCAwLjApXFxuICAgICAgXFxcImFsbG9jYXRpb24gYW1vdW50IG11c3QgYmUgbm9uLW5lZ2F0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChsZXRcXG4gICAgICAoKGd1YXJkOmd1YXJkIChrZXlzZXQtcmVmLWd1YXJkIGtleXNldC1yZWYpKSlcXG5cXG4gICAgICAoY3JlYXRlLWFjY291bnQgYWNjb3VudCBndWFyZClcXG5cXG4gICAgICAoaW5zZXJ0IGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiBhbW91bnRcXG4gICAgICAgICwgXFxcImRhdGVcXFwiIDogZGF0ZVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmRcXG4gICAgICAgICwgXFxcInJlZGVlbWVkXFxcIiA6IGZhbHNlXFxuICAgICAgICB9KSkpXFxuXFxuICAoZGVmdW4gcmVsZWFzZS1hbGxvY2F0aW9uXFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcblxcbiAgICBAZG9jIFxcXCJSZWxlYXNlIGZ1bmRzIGFzc29jaWF0ZWQgd2l0aCBhbGxvY2F0aW9uIEFDQ09VTlQgaW50byBtYWluIGxlZGdlci4gICBcXFxcXFxuICAgICAgICAgXFxcXEFDQ09VTlQgbXVzdCBhbHJlYWR5IGV4aXN0IGluIG1haW4gbGVkZ2VyLiBBbGxvY2F0aW9uIGlzIGRlYWN0aXZhdGVkIFxcXFxcXG4gICAgICAgICBcXFxcYWZ0ZXIgcmVsZWFzZS5cXFwiXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAod2l0aC1yZWFkIGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2VcXG4gICAgICAsIFxcXCJkYXRlXFxcIiA6PSByZWxlYXNlLXRpbWVcXG4gICAgICAsIFxcXCJyZWRlZW1lZFxcXCIgOj0gcmVkZWVtZWRcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgOj0gZ3VhcmRcXG4gICAgICB9XFxuXFxuICAgICAgKGxldCAoKGN1cnItdGltZTp0aW1lIChhdCAnYmxvY2stdGltZSAoY2hhaW4tZGF0YSkpKSlcXG5cXG4gICAgICAgIChlbmZvcmNlIChub3QgcmVkZWVtZWQpXFxuICAgICAgICAgIFxcXCJhbGxvY2F0aW9uIGZ1bmRzIGhhdmUgYWxyZWFkeSBiZWVuIHJlZGVlbWVkXFxcIilcXG5cXG4gICAgICAgIChlbmZvcmNlXFxuICAgICAgICAgICg-PSBjdXJyLXRpbWUgcmVsZWFzZS10aW1lKVxcbiAgICAgICAgICAoZm9ybWF0IFxcXCJmdW5kcyBsb2NrZWQgdW50aWwge30uIGN1cnJlbnQgdGltZToge31cXFwiIFtyZWxlYXNlLXRpbWUgY3Vyci10aW1lXSkpXFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG5cXG4gICAgICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgICAgICAoY3JlZGl0IGFjY291bnQgZ3VhcmQgYmFsYW5jZSlcXG5cXG4gICAgICAgICAgKHVwZGF0ZSBhbGxvY2F0aW9uLXRhYmxlIGFjY291bnRcXG4gICAgICAgICAgICB7IFxcXCJyZWRlZW1lZFxcXCIgOiB0cnVlXFxuICAgICAgICAgICAgLCBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAgICAgICB9KVxcblxcbiAgICAgICAgICBcXFwiQWxsb2NhdGlvbiBzdWNjZXNzZnVsbHkgcmVsZWFzZWQgdG8gbWFpbiBsZWRnZXJcXFwiKVxcbiAgICApKSlcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJjb2luLWNvbnRyYWN0LXYyXCJ9In0" , - "eyJoYXNoIjoic1dNcmcxeUdCSDRnSWRnc2ZKV2VIN2l6MHc4d0gzdGphQWktRXpQSmlRNCIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihjb2luLnJlbWVkaWF0ZSBcXFwic2VuZGVyMDdcXFwiIDEzMzcuNylcXG4oY29pbi5yZW1lZGlhdGUgXFxcInNlbmRlcjA5XFxcIiAxMzM3LjkpXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJkZXZuZXQtcmVtZWRpYXRpb25zXCJ9In0" + "eyJoYXNoIjoiS1BleXNfYndLeHpGV1M4cEdrWVg0QmZSWkh6MXhiVm43MkVTSk9PRGs0WSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihjb2luLnJlbWVkaWF0ZSBcXFwic2VuZGVyMDdcXFwiIDEzMzcuNylcXG4oY29pbi5yZW1lZGlhdGUgXFxcInNlbmRlcjA5XFxcIiAxMzM3LjkpXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJkZXZuZXQtb3RoZXItcmVtZWRpYXRpb25zXCJ9In0" ] diff --git a/src/Chainweb/Pact/Transactions/OtherTransactions.hs b/src/Chainweb/Pact/Transactions/OtherTransactions.hs index e3714295da..2da41ed596 100644 --- a/src/Chainweb/Pact/Transactions/OtherTransactions.hs +++ b/src/Chainweb/Pact/Transactions/OtherTransactions.hs @@ -17,6 +17,4 @@ transactions = "eyJoYXNoIjoiMDVCdGo3ZUJaQlc3by1TYUxvVmhBaWNNVVBaVUJiRzZRVDhfTEFrQ3hIcyIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihpbnRlcmZhY2UgZnVuZ2libGUtdjJcXG5cXG4gIFxcXCIgU3RhbmRhcmQgZm9yIGZ1bmdpYmxlIGNvaW5zIGFuZCB0b2tlbnMgYXMgc3BlY2lmaWVkIGluIEtJUC0wMDAyLiBcXFwiXFxuXFxuICAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICAgOyBTY2hlbWFcXG5cXG4gICAoZGVmc2NoZW1hIGFjY291bnQtZGV0YWlsc1xcbiAgICBAZG9jIFxcXCJTY2hlbWEgZm9yIHJlc3VsdHMgb2YgJ2FjY291bnQnIG9wZXJhdGlvbi5cXFwiXFxuICAgIEBtb2RlbCBbIChpbnZhcmlhbnQgKCE9IFxcXCJcXFwiIHNlbmRlcikpIF1cXG5cXG4gICAgYWNjb3VudDpzdHJpbmdcXG4gICAgYmFsYW5jZTpkZWNpbWFsXFxuICAgIGd1YXJkOmd1YXJkKVxcblxcblxcbiAgIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgIDsgQ2Fwc1xcblxcbiAgIChkZWZjYXAgVFJBTlNGRVI6Ym9vbFxcbiAgICAgKCBzZW5kZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIE1hbmFnZWQgY2FwYWJpbGl0eSBzZWFsaW5nIEFNT1VOVCBmb3IgdHJhbnNmZXIgZnJvbSBTRU5ERVIgdG8gXFxcXFxcbiAgICAgICAgICBcXFxcIFJFQ0VJVkVSLiBQZXJtaXRzIGFueSBudW1iZXIgb2YgdHJhbnNmZXJzIHVwIHRvIEFNT1VOVC5cXFwiXFxuICAgICBAbWFuYWdlZCBhbW91bnQgVFJBTlNGRVItbWdyXFxuICAgICApXFxuXFxuICAgKGRlZnVuIFRSQU5TRkVSLW1ncjpkZWNpbWFsXFxuICAgICAoIG1hbmFnZWQ6ZGVjaW1hbFxcbiAgICAgICByZXF1ZXN0ZWQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIE1hbmFnZXMgVFJBTlNGRVIgQU1PVU5UIGxpbmVhcmx5LCBcXFxcXFxuICAgICAgICAgIFxcXFwgc3VjaCB0aGF0IGEgcmVxdWVzdCBmb3IgMS4wIGFtb3VudCBvbiBhIDMuMCBcXFxcXFxuICAgICAgICAgIFxcXFwgbWFuYWdlZCBxdWFudGl0eSBlbWl0cyB1cGRhdGVkIGFtb3VudCAyLjAuXFxcIlxcbiAgICAgKVxcblxcbiAgIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgIDsgRnVuY3Rpb25hbGl0eVxcblxcblxcbiAgKGRlZnVuIHRyYW5zZmVyOnN0cmluZ1xcbiAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlcjpzdHJpbmdcXG4gICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICApXFxuICAgIEBkb2MgXFxcIiBUcmFuc2ZlciBBTU9VTlQgYmV0d2VlbiBhY2NvdW50cyBTRU5ERVIgYW5kIFJFQ0VJVkVSLiBcXFxcXFxuICAgICAgICAgXFxcXCBGYWlscyBpZiBlaXRoZXIgU0VOREVSIG9yIFJFQ0VJVkVSIGRvZXMgbm90IGV4aXN0LlxcXCJcXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAoIT0gcmVjZWl2ZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICBdXFxuICAgIClcXG5cXG4gICAoZGVmdW4gdHJhbnNmZXItY3JlYXRlOnN0cmluZ1xcbiAgICAgKCBzZW5kZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICAgKVxcbiAgICAgQGRvYyBcXFwiIFRyYW5zZmVyIEFNT1VOVCBiZXR3ZWVuIGFjY291bnRzIFNFTkRFUiBhbmQgUkVDRUlWRVIuIFxcXFxcXG4gICAgICAgICAgXFxcXCBGYWlscyBpZiBTRU5ERVIgZG9lcyBub3QgZXhpc3QuIElmIFJFQ0VJVkVSIGV4aXN0cywgZ3VhcmQgXFxcXFxcbiAgICAgICAgICBcXFxcIG11c3QgbWF0Y2ggZXhpc3RpbmcgdmFsdWUuIElmIFJFQ0VJVkVSIGRvZXMgbm90IGV4aXN0LCBcXFxcXFxuICAgICAgICAgIFxcXFwgUkVDRUlWRVIgYWNjb3VudCBpcyBjcmVhdGVkIHVzaW5nIFJFQ0VJVkVSLUdVQVJELiBcXFxcXFxuICAgICAgICAgIFxcXFwgU3ViamVjdCB0byBtYW5hZ2VtZW50IGJ5IFRSQU5TRkVSIGNhcGFiaWxpdHkuXFxcIlxcbiAgICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSByZWNlaXZlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICAgXVxcbiAgICAgKVxcblxcbiAgIChkZWZwYWN0IHRyYW5zZmVyLWNyb3NzY2hhaW46c3RyaW5nXFxuICAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICAgcmVjZWl2ZXI6c3RyaW5nXFxuICAgICAgIHJlY2VpdmVyLWd1YXJkOmd1YXJkXFxuICAgICAgIHRhcmdldC1jaGFpbjpzdHJpbmdcXG4gICAgICAgYW1vdW50OmRlY2ltYWxcXG4gICAgIClcXG4gICAgIEBkb2MgXFxcIiAyLXN0ZXAgcGFjdCB0byB0cmFuc2ZlciBBTU9VTlQgZnJvbSBTRU5ERVIgb24gY3VycmVudCBjaGFpbiBcXFxcXFxuICAgICAgICAgIFxcXFwgdG8gUkVDRUlWRVIgb24gVEFSR0VULUNIQUlOIHZpYSBTUFYgcHJvb2YuIFxcXFxcXG4gICAgICAgICAgXFxcXCBUQVJHRVQtQ0hBSU4gbXVzdCBiZSBkaWZmZXJlbnQgdGhhbiBjdXJyZW50IGNoYWluIGlkLiBcXFxcXFxuICAgICAgICAgIFxcXFwgRmlyc3Qgc3RlcCBkZWJpdHMgQU1PVU5UIGNvaW5zIGluIFNFTkRFUiBhY2NvdW50IGFuZCB5aWVsZHMgXFxcXFxcbiAgICAgICAgICBcXFxcIFJFQ0VJVkVSLCBSRUNFSVZFUl9HVUFSRCBhbmQgQU1PVU5UIHRvIFRBUkdFVC1DSEFJTi4gXFxcXFxcbiAgICAgICAgICBcXFxcIFNlY29uZCBzdGVwIGNvbnRpbnVhdGlvbiBpcyBzZW50IGludG8gVEFSR0VULUNIQUlOIHdpdGggcHJvb2YgXFxcXFxcbiAgICAgICAgICBcXFxcIG9idGFpbmVkIGZyb20gdGhlIHNwdiAnb3V0cHV0JyBlbmRwb2ludCBvZiBDaGFpbndlYi4gXFxcXFxcbiAgICAgICAgICBcXFxcIFByb29mIGlzIHZhbGlkYXRlZCBhbmQgUkVDRUlWRVIgaXMgY3JlZGl0ZWQgd2l0aCBBTU9VTlQgXFxcXFxcbiAgICAgICAgICBcXFxcIGNyZWF0aW5nIGFjY291bnQgd2l0aCBSRUNFSVZFUl9HVUFSRCBhcyBuZWNlc3NhcnkuXFxcIlxcbiAgICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgXFxcIlxcXCIpKVxcbiAgICAgICAgICAgICAgKHByb3BlcnR5ICghPSByZWNlaXZlciBcXFwiXFxcIikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHNlbmRlciByZWNlaXZlcikpXFxuICAgICAgICAgICAgICAocHJvcGVydHkgKCE9IHRhcmdldC1jaGFpbiBcXFwiXFxcIikpXFxuICAgICAgICAgICAgXVxcbiAgICAgKVxcblxcbiAgIChkZWZ1biBnZXQtYmFsYW5jZTpkZWNpbWFsXFxuICAgICAoIGFjY291bnQ6c3RyaW5nIClcXG4gICAgIFxcXCIgR2V0IGJhbGFuY2UgZm9yIEFDQ09VTlQuIEZhaWxzIGlmIGFjY291bnQgZG9lcyBub3QgZXhpc3QuXFxcIlxcbiAgICAgKVxcblxcbiAgIChkZWZ1biBkZXRhaWxzOm9iamVjdHthY2NvdW50LWRldGFpbHN9XFxuICAgICAoIGFjY291bnQ6IHN0cmluZyApXFxuICAgICBcXFwiIEdldCBhbiBvYmplY3Qgd2l0aCBkZXRhaWxzIG9mIEFDQ09VTlQuIFxcXFxcXG4gICAgIFxcXFwgRmFpbHMgaWYgYWNjb3VudCBkb2VzIG5vdCBleGlzdC5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIHByZWNpc2lvbjppbnRlZ2VyXFxuICAgICAoKVxcbiAgICAgXFxcIlJldHVybiB0aGUgbWF4aW11bSBhbGxvd2VkIGRlY2ltYWwgcHJlY2lzaW9uLlxcXCJcXG4gICAgIClcXG5cXG4gICAoZGVmdW4gZW5mb3JjZS11bml0OmJvb2xcXG4gICAgICggYW1vdW50OmRlY2ltYWwgKVxcbiAgICAgXFxcIiBFbmZvcmNlIG1pbmltdW0gcHJlY2lzaW9uIGFsbG93ZWQgZm9yIHRyYW5zYWN0aW9ucy5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIGNyZWF0ZS1hY2NvdW50OnN0cmluZ1xcbiAgICAgKCBhY2NvdW50OnN0cmluZ1xcbiAgICAgICBndWFyZDpndWFyZFxcbiAgICAgKVxcbiAgICAgXFxcIiBDcmVhdGUgQUNDT1VOVCB3aXRoIDAuMCBiYWxhbmNlLCB3aXRoIEdVQVJEIGNvbnRyb2xsaW5nIGFjY2Vzcy5cXFwiXFxuICAgICApXFxuXFxuICAgKGRlZnVuIHJvdGF0ZTpzdHJpbmdcXG4gICAgICggYWNjb3VudDpzdHJpbmdcXG4gICAgICAgbmV3LWd1YXJkOmd1YXJkXFxuICAgICApXFxuICAgICBcXFwiIFJvdGF0ZSBndWFyZCBmb3IgQUNDT1VOVC4gVHJhbnNhY3Rpb24gaXMgdmFsaWRhdGVkIGFnYWluc3QgXFxcXFxcbiAgICAgXFxcXCBleGlzdGluZyBndWFyZCBiZWZvcmUgaW5zdGFsbGluZyBuZXcgZ3VhcmQuIFxcXCJcXG4gICAgIClcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJmdW5naWJsZS1hc3NldC12MlwifSJ9" , "eyJoYXNoIjoibVZzMjNxNnJyUjZrWDFGX0ItamNCX05hLXdZdmR3dnRwa1cwQVNaZExjRSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihtb2R1bGUgY29pbiBHT1ZFUk5BTkNFXFxuXFxuICBAZG9jIFxcXCInY29pbicgcmVwcmVzZW50cyB0aGUgS2FkZW5hIENvaW4gQ29udHJhY3QuIFRoaXMgY29udHJhY3QgcHJvdmlkZXMgYm90aCB0aGUgXFxcXFxcbiAgXFxcXGJ1eS9yZWRlZW0gZ2FzIHN1cHBvcnQgaW4gdGhlIGZvcm0gb2YgJ2Z1bmQtdHgnLCBhcyB3ZWxsIGFzIHRyYW5zZmVyLCAgICAgICBcXFxcXFxuICBcXFxcY3JlZGl0LCBkZWJpdCwgY29pbmJhc2UsIGFjY291bnQgY3JlYXRpb24gYW5kIHF1ZXJ5LCBhcyB3ZWxsIGFzIFNQViBidXJuICAgIFxcXFxcXG4gIFxcXFxjcmVhdGUuIFRvIGFjY2VzcyB0aGUgY29pbiBjb250cmFjdCwgeW91IG1heSB1c2UgaXRzIGZ1bGx5LXF1YWxpZmllZCBuYW1lLCAgXFxcXFxcbiAgXFxcXG9yIGlzc3VlIHRoZSAnKHVzZSBjb2luKScgY29tbWFuZCBpbiB0aGUgYm9keSBvZiBhIG1vZHVsZSBkZWNsYXJhdGlvbi5cXFwiXFxuXFxuICBAbW9kZWxcXG4gICAgWyAoZGVmcHJvcGVydHkgY29uc2VydmVzLW1hc3NcXG4gICAgICAgICg9IChjb2x1bW4tZGVsdGEgY29pbi10YWJsZSAnYmFsYW5jZSkgMC4wKSlcXG5cXG4gICAgICAoZGVmcHJvcGVydHkgdmFsaWQtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgICAgICAoYW5kXFxuICAgICAgICAgICg-PSAobGVuZ3RoIGFjY291bnQpIDMpXFxuICAgICAgICAgICg8PSAobGVuZ3RoIGFjY291bnQpIDI1NikpKVxcbiAgICBdXFxuXFxuICAoaW1wbGVtZW50cyBmdW5naWJsZS12MilcXG5cXG4gIDsgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cXG4gIDsgU2NoZW1hcyBhbmQgVGFibGVzXFxuXFxuICAoZGVmc2NoZW1hIGNvaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlRoZSBjb2luIGNvbnRyYWN0IHRva2VuIHNjaGVtYVxcXCJcXG4gICAgQG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBndWFyZDpndWFyZClcXG5cXG4gIChkZWZ0YWJsZSBjb2luLXRhYmxlOntjb2luLXNjaGVtYX0pXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENhcGFiaWxpdGllc1xcblxcbiAgKGRlZmNhcCBHT1ZFUk5BTkNFICgpXFxuICAgIChlbmZvcmNlIGZhbHNlIFxcXCJFbmZvcmNlIG5vbi11cGdyYWRlYWJpbGl0eVxcXCIpKVxcblxcbiAgKGRlZmNhcCBHQVMgKClcXG4gICAgXFxcIk1hZ2ljIGNhcGFiaWxpdHkgdG8gcHJvdGVjdCBnYXMgYnV5IGFuZCByZWRlZW1cXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIENPSU5CQVNFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IHRvIHByb3RlY3QgbWluZXIgcmV3YXJkXFxcIlxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBHRU5FU0lTICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGNvbnN0cmFpbmluZyBnZW5lc2lzIHRyYW5zYWN0aW9uc1xcXCJcXG4gICAgdHJ1ZSlcXG5cXG4gIChkZWZjYXAgUkVNRURJQVRFICgpXFxuICAgIFxcXCJNYWdpYyBjYXBhYmlsaXR5IGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnNcXFwiXFxuICAgIHRydWUpXFxuXFxuICAoZGVmY2FwIERFQklUIChzZW5kZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgZGViaXRpbmcgb3BlcmF0aW9uc1xcXCJcXG4gICAgKGVuZm9yY2UtZ3VhcmQgKGF0ICdndWFyZCAocmVhZCBjb2luLXRhYmxlIHNlbmRlcikpKVxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIFxcXCJcXFwiKSBcXFwidmFsaWQgc2VuZGVyXFxcIikpXFxuXFxuICAoZGVmY2FwIENSRURJVCAocmVjZWl2ZXI6c3RyaW5nKVxcbiAgICBcXFwiQ2FwYWJpbGl0eSBmb3IgbWFuYWdpbmcgY3JlZGl0aW5nIG9wZXJhdGlvbnNcXFwiXFxuICAgIChlbmZvcmNlICghPSByZWNlaXZlciBcXFwiXFxcIikgXFxcInZhbGlkIHJlY2VpdmVyXFxcIikpXFxuXFxuICAoZGVmY2FwIFJPVEFURSAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkF1dG9ub21vdXNseSBtYW5hZ2VkIGNhcGFiaWxpdHkgZm9yIGd1YXJkIHJvdGF0aW9uXFxcIlxcbiAgICBAbWFuYWdlZFxcbiAgICB0cnVlKVxcblxcbiAgKGRlZmNhcCBUUkFOU0ZFUjpib29sXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsXFxuICAgIClcXG4gICAgQG1hbmFnZWQgYW1vdW50IFRSQU5TRkVSLW1nclxcbiAgICAoZW5mb3JjZSAoIT0gc2VuZGVyIHJlY2VpdmVyKSBcXFwic2FtZSBzZW5kZXIgYW5kIHJlY2VpdmVyXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApIFxcXCJQb3NpdGl2ZSBhbW91bnRcXFwiKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpKVxcbiAgICAoY29tcG9zZS1jYXBhYmlsaXR5IChDUkVESVQgcmVjZWl2ZXIpKVxcbiAgKVxcblxcbiAgKGRlZnVuIFRSQU5TRkVSLW1ncjpkZWNpbWFsXFxuICAgICggbWFuYWdlZDpkZWNpbWFsXFxuICAgICAgcmVxdWVzdGVkOmRlY2ltYWxcXG4gICAgKVxcblxcbiAgICAobGV0ICgobmV3YmFsICgtIG1hbmFnZWQgcmVxdWVzdGVkKSkpXFxuICAgICAgKGVuZm9yY2UgKD49IG5ld2JhbCAwLjApXFxuICAgICAgICAoZm9ybWF0IFxcXCJUUkFOU0ZFUiBleGNlZWRlZCBmb3IgYmFsYW5jZSB7fVxcXCIgW21hbmFnZWRdKSlcXG4gICAgICBuZXdiYWwpXFxuICApXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvbnN0YW50c1xcblxcbiAgKGRlZmNvbnN0IENPSU5fQ0hBUlNFVCBDSEFSU0VUX0xBVElOMVxcbiAgICBcXFwiVGhlIGRlZmF1bHQgY29pbiBjb250cmFjdCBjaGFyYWN0ZXIgc2V0XFxcIilcXG5cXG4gIChkZWZjb25zdCBNSU5JTVVNX1BSRUNJU0lPTiAxMlxcbiAgICBcXFwiTWluaW11bSBhbGxvd2VkIHByZWNpc2lvbiBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiKVxcblxcbiAgKGRlZmNvbnN0IE1JTklNVU1fQUNDT1VOVF9MRU5HVEggM1xcbiAgICBcXFwiTWluaW11bSBhY2NvdW50IGxlbmd0aCBhZG1pc3NpYmxlIGZvciBjb2luIGFjY291bnRzXFxcIilcXG5cXG4gIChkZWZjb25zdCBNQVhJTVVNX0FDQ09VTlRfTEVOR1RIIDI1NlxcbiAgICBcXFwiTWF4aW11bSBhY2NvdW50IG5hbWUgbGVuZ3RoIGFkbWlzc2libGUgZm9yIGNvaW4gYWNjb3VudHNcXFwiKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBVdGlsaXRpZXNcXG5cXG4gIChkZWZ1biBlbmZvcmNlLXVuaXQ6Ym9vbCAoYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgbWluaW11bSBwcmVjaXNpb24gYWxsb3dlZCBmb3IgY29pbiB0cmFuc2FjdGlvbnNcXFwiXFxuXFxuICAgIChlbmZvcmNlXFxuICAgICAgKD0gKGZsb29yIGFtb3VudCBNSU5JTVVNX1BSRUNJU0lPTilcXG4gICAgICAgICBhbW91bnQpXFxuICAgICAgKGZvcm1hdCBcXFwiQW1vdW50IHZpb2xhdGVzIG1pbmltdW0gcHJlY2lzaW9uOiB7fVxcXCIgW2Ftb3VudF0pKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdmFsaWRhdGUtYWNjb3VudCAoYWNjb3VudDpzdHJpbmcpXFxuICAgIEBkb2MgXFxcIkVuZm9yY2UgdGhhdCBhbiBhY2NvdW50IG5hbWUgY29uZm9ybXMgdG8gdGhlIGNvaW4gY29udHJhY3QgXFxcXFxcbiAgICAgICAgIFxcXFxtaW5pbXVtIGFuZCBtYXhpbXVtIGxlbmd0aCByZXF1aXJlbWVudHMsIGFzIHdlbGwgYXMgdGhlICAgIFxcXFxcXG4gICAgICAgICBcXFxcbGF0aW4tMSBjaGFyYWN0ZXIgc2V0LlxcXCJcXG5cXG4gICAgKGVuZm9yY2VcXG4gICAgICAoaXMtY2hhcnNldCBDT0lOX0NIQVJTRVQgYWNjb3VudClcXG4gICAgICAoZm9ybWF0XFxuICAgICAgICBcXFwiQWNjb3VudCBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBjb2luIGNvbnRyYWN0IGNoYXJzZXQ6IHt9XFxcIlxcbiAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgKGxldCAoKGFjY291bnQtbGVuZ3RoIChsZW5ndGggYWNjb3VudCkpKVxcblxcbiAgICAgIChlbmZvcmNlXFxuICAgICAgICAoPj0gYWNjb3VudC1sZW5ndGggTUlOSU1VTV9BQ0NPVU5UX0xFTkdUSClcXG4gICAgICAgIChmb3JtYXRcXG4gICAgICAgICAgXFxcIkFjY291bnQgbmFtZSBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBtaW4gbGVuZ3RoIHJlcXVpcmVtZW50OiB7fVxcXCJcXG4gICAgICAgICAgW2FjY291bnRdKSlcXG5cXG4gICAgICAoZW5mb3JjZVxcbiAgICAgICAgKDw9IGFjY291bnQtbGVuZ3RoIE1BWElNVU1fQUNDT1VOVF9MRU5HVEgpXFxuICAgICAgICAoZm9ybWF0XFxuICAgICAgICAgIFxcXCJBY2NvdW50IG5hbWUgZG9lcyBub3QgY29uZm9ybSB0byB0aGUgbWF4IGxlbmd0aCByZXF1aXJlbWVudDoge31cXFwiXFxuICAgICAgICAgIFthY2NvdW50XSkpXFxuICAgICAgKVxcbiAgKVxcblxcbiAgOyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbiAgOyBDb2luIENvbnRyYWN0XFxuXFxuICAoZGVmdW4gZ2FzLW9ubHkgKClcXG4gICAgXFxcIlByZWRpY2F0ZSBmb3IgZ2FzLW9ubHkgdXNlciBndWFyZHMuXFxcIlxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKSlcXG5cXG4gIChkZWZ1biBnYXMtZ3VhcmQgKGd1YXJkOmd1YXJkKVxcbiAgICBcXFwiUHJlZGljYXRlIGZvciBnYXMgKyBzaW5nbGUga2V5IHVzZXIgZ3VhcmRzXFxcIlxcbiAgICAoZW5mb3JjZS1vbmVcXG4gICAgICBcXFwiRW5mb3JjZSBlaXRoZXIgdGhlIHByZXNlbmNlIG9mIGEgR0FTIGNhcCBvciBrZXlzZXRcXFwiXFxuICAgICAgWyAoZ2FzLW9ubHkpXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG4gICAgICBdKSlcXG5cXG4gIChkZWZ1biBidXktZ2FzOnN0cmluZyAoc2VuZGVyOnN0cmluZyB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCJUaGlzIGZ1bmN0aW9uIGRlc2NyaWJlcyB0aGUgbWFpbiAnZ2FzIGJ1eScgb3BlcmF0aW9uLiBBdCB0aGlzIHBvaW50IFxcXFxcXG4gICAgXFxcXE1JTkVSIGhhcyBiZWVuIGNob3NlbiBmcm9tIHRoZSBwb29sLCBhbmQgd2lsbCBiZSB2YWxpZGF0ZWQuIFRoZSBTRU5ERVIgICBcXFxcXFxuICAgIFxcXFxvZiB0aGlzIHRyYW5zYWN0aW9uIGhhcyBzcGVjaWZpZWQgYSBnYXMgbGltaXQgTElNSVQgKG1heGltdW0gZ2FzKSBmb3IgICAgXFxcXFxcbiAgICBcXFxcdGhlIHRyYW5zYWN0aW9uLCBhbmQgdGhlIHByaWNlIGlzIHRoZSBzcG90IHByaWNlIG9mIGdhcyBhdCB0aGF0IHRpbWUuICAgIFxcXFxcXG4gICAgXFxcXFRoZSBnYXMgYnV5IHdpbGwgYmUgZXhlY3V0ZWQgcHJpb3IgdG8gZXhlY3V0aW5nIFNFTkRFUidzIGNvZGUuXFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCB0b3RhbClcXG4gICAgKGVuZm9yY2UgKD4gdG90YWwgMC4wKSBcXFwiZ2FzIHN1cHBseSBtdXN0IGJlIGEgcG9zaXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHQVMpKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuICAgICAgKGRlYml0IHNlbmRlciB0b3RhbCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZWRlZW0tZ2FzOnN0cmluZyAobWluZXI6c3RyaW5nIG1pbmVyLWd1YXJkOmd1YXJkIHNlbmRlcjpzdHJpbmcgdG90YWw6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiVGhpcyBmdW5jdGlvbiBkZXNjcmliZXMgdGhlIG1haW4gJ3JlZGVlbSBnYXMnIG9wZXJhdGlvbi4gQXQgdGhpcyAgICBcXFxcXFxuICAgIFxcXFxwb2ludCwgdGhlIFNFTkRFUidzIHRyYW5zYWN0aW9uIGhhcyBiZWVuIGV4ZWN1dGVkLCBhbmQgdGhlIGdhcyB0aGF0ICAgICAgXFxcXFxcbiAgICBcXFxcd2FzIGNoYXJnZWQgaGFzIGJlZW4gY2FsY3VsYXRlZC4gTUlORVIgd2lsbCBiZSBjcmVkaXRlZCB0aGUgZ2FzIGNvc3QsICAgIFxcXFxcXG4gICAgXFxcXGFuZCBTRU5ERVIgd2lsbCByZWNlaXZlIHRoZSByZW1haW5kZXIgdXAgdG8gdGhlIGxpbWl0XFxcIlxcblxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKD4gdG90YWwgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHNlbmRlcikpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBtaW5lcikpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHNlbmRlcilcXG4gICAgKHZhbGlkYXRlLWFjY291bnQgbWluZXIpXFxuICAgIChlbmZvcmNlLXVuaXQgdG90YWwpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKEdBUykpXFxuICAgIChsZXQqXFxuICAgICAgKChmZWUgKHJlYWQtZGVjaW1hbCBcXFwiZmVlXFxcIikpXFxuICAgICAgIChyZWZ1bmQgKC0gdG90YWwgZmVlKSkpXFxuXFxuICAgICAgKGVuZm9yY2UtdW5pdCBmZWUpXFxuICAgICAgKGVuZm9yY2UgKD49IGZlZSAwLjApXFxuICAgICAgICBcXFwiZmVlIG11c3QgYmUgYSBub24tbmVnYXRpdmUgcXVhbnRpdHlcXFwiKVxcblxcbiAgICAgIChlbmZvcmNlICg-PSByZWZ1bmQgMC4wKVxcbiAgICAgICAgXFxcInJlZnVuZCBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIHF1YW50aXR5XFxcIilcXG5cXG4gICAgICAgIDsgZGlyZWN0bHkgdXBkYXRlIGluc3RlYWQgb2YgY3JlZGl0XFxuICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHNlbmRlcilcXG4gICAgICAgIChpZiAoPiByZWZ1bmQgMC4wKVxcbiAgICAgICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgc2VuZGVyXFxuICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOj0gYmFsYW5jZSB9XFxuICAgICAgICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIHNlbmRlclxcbiAgICAgICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCI6ICgrIGJhbGFuY2UgcmVmdW5kKSB9KSlcXG5cXG4gICAgICAgICAgXFxcIm5vb3BcXFwiKSlcXG5cXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChDUkVESVQgbWluZXIpXFxuICAgICAgICAoaWYgKD4gZmVlIDAuMClcXG4gICAgICAgICAgKGNyZWRpdCBtaW5lciBtaW5lci1ndWFyZCBmZWUpXFxuICAgICAgICAgIFxcXCJub29wXFxcIikpXFxuICAgICAgKVxcblxcbiAgICApXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFjY291bnQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZClcXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKSBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChpbnNlcnQgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgICA6IGd1YXJkXFxuICAgICAgfSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGdldC1iYWxhbmNlOmRlY2ltYWwgKGFjY291bnQ6c3RyaW5nKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcbiAgICAgIGJhbGFuY2VcXG4gICAgICApXFxuICAgIClcXG5cXG4gIChkZWZ1biBkZXRhaWxzOm9iamVjdHtmdW5naWJsZS12Mi5hY2NvdW50LWRldGFpbHN9XFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIiA6PSBnIH1cXG4gICAgICB7IFxcXCJhY2NvdW50XFxcIiA6IGFjY291bnRcXG4gICAgICAsIFxcXCJiYWxhbmNlXFxcIiA6IGJhbFxcbiAgICAgICwgXFxcImd1YXJkXFxcIjogZyB9KVxcbiAgICApXFxuXFxuICAoZGVmdW4gcm90YXRlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgbmV3LWd1YXJkOmd1YXJkKVxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChST1RBVEUgYWNjb3VudClcXG4gICAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IG9sZC1ndWFyZCB9XFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBvbGQtZ3VhcmQpXFxuXFxuICAgICAgICAodXBkYXRlIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgICAgICB7IFxcXCJndWFyZFxcXCIgOiBuZXctZ3VhcmQgfVxcbiAgICAgICAgICApKSlcXG4gICAgKVxcblxcblxcbiAgKGRlZnVuIHByZWNpc2lvbjppbnRlZ2VyXFxuICAgICgpXFxuICAgIE1JTklNVU1fUFJFQ0lTSU9OKVxcblxcbiAgKGRlZnVuIHRyYW5zZmVyOnN0cmluZyAoc2VuZGVyOnN0cmluZyByZWNlaXZlcjpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcylcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICghPSBzZW5kZXIgcmVjZWl2ZXIpKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgICh3aXRoLXJlYWQgY29pbi10YWJsZSByZWNlaXZlclxcbiAgICAgICAgeyBcXFwiZ3VhcmRcXFwiIDo9IGcgfVxcblxcbiAgICAgICAgKGNyZWRpdCByZWNlaXZlciBnIGFtb3VudCkpXFxuICAgICAgKVxcbiAgICApXFxuXFxuICAoZGVmdW4gdHJhbnNmZXItY3JlYXRlOnN0cmluZ1xcbiAgICAoIHNlbmRlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlcjpzdHJpbmdcXG4gICAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5IGNvbnNlcnZlcy1tYXNzKSBdXFxuXFxuICAgIChlbmZvcmNlICghPSBzZW5kZXIgcmVjZWl2ZXIpXFxuICAgICAgXFxcInNlbmRlciBjYW5ub3QgYmUgdGhlIHJlY2VpdmVyIG9mIGEgdHJhbnNmZXJcXFwiKVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IHJlY2VpdmVyKVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgIFxcXCJ0cmFuc2ZlciBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAod2l0aC1jYXBhYmlsaXR5IChUUkFOU0ZFUiBzZW5kZXIgcmVjZWl2ZXIgYW1vdW50KVxcbiAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcbiAgICAgIChjcmVkaXQgcmVjZWl2ZXIgcmVjZWl2ZXItZ3VhcmQgYW1vdW50KSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGNvaW5iYXNlOnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYWNjb3VudC1ndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiSW50ZXJuYWwgZnVuY3Rpb24gZm9yIHRoZSBpbml0aWFsIGNyZWF0aW9uIG9mIGNvaW5zLiAgVGhpcyBmdW5jdGlvbiBcXFxcXFxuICAgIFxcXFxjYW5ub3QgYmUgdXNlZCBvdXRzaWRlIG9mIHRoZSBjb2luIGNvbnRyYWN0LlxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKD4gYW1vdW50IDAuMCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuICAgIChlbmZvcmNlLXVuaXQgYW1vdW50KVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChDT0lOQkFTRSkpXFxuICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgIChjcmVkaXQgYWNjb3VudCBhY2NvdW50LWd1YXJkIGFtb3VudCkpXFxuICAgIClcXG5cXG4gIChkZWZ1biByZW1lZGlhdGU6c3RyaW5nIChhY2NvdW50OnN0cmluZyBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQWxsb3dzIGZvciByZW1lZGlhdGlvbiB0cmFuc2FjdGlvbnMuIFRoaXMgZnVuY3Rpb24gXFxcXFxcbiAgICAgICAgIFxcXFxpcyBwcm90ZWN0ZWQgYnkgdGhlIFJFTUVESUFURSBjYXBhYmlsaXR5XFxcIlxcbiAgICBAbW9kZWwgWyAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICAgIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG5cXG4gICAgKGVuZm9yY2UgKD4gYW1vdW50IDAuMClcXG4gICAgICBcXFwiUmVtZWRpYXRpb24gYW1vdW50IG11c3QgYmUgcG9zaXRpdmVcXFwiKVxcblxcbiAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgKHJlcXVpcmUtY2FwYWJpbGl0eSAoUkVNRURJQVRFKSlcXG4gICAgKHdpdGgtcmVhZCBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6PSBiYWxhbmNlIH1cXG5cXG4gICAgICAoZW5mb3JjZSAoPD0gYW1vdW50IGJhbGFuY2UpIFxcXCJJbnN1ZmZpY2llbnQgZnVuZHNcXFwiKVxcblxcbiAgICAgICh1cGRhdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgtIGJhbGFuY2UgYW1vdW50KSB9XFxuICAgICAgICApKVxcbiAgICApXFxuXFxuICAoZGVmcGFjdCBmdW5kLXR4IChzZW5kZXI6c3RyaW5nIG1pbmVyOnN0cmluZyBtaW5lci1ndWFyZDpndWFyZCB0b3RhbDpkZWNpbWFsKVxcbiAgICBAZG9jIFxcXCInZnVuZC10eCcgaXMgYSBzcGVjaWFsIHBhY3QgdG8gZnVuZCBhIHRyYW5zYWN0aW9uIGluIHR3byBzdGVwcywgICAgIFxcXFxcXG4gICAgXFxcXHdpdGggdGhlIGFjdHVhbCB0cmFuc2FjdGlvbiB0cmFuc3BpcmluZyBpbiB0aGUgbWlkZGxlOiAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXFxcXFxcbiAgICBcXFxcICAxKSBBIGJ1eWluZyBwaGFzZSwgZGViaXRpbmcgdGhlIHNlbmRlciBmb3IgdG90YWwgZ2FzIGFuZCBmZWUsIHlpZWxkaW5nIFxcXFxcXG4gICAgXFxcXCAgICAgVFhfTUFYX0NIQVJHRS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcXFxcXFxuICAgIFxcXFwgIDIpIEEgc2V0dGxlbWVudCBwaGFzZSwgcmVzdW1pbmcgVFhfTUFYX0NIQVJHRSwgYW5kIGFsbG9jYXRpbmcgdG8gdGhlICAgXFxcXFxcbiAgICBcXFxcICAgICBjb2luYmFzZSBhY2NvdW50IGZvciB1c2VkIGdhcyBhbmQgZmVlLCBhbmQgc2VuZGVyIGFjY291bnQgZm9yIGJhbC0gIFxcXFxcXG4gICAgXFxcXCAgICAgYW5jZSAodW51c2VkIGdhcywgaWYgYW55KS5cXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiB0b3RhbCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IG1pbmVyKSlcXG4gICAgICAgICAgICAgOyhwcm9wZXJ0eSBjb25zZXJ2ZXMtbWFzcykgbm90IHN1cHBvcnRlZCB5ZXRcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXAgKGJ1eS1nYXMgc2VuZGVyIHRvdGFsKSlcXG4gICAgKHN0ZXAgKHJlZGVlbS1nYXMgbWluZXIgbWluZXItZ3VhcmQgc2VuZGVyIHRvdGFsKSlcXG4gICAgKVxcblxcbiAgKGRlZnVuIGRlYml0OnN0cmluZyAoYWNjb3VudDpzdHJpbmcgYW1vdW50OmRlY2ltYWwpXFxuICAgIEBkb2MgXFxcIkRlYml0IEFNT1VOVCBmcm9tIEFDQ09VTlQgYmFsYW5jZVxcXCJcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgYWNjb3VudCkpXFxuICAgICAgICAgICBdXFxuXFxuICAgICh2YWxpZGF0ZS1hY2NvdW50IGFjY291bnQpXFxuXFxuICAgIChlbmZvcmNlICg-IGFtb3VudCAwLjApXFxuICAgICAgXFxcImRlYml0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKERFQklUIGFjY291bnQpKVxcbiAgICAod2l0aC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UgfVxcblxcbiAgICAgIChlbmZvcmNlICg8PSBhbW91bnQgYmFsYW5jZSkgXFxcIkluc3VmZmljaWVudCBmdW5kc1xcXCIpXFxuXFxuICAgICAgKHVwZGF0ZSBjb2luLXRhYmxlIGFjY291bnRcXG4gICAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogKC0gYmFsYW5jZSBhbW91bnQpIH1cXG4gICAgICAgICkpXFxuICAgIClcXG5cXG5cXG4gIChkZWZ1biBjcmVkaXQ6c3RyaW5nIChhY2NvdW50OnN0cmluZyBndWFyZDpndWFyZCBhbW91bnQ6ZGVjaW1hbClcXG4gICAgQGRvYyBcXFwiQ3JlZGl0IEFNT1VOVCB0byBBQ0NPVU5UIGJhbGFuY2VcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAoPiBhbW91bnQgMC4wKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IGFjY291bnQpKVxcbiAgICAgICAgICAgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKSBcXFwiY3JlZGl0IGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIilcXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChyZXF1aXJlLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KSlcXG4gICAgKHdpdGgtZGVmYXVsdC1yZWFkIGNvaW4tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDogMC4wLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmQgfVxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2UsIFxcXCJndWFyZFxcXCIgOj0gcmV0ZyB9XFxuICAgICAgOyB3ZSBkb24ndCB3YW50IHRvIG92ZXJ3cml0ZSBhbiBleGlzdGluZyBndWFyZCB3aXRoIHRoZSB1c2VyLXN1cHBsaWVkIG9uZVxcbiAgICAgIChlbmZvcmNlICg9IHJldGcgZ3VhcmQpXFxuICAgICAgICBcXFwiYWNjb3VudCBndWFyZHMgZG8gbm90IG1hdGNoXFxcIilcXG5cXG4gICAgICAod3JpdGUgY29pbi10YWJsZSBhY2NvdW50XFxuICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIiA6ICgrIGJhbGFuY2UgYW1vdW50KVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiICAgOiByZXRnXFxuICAgICAgICB9KVxcbiAgICAgICkpXFxuXFxuXFxuICAoZGVmc2NoZW1hIGNyb3NzY2hhaW4tc2NoZW1hXFxuICAgIEBkb2MgXFxcIlNjaGVtYSBmb3IgeWllbGRlZCB2YWx1ZSBpbiBjcm9zcy1jaGFpbiB0cmFuc2ZlcnNcXFwiXFxuICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICByZWNlaXZlci1ndWFyZDpndWFyZFxcbiAgICBhbW91bnQ6ZGVjaW1hbClcXG5cXG4gIChkZWZwYWN0IHRyYW5zZmVyLWNyb3NzY2hhaW46c3RyaW5nXFxuICAgICggc2VuZGVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyOnN0cmluZ1xcbiAgICAgIHJlY2VpdmVyLWd1YXJkOmd1YXJkXFxuICAgICAgdGFyZ2V0LWNoYWluOnN0cmluZ1xcbiAgICAgIGFtb3VudDpkZWNpbWFsIClcXG5cXG4gICAgQG1vZGVsIFsgKHByb3BlcnR5ICg-IGFtb3VudCAwLjApKVxcbiAgICAgICAgICAgICAocHJvcGVydHkgKHZhbGlkLWFjY291bnQgc2VuZGVyKSlcXG4gICAgICAgICAgICAgKHByb3BlcnR5ICh2YWxpZC1hY2NvdW50IHJlY2VpdmVyKSlcXG4gICAgICAgICAgIF1cXG5cXG4gICAgKHN0ZXBcXG4gICAgICAod2l0aC1jYXBhYmlsaXR5IChERUJJVCBzZW5kZXIpXFxuXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCBzZW5kZXIpXFxuICAgICAgICAodmFsaWRhdGUtYWNjb3VudCByZWNlaXZlcilcXG5cXG4gICAgICAgIChlbmZvcmNlICghPSBcXFwiXFxcIiB0YXJnZXQtY2hhaW4pIFxcXCJlbXB0eSB0YXJnZXQtY2hhaW5cXFwiKVxcbiAgICAgICAgKGVuZm9yY2UgKCE9IChhdCAnY2hhaW4taWQgKGNoYWluLWRhdGEpKSB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgIFxcXCJjYW5ub3QgcnVuIGNyb3NzLWNoYWluIHRyYW5zZmVycyB0byB0aGUgc2FtZSBjaGFpblxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZSAoPiBhbW91bnQgMC4wKVxcbiAgICAgICAgICBcXFwidHJhbnNmZXIgcXVhbnRpdHkgbXVzdCBiZSBwb3NpdGl2ZVxcXCIpXFxuXFxuICAgICAgICAoZW5mb3JjZS11bml0IGFtb3VudClcXG5cXG4gICAgICAgIDs7IHN0ZXAgMSAtIGRlYml0IGRlbGV0ZS1hY2NvdW50IG9uIGN1cnJlbnQgY2hhaW5cXG4gICAgICAgIChkZWJpdCBzZW5kZXIgYW1vdW50KVxcblxcbiAgICAgICAgKGxldFxcbiAgICAgICAgICAoKGNyb3NzY2hhaW4tZGV0YWlsczpvYmplY3R7Y3Jvc3NjaGFpbi1zY2hlbWF9XFxuICAgICAgICAgICAgeyBcXFwicmVjZWl2ZXJcXFwiIDogcmVjZWl2ZXJcXG4gICAgICAgICAgICAsIFxcXCJyZWNlaXZlci1ndWFyZFxcXCIgOiByZWNlaXZlci1ndWFyZFxcbiAgICAgICAgICAgICwgXFxcImFtb3VudFxcXCIgOiBhbW91bnRcXG4gICAgICAgICAgICB9KSlcXG4gICAgICAgICAgKHlpZWxkIGNyb3NzY2hhaW4tZGV0YWlscyB0YXJnZXQtY2hhaW4pXFxuICAgICAgICAgICkpKVxcblxcbiAgICAoc3RlcFxcbiAgICAgIChyZXN1bWVcXG4gICAgICAgIHsgXFxcInJlY2VpdmVyXFxcIiA6PSByZWNlaXZlclxcbiAgICAgICAgLCBcXFwicmVjZWl2ZXItZ3VhcmRcXFwiIDo9IHJlY2VpdmVyLWd1YXJkXFxuICAgICAgICAsIFxcXCJhbW91bnRcXFwiIDo9IGFtb3VudFxcbiAgICAgICAgfVxcblxcbiAgICAgICAgOzsgc3RlcCAyIC0gY3JlZGl0IGNyZWF0ZSBhY2NvdW50IG9uIHRhcmdldCBjaGFpblxcbiAgICAgICAgKHdpdGgtY2FwYWJpbGl0eSAoQ1JFRElUIHJlY2VpdmVyKVxcbiAgICAgICAgICAoY3JlZGl0IHJlY2VpdmVyIHJlY2VpdmVyLWd1YXJkIGFtb3VudCkpXFxuICAgICAgICApKVxcbiAgICApXFxuXFxuXFxuICA7IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXFxuICA7IENvaW4gYWxsb2NhdGlvbnNcXG5cXG4gIChkZWZzY2hlbWEgYWxsb2NhdGlvbi1zY2hlbWFcXG4gICAgQGRvYyBcXFwiR2VuZXNpcyBhbGxvY2F0aW9uIHJlZ2lzdHJ5XFxcIlxcbiAgICA7QG1vZGVsIFsgKGludmFyaWFudCAoPj0gYmFsYW5jZSAwLjApKSBdXFxuXFxuICAgIGJhbGFuY2U6ZGVjaW1hbFxcbiAgICBkYXRlOnRpbWVcXG4gICAgZ3VhcmQ6Z3VhcmRcXG4gICAgcmVkZWVtZWQ6Ym9vbClcXG5cXG4gIChkZWZ0YWJsZSBhbGxvY2F0aW9uLXRhYmxlOnthbGxvY2F0aW9uLXNjaGVtYX0pXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFsbG9jYXRpb24tYWNjb3VudFxcbiAgICAoIGFjY291bnQ6c3RyaW5nXFxuICAgICAgZGF0ZTp0aW1lXFxuICAgICAga2V5c2V0LXJlZjpzdHJpbmdcXG4gICAgICBhbW91bnQ6ZGVjaW1hbFxcbiAgICApXFxuXFxuICAgIEBkb2MgXFxcIkFkZCBhbiBlbnRyeSB0byB0aGUgY29pbiBhbGxvY2F0aW9uIHRhYmxlLiBUaGlzIGZ1bmN0aW9uIFxcXFxcXG4gICAgICAgICBcXFxcYWxzbyBjcmVhdGVzIGEgY29ycmVzcG9uZGluZyBlbXB0eSBjb2luIGNvbnRyYWN0IGFjY291bnQgXFxcXFxcbiAgICAgICAgIFxcXFxvZiB0aGUgc2FtZSBuYW1lIGFuZCBndWFyZC4gUmVxdWlyZXMgR0VORVNJUyBjYXBhYmlsaXR5LiBcXFwiXFxuXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAocmVxdWlyZS1jYXBhYmlsaXR5IChHRU5FU0lTKSlcXG5cXG4gICAgKHZhbGlkYXRlLWFjY291bnQgYWNjb3VudClcXG4gICAgKGVuZm9yY2UgKD49IGFtb3VudCAwLjApXFxuICAgICAgXFxcImFsbG9jYXRpb24gYW1vdW50IG11c3QgYmUgbm9uLW5lZ2F0aXZlXFxcIilcXG5cXG4gICAgKGVuZm9yY2UtdW5pdCBhbW91bnQpXFxuXFxuICAgIChsZXRcXG4gICAgICAoKGd1YXJkOmd1YXJkIChrZXlzZXQtcmVmLWd1YXJkIGtleXNldC1yZWYpKSlcXG5cXG4gICAgICAoY3JlYXRlLWFjY291bnQgYWNjb3VudCBndWFyZClcXG5cXG4gICAgICAoaW5zZXJ0IGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCIgOiBhbW91bnRcXG4gICAgICAgICwgXFxcImRhdGVcXFwiIDogZGF0ZVxcbiAgICAgICAgLCBcXFwiZ3VhcmRcXFwiIDogZ3VhcmRcXG4gICAgICAgICwgXFxcInJlZGVlbWVkXFxcIiA6IGZhbHNlXFxuICAgICAgICB9KSkpXFxuXFxuICAoZGVmdW4gcmVsZWFzZS1hbGxvY2F0aW9uXFxuICAgICggYWNjb3VudDpzdHJpbmcgKVxcblxcbiAgICBAZG9jIFxcXCJSZWxlYXNlIGZ1bmRzIGFzc29jaWF0ZWQgd2l0aCBhbGxvY2F0aW9uIEFDQ09VTlQgaW50byBtYWluIGxlZGdlci4gICBcXFxcXFxuICAgICAgICAgXFxcXEFDQ09VTlQgbXVzdCBhbHJlYWR5IGV4aXN0IGluIG1haW4gbGVkZ2VyLiBBbGxvY2F0aW9uIGlzIGRlYWN0aXZhdGVkIFxcXFxcXG4gICAgICAgICBcXFxcYWZ0ZXIgcmVsZWFzZS5cXFwiXFxuICAgIEBtb2RlbCBbIChwcm9wZXJ0eSAodmFsaWQtYWNjb3VudCBhY2NvdW50KSkgXVxcblxcbiAgICAodmFsaWRhdGUtYWNjb3VudCBhY2NvdW50KVxcblxcbiAgICAod2l0aC1yZWFkIGFsbG9jYXRpb24tdGFibGUgYWNjb3VudFxcbiAgICAgIHsgXFxcImJhbGFuY2VcXFwiIDo9IGJhbGFuY2VcXG4gICAgICAsIFxcXCJkYXRlXFxcIiA6PSByZWxlYXNlLXRpbWVcXG4gICAgICAsIFxcXCJyZWRlZW1lZFxcXCIgOj0gcmVkZWVtZWRcXG4gICAgICAsIFxcXCJndWFyZFxcXCIgOj0gZ3VhcmRcXG4gICAgICB9XFxuXFxuICAgICAgKGxldCAoKGN1cnItdGltZTp0aW1lIChhdCAnYmxvY2stdGltZSAoY2hhaW4tZGF0YSkpKSlcXG5cXG4gICAgICAgIChlbmZvcmNlIChub3QgcmVkZWVtZWQpXFxuICAgICAgICAgIFxcXCJhbGxvY2F0aW9uIGZ1bmRzIGhhdmUgYWxyZWFkeSBiZWVuIHJlZGVlbWVkXFxcIilcXG5cXG4gICAgICAgIChlbmZvcmNlXFxuICAgICAgICAgICg-PSBjdXJyLXRpbWUgcmVsZWFzZS10aW1lKVxcbiAgICAgICAgICAoZm9ybWF0IFxcXCJmdW5kcyBsb2NrZWQgdW50aWwge30uIGN1cnJlbnQgdGltZToge31cXFwiIFtyZWxlYXNlLXRpbWUgY3Vyci10aW1lXSkpXFxuXFxuICAgICAgICAoZW5mb3JjZS1ndWFyZCBndWFyZClcXG5cXG4gICAgICAgICh3aXRoLWNhcGFiaWxpdHkgKENSRURJVCBhY2NvdW50KVxcbiAgICAgICAgICAoY3JlZGl0IGFjY291bnQgZ3VhcmQgYmFsYW5jZSlcXG5cXG4gICAgICAgICAgKHVwZGF0ZSBhbGxvY2F0aW9uLXRhYmxlIGFjY291bnRcXG4gICAgICAgICAgICB7IFxcXCJyZWRlZW1lZFxcXCIgOiB0cnVlXFxuICAgICAgICAgICAgLCBcXFwiYmFsYW5jZVxcXCIgOiAwLjBcXG4gICAgICAgICAgICB9KVxcblxcbiAgICAgICAgICBcXFwiQWxsb2NhdGlvbiBzdWNjZXNzZnVsbHkgcmVsZWFzZWQgdG8gbWFpbiBsZWRnZXJcXFwiKVxcbiAgICApKSlcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJjb2luLWNvbnRyYWN0LXYyXCJ9In0" - , - "eyJoYXNoIjoiS1BleXNfYndLeHpGV1M4cEdrWVg0QmZSWkh6MXhiVm43MkVTSk9PRGs0WSIsInNpZ3MiOltdLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6bnVsbCxcImNvZGVcIjpcIihjb2luLnJlbWVkaWF0ZSBcXFwic2VuZGVyMDdcXFwiIDEzMzcuNylcXG4oY29pbi5yZW1lZGlhdGUgXFxcInNlbmRlcjA5XFxcIiAxMzM3LjkpXCJ9fSxcInNpZ25lcnNcIjpbXSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6MTcyODAwLFwiZ2FzTGltaXRcIjowLFwiY2hhaW5JZFwiOlwiXCIsXCJnYXNQcmljZVwiOjAsXCJzZW5kZXJcIjpcIlwifSxcIm5vbmNlXCI6XCJkZXZuZXQtb3RoZXItcmVtZWRpYXRpb25zXCJ9In0" ] diff --git a/test/Chainweb/Test/Pact/ModuleCacheOnRestart.hs b/test/Chainweb/Test/Pact/ModuleCacheOnRestart.hs index e489f87d8f..8ac97d7277 100644 --- a/test/Chainweb/Test/Pact/ModuleCacheOnRestart.hs +++ b/test/Chainweb/Test/Pact/ModuleCacheOnRestart.hs @@ -1,10 +1,10 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} + module Chainweb.Test.Pact.ModuleCacheOnRestart (tests) where import Control.Concurrent.MVar.Strict @@ -34,10 +34,10 @@ import Chainweb.BlockHeader.Genesis import Chainweb.ChainId import Chainweb.Logger import Chainweb.Miner.Pact -import Chainweb.Pact.Backend.Types import Chainweb.Pact.PactService import Chainweb.Pact.Types import Chainweb.Payload +import Chainweb.Payload.PayloadStore import Chainweb.Time import Chainweb.Test.Cut import Chainweb.Test.Cut.TestBlockDb @@ -47,59 +47,45 @@ import Chainweb.Version import Chainweb.Version.Utils import Chainweb.WebBlockHeaderDB - --- ---------------------------------------------------------------------- -- --- Global data - -logger :: GenericLogger -logger = genericLogger Quiet T.putStrLn - testVer :: ChainwebVersion testVer = FastTimedCPM peterson testChainId :: ChainId testChainId = someChainId testVer -genblock :: BlockHeader -genblock = genesisBlockHeader testVer testChainId - -type CacheTest - = ( PactServiceM RocksDbCas () - , IO (MVar ModuleCache) -> ModuleCache -> Assertion - ) - -type CacheTestStep - = (SQLiteEnv, CacheTest -> Assertion) - --- ---------------------------------------------------------------------- -- --- Tests - tests :: ScheduledTest -tests = ScheduledTest label $ - withMVarResource mempty $ \iom -> - withTestBlockDbTest testVer $ \bdbio -> - withTemporaryDir $ \dir -> testGroup label - [ withPactTestCase bdbio dir iom testInitial "testInitial" +tests = + ScheduledTest label $ + withMVarResource mempty $ \iom -> + withTestBlockDbTest testVer $ \bdbio -> + withTemporaryDir $ \dir -> + testGroup label + [ + withPact' bdbio dir iom testInitial (testCase "testInitial") , after AllSucceed "testInitial" $ - withPactTestCase bdbio dir iom testRestart "testRestart1" + withPact' bdbio dir iom testRestart (testCase "testRestart1") , after AllSucceed "testRestart1" $ -- wow, Tasty thinks there's a "loop" if the following test is called "testCoinbase"!! - withPactTestCase bdbio dir iom (testCoinbase bdbio) "testDoUpgrades" + withPact' bdbio dir iom (testCoinbase bdbio) (testCase "testDoUpgrades") , after AllSucceed "testDoUpgrades" $ - withPactTestCase bdbio dir iom testRestart "testRestart2" + withPact' bdbio dir iom testRestart (testCase "testRestart2") + ] where label = "Chainweb.Test.Pact.ModuleCacheOnRestart" +type CacheTest cas = + (PactServiceM cas () + ,IO (MVar ModuleCache) -> ModuleCache -> Assertion) + -- | Do genesis load, snapshot cache. --- -testInitial :: CacheTest -testInitial = (initPayloadState, snapshotCache) +testInitial :: PayloadCasLookup cas => CacheTest cas +testInitial = (initPayloadState,snapshotCache) + where -- | Do restart load, test results of 'initialPayloadState' against snapshotted cache. --- -testRestart :: CacheTest -testRestart = (initPayloadState, checkLoadedCache) +testRestart :: PayloadCasLookup cas => CacheTest cas +testRestart = (initPayloadState,checkLoadedCache) where checkLoadedCache ioa initCache = do a <- ioa >>= readMVar @@ -113,8 +99,7 @@ testRestart = (initPayloadState, checkLoadedCache) assertBool msg (a' == c') -- | Run coinbase to do upgrade to v2, snapshot cache. --- -testCoinbase :: IO TestBlockDb -> CacheTest +testCoinbase :: PayloadCasLookup cas => IO TestBlockDb -> CacheTest cas testCoinbase iobdb = (initPayloadState >> doCoinbase,snapshotCache) where doCoinbase = do @@ -124,15 +109,14 @@ testCoinbase iobdb = (initPayloadState >> doCoinbase,snapshotCache) nextH <- liftIO $ getParentTestBlockDb bdb testChainId void $ execValidateBlock nextH (payloadWithOutputsToPayloadData pwo) --- ---------------------------------------------------------------------- -- --- Test data - -- | Interfaces can't be upgraded, but modules can, so verify hash in that case. --- justModuleHashes :: ModuleCache -> HM.HashMap ModuleName (Maybe ModuleHash) justModuleHashes = HM.map $ \v -> preview (_1 . mdModule . _MDModule . mHash) v -initPayloadState :: PactServiceM RocksDbCas () +genblock :: BlockHeader +genblock = genesisBlockHeader testVer testChainId + +initPayloadState :: PayloadCasLookup cas => PactServiceM cas () initPayloadState = initialPayloadState dummyLogger testVer testChainId snapshotCache :: IO (MVar ModuleCache) -> ModuleCache -> IO () @@ -140,33 +124,28 @@ snapshotCache iomcache initCache = do mcache <- iomcache modifyMVar_ mcache (const (pure initCache)) --- ---------------------------------------------------------------------- -- --- Test runners -withPactTestCase +withPact' :: IO TestBlockDb -> IO FilePath -> IO (MVar ModuleCache) - -> CacheTest - -> String + -> CacheTest RocksDbCas + -> (Assertion -> TestTree) -> TestTree -withPactTestCase bdbio iodir r ctest label = +withPact' bdbio iodir r ctest toTestTree = withResource startPact stopPact go where - go :: IO CacheTestStep -> TestTree - go iof = testCase label $ iof >>= \(_,f) -> f ctest - - startPact :: IO CacheTestStep + go iof = toTestTree $ iof >>= \(_,f) -> f ctest startPact = do bdb <- bdbio bhdb <- getWebBlockHeaderDb (_bdbWebBlockHeaderDb bdb) testChainId let pdb = _bdbPayloadDb bdb dir <- iodir sqlEnv <- startSqliteDb testVer testChainId logger (Just dir) Nothing False - return $ (sqlEnv,) $ \(ps, cacheTest) -> do + return $ (sqlEnv,) $ \(ps,cacheTest) -> do T2 _ pstate <- initPactService' testVer testChainId logger bhdb pdb sqlEnv defaultPactServiceConfig ps cacheTest r (_psInitCache pstate) - stopPact :: CacheTestStep -> IO () stopPact (sqlEnv, _) = stopSqliteDb sqlEnv + logger = genericLogger Quiet T.putStrLn diff --git a/test/Chainweb/Test/Pact/PactInProcApi.hs b/test/Chainweb/Test/Pact/PactInProcApi.hs index 8ce1483513..ebfbddb557 100644 --- a/test/Chainweb/Test/Pact/PactInProcApi.hs +++ b/test/Chainweb/Test/Pact/PactInProcApi.hs @@ -145,23 +145,19 @@ getHistory refIO reqIO = testCase "getHistory" $ do (BlockTxHistory hist) <- forSuccess "getHistory" (return mv) -- just check first one here assertEqual "check first entry of history" - (Just - [ TxLog "coin_coin-table" "sender00" - ( object - [ "guard" .= object - [ "pred" .= ("keys-all" :: T.Text) - , "keys" .= ["368820f80c324bbc7c2b0610688a7da43e39f91d118732671cd9c7500ff43cca" :: T.Text] - ] - , "balance" .= (Number 99999900.0) - ] - ) - ] - ) - - (M.lookup 11 hist) -- skip remediations at 10 + (Just [TxLog "coin_coin-table" "sender00" + (object + [ "guard" .= object + [ "pred" .= ("keys-all" :: T.Text) + , "keys" .= + ["368820f80c324bbc7c2b0610688a7da43e39f91d118732671cd9c7500ff43cca" :: T.Text] + ] + , "balance" .= (Number 99999900.0) + ])]) + (M.lookup 10 hist) -- and transaction txids assertEqual "check txids" - [7,10,11,13,14,16,17,19,20,22,23,25,26,28,29,31,32,34,35,37,38,40,41,43] + [7,10,12,13,15,16,18,19,21,22,24,25,27,28,30,31,33,34,36,37,39,40,42] (M.keys hist) getHistoricalLookupNoTxs diff --git a/test/golden/create-accounts-expected.txt b/test/golden/create-accounts-expected.txt index 96b27fcc48..4385fec173 100644 --- a/test/golden/create-accounts-expected.txt +++ b/test/golden/create-accounts-expected.txt @@ -1,4 +1,4 @@ -- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs +- output: s0GHumQ2cht2jXZZYlcqPhNcNtAUsP4zVU_R9MXuq-g cmd: coinbase - output: G15srpFoJgfoVchKV2ilyjMGtscxfNFlxwV0tvUC6bE cmd: diff --git a/test/golden/create-table-expected.txt b/test/golden/create-table-expected.txt index 20ad191c5c..c4a54a6949 100644 --- a/test/golden/create-table-expected.txt +++ b/test/golden/create-table-expected.txt @@ -1,4 +1,4 @@ -- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs +- output: s0GHumQ2cht2jXZZYlcqPhNcNtAUsP4zVU_R9MXuq-g cmd: coinbase - output: ExfKxPyfW_VnvUXfZva1taP6-woqfIYlNcnlFnKv5wQ cmd: diff --git a/test/golden/empty-block-tests-expected.txt b/test/golden/empty-block-tests-expected.txt index 68c8037c6b..c69cd98eb9 100644 --- a/test/golden/empty-block-tests-expected.txt +++ b/test/golden/empty-block-tests-expected.txt @@ -3,6 +3,6 @@ results: transactions: [] minerData: eyJhY2NvdW50IjoiTm9NaW5lciIsInByZWRpY2F0ZSI6IjwiLCJwdWJsaWMta2V5cyI6W119 transactionsHash: lL9ztEiU-NwzrlTpBbvhT4M1l5Shsht94OwFyhBaFD0 - outputsHash: mY63CaLW5zc6z3pyqAQzHt68b0aGaZOhqfXYXzAXLxc - payloadHash: nqycG99dCoGv7tYDaUzTCPXr5fNUQZyPrspb26ydhHk - coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoidG9fdGsyTzltM2lvblJyU1IwQ1dCY2tScGliS0NQbWpWSnRsS2daZVUxdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 + outputsHash: GSbZgTYq99iKlwligYOyB5nG4FnBE03Fscp1FQUOL2I + payloadHash: Vclgdw9i9rvv06CENBaSlMylLE92Xp3786S9pX1o2wk + coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoibFdaVWZjX0dKdGxUUy1LeDAtYm00aXRfSWE5bnNGZG5jZ2NwSE0td091OCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 diff --git a/test/golden/new-block-0-expected.txt b/test/golden/new-block-0-expected.txt index 5d336d2a67..c0ced25d2b 100644 --- a/test/golden/new-block-0-expected.txt +++ b/test/golden/new-block-0-expected.txt @@ -2,29 +2,29 @@ test-group: new-block results: transactions: - - eyJoYXNoIjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsInNpZ3MiOlt7InNpZyI6ImYzZTc5Mjc4MGRmNTIwZmVkMjg5MDc3MjllMjI1NTA4NTk2MzJhMzNiMTQzMTM0MDlkOTkyZmRmMjJjNTZlZDEwMzdiZTcxNDYyNWRkMTZmYWI5MmVlNjZhZmQ1MjhiNWViZjEwYWNhZjY2ZjRlZGVmMWM2ZjZjY2Q4OTkxMjA0In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihkZWZpbmUta2V5c2V0ICd0ZXN0LWFkbWluIChyZWFkLWtleXNldCBcXFwidGVzdC1hZG1pbi1rZXlzZXRcXFwiKSlcXG5cXG4obmFtZXNwYWNlICdmcmVlKVxcblxcbihtb2R1bGUgdGVzdDEgJ3Rlc3QtYWRtaW5cXG5cXG4gIChkZWZzY2hlbWEgYWNjb3VudFxcbiAgICBiYWxhbmNlOmRlY2ltYWxcXG4gICAgYW1vdW50OmRlY2ltYWxcXG4gICAgZGF0YSlcXG5cXG4gIChkZWZ0YWJsZSBhY2NvdW50czp7YWNjb3VudH0pXFxuXFxuICAoZGVmdW4gY3JlYXRlLWFjY291bnQgKGlkIGluaXQtYmFsKVxcbiAgICAoaW5zZXJ0IGFjY291bnRzIGlkXFxuICAgICAgICAgeyBcXFwiYmFsYW5jZVxcXCI6IGluaXQtYmFsLCBcXFwiYW1vdW50XFxcIjogaW5pdC1iYWwsIFxcXCJkYXRhXFxcIjogXFxcIkNyZWF0ZWQgYWNjb3VudFxcXCIgfSkpXFxuXFxuICAoZGVmdW4gdHJhbnNmZXIgKHNyYyBkZXN0IGFtb3VudClcXG4gICAgXFxcInRyYW5zZmVyIEFNT1VOVCBmcm9tIFNSQyB0byBERVNUIGZvciB1bmVuY3J5cHRlZCBhY2NvdW50c1xcXCJcXG4gICAgKGRlYml0IHNyYyBhbW91bnQgeyBcXFwidHJhbnNmZXItdG9cXFwiOiBkZXN0IH0pXFxuICAgIChjcmVkaXQgZGVzdCBhbW91bnQgeyBcXFwidHJhbnNmZXItZnJvbVxcXCI6IHNyYyB9KSlcXG5cXG4gIChkZWZwYWN0IHBheW1lbnQgKHNyYy1lbnRpdHkgc3JjIGRlc3QtZW50aXR5IGRlc3QgYW1vdW50KVxcbiAgICBcXFwiVHdvLXBoYXNlIGNvbmZpZGVudGlhbCBwYXltZW50LCBzZW5kaW5nIG1vbmV5IGZyb20gU1JDIGF0IFNSQy1FTlRJVFkgdG8gREVTVCBhdCBERVNULUVOVElUWS5cXFwiXFxuXFxuICAgIChzdGVwLXdpdGgtcm9sbGJhY2tcXG4gICAgIHNyYy1lbnRpdHlcXG4gICAgIChsZXQgKChyZXN1bHQgKGRlYml0IHNyYyBhbW91bnQgeyBcXFwidHJhbnNmZXItdG9cXFwiOiBkZXN0LCBcXFwibWVzc2FnZVxcXCI6IFxcXCJTdGFydGluZyBwYWN0XFxcIiB9KSkpXFxuICAgICAgICh5aWVsZCB7IFxcXCJyZXN1bHRcXFwiOiByZXN1bHQsIFxcXCJhbW91bnRcXFwiOiBhbW91bnQsIFxcXCJ0eFxcXCI6IChwYWN0LWlkKSB9KSlcXG4gICAgIChjcmVkaXQgc3JjIGFtb3VudCB7IFxcXCJyb2xsYmFja1xcXCI6IChwYWN0LWlkKSB9KSlcXG5cXG4gICAgKHN0ZXBcXG4gICAgIGRlc3QtZW50aXR5XFxuICAgICAocmVzdW1lIHsgXFxcInJlc3VsdFxcXCI6PSByZXN1bHQsIFxcXCJhbW91bnRcXFwiOj0gZGViaXQtYW1vdW50IH1cXG4gICAgICAgKGNyZWRpdCBkZXN0IGRlYml0LWFtb3VudFxcbiAgICAgICAgICAgICAgIHsgXFxcInRyYW5zZmVyLWZyb21cXFwiOiBzcmMsIFxcXCJkZWJpdC1yZXN1bHRcXFwiOiByZXN1bHQsIFxcXCJ0eFxcXCI6IChwYWN0LWlkKSB9KSkpKVxcblxcbiAgKGRlZnVuIGRlYml0IChhY2N0IGFtb3VudCBkYXRhKVxcbiAgICBcXFwiRGViaXQgQUNDVCBmb3IgQU1PVU5ULCBlbmZvcmNpbmcgcG9zaXRpdmUgYW1vdW50IGFuZCBzdWZmaWNpZW50IGZ1bmRzLCBhbm5vdGF0aW5nIHdpdGggREFUQVxcXCJcXG4gICAgKGVuZm9yY2UtcG9zaXRpdmUgYW1vdW50KVxcbiAgICAod2l0aC1yZWFkIGFjY291bnRzIGFjY3QgeyBcXFwiYmFsYW5jZVxcXCI6PSBiYWxhbmNlIH1cXG4gICAgICAoY2hlY2stYmFsYW5jZSBiYWxhbmNlIGFtb3VudClcXG4gICAgICAodXBkYXRlIGFjY291bnRzIGFjY3RcXG4gICAgICAgICAgICB7IFxcXCJiYWxhbmNlXFxcIjogKC0gYmFsYW5jZSBhbW91bnQpLCBcXFwiYW1vdW50XFxcIjogKC0gYW1vdW50KVxcbiAgICAgICAgICAgICwgXFxcImRhdGFcXFwiOiBkYXRhIH0pKSlcXG5cXG4gIChkZWZ1biBjcmVkaXQgKGFjY3QgYW1vdW50IGRhdGEpXFxuICAgIFxcXCJDcmVkaXQgQUNDVCBmb3IgQU1PVU5ULCBlbmZvcmNpbmcgcG9zaXRpdmUgYW1vdW50XFxcIlxcbiAgICAoZW5mb3JjZS1wb3NpdGl2ZSBhbW91bnQpXFxuICAgICh3aXRoLXJlYWQgYWNjb3VudHMgYWNjdCB7IFxcXCJiYWxhbmNlXFxcIjo9IGJhbGFuY2UgfVxcbiAgICAgICh1cGRhdGUgYWNjb3VudHMgYWNjdFxcbiAgICAgICAgICAgIHsgXFxcImJhbGFuY2VcXFwiOiAoKyBiYWxhbmNlIGFtb3VudCksIFxcXCJhbW91bnRcXFwiOiBhbW91bnRcXG4gICAgICAgICAgICAsIFxcXCJkYXRhXFxcIjogZGF0YSB9KSkpXFxuXFxuXFxuICAoZGVmdW4gcmVhZC1hY2NvdW50IChpZClcXG4gICAgXFxcIlJlYWQgZGF0YSBmb3IgYWNjb3VudCBJRFxcXCJcXG4gICAgKCsgeyBcXFwiYWNjb3VudFxcXCI6IGlkIH0gKHJlYWQgYWNjb3VudHMgaWQpKSlcXG5cXG4gIChkZWZ1biBjaGVjay1iYWxhbmNlIChiYWxhbmNlIGFtb3VudClcXG4gICAgKGVuZm9yY2UgKDw9IGFtb3VudCBiYWxhbmNlKSBcXFwiSW5zdWZmaWNpZW50IGZ1bmRzXFxcIikpXFxuXFxuICAoZGVmdW4gZW5mb3JjZS1wb3NpdGl2ZSAoYW1vdW50KVxcbiAgICAoZW5mb3JjZSAoPj0gYW1vdW50IDAuMCkgXFxcImFtb3VudCBtdXN0IGJlIHBvc2l0aXZlXFxcIikpXFxuXFxuIChkZWZ1biByZWFkLWFsbCAoKVxcbiAgIChtYXAgKHJlYWQtYWNjb3VudCkgKGtleXMgYWNjb3VudHMpKSlcXG5cXG4gKGRlZnVuIHJlYWQtYWxsLWdsb2JhbCAoKVxcbiAgIChtYXAgKHJlYWQtYWNjb3VudCkgW1xcXCJBY2N0MVxcXCIgXFxcIkFjY3QyXFxcIl0pKVxcblxcbiAoZGVmdW4gY3JlYXRlLWdsb2JhbC1hY2NvdW50cyAoKVxcbiAgIChjcmVhdGUtYWNjb3VudCBcXFwiQWNjdDFcXFwiIDEwMDAwMDAuMClcXG4gICAoY3JlYXRlLWFjY291bnQgXFxcIkFjY3QyXFxcIiAwLjApXFxuICAgKHJlYWQtYWxsKSlcXG5cXG4gKGRlZnBhY3QgY3JlYXRlLXByaXZhdGUtYWNjb3VudHMgKClcXG4gICAoc3RlcCBcXFwiQWxpY2VcXFwiIChjcmVhdGUtYWNjb3VudCBcXFwiQVxcXCIgMTAwMC4wKSlcXG4gICAoc3RlcCBcXFwiQm9iXFxcIiAoY3JlYXRlLWFjY291bnQgXFxcIkJcXFwiIDEwMDAuMCkpXFxuICAgKHN0ZXAgXFxcIkNhcm9sXFxcIiAoY3JlYXRlLWFjY291bnQgXFxcIkNcXFwiIDEwMDAuMCkpXFxuICAgKHN0ZXAgXFxcIkRpbmVzaFxcXCIgKGNyZWF0ZS1hY2NvdW50IFxcXCJEXFxcIiAxMDAwLjApKSlcXG5cXG4pXFxuXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjEwXCJ9In0 - - eyJnYXMiOjY0OSwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiTG9hZGVkIG1vZHVsZSBmcmVlLnRlc3QxLCBoYXNoIEI2WkpnZldENW9iUEdtWWNfaVJLaXJETVA2LVVHbTJwVVY3bXRIRC1Sc1EifSwicmVxS2V5IjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsImxvZ3MiOiJMRm51NzRDaE4wZS1IbGI3azlqZlAzcmpmcWh6WjFweUpibXpkX1lOMFdZIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MTJ9 + - eyJnYXMiOjY0OSwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiTG9hZGVkIG1vZHVsZSBmcmVlLnRlc3QxLCBoYXNoIEI2WkpnZldENW9iUEdtWWNfaVJLaXJETVA2LVVHbTJwVVY3bXRIRC1Sc1EifSwicmVxS2V5IjoiSWxGRDdhOVVZT0dXMUJHRUZjYWRwejVUVW1XLVc5ZkJ5NkZIVzYzaXEzayIsImxvZ3MiOiJMRm51NzRDaE4wZS1IbGI3azlqZlAzcmpmcWh6WjFweUpibXpkX1lOMFdZIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MTF9 - - eyJoYXNoIjoidUFaMDFQQ21QWW43UTBrdGRMZ21abEZueVFUU2t3aXRXTmp0ZTNUQ3hOYyIsInNpZ3MiOlt7InNpZyI6IjU1Nzk3Zjk2YjEwYzY5ZjRhMGY2ZTg5ZDI4OGFjMTNlZDE1MDI4NWJkNDJmODNjZTMzNjE2M2IzYTllNmM3MjFiY2FlMGE2MzhjMTgwYTk0MTE2YjlhZDBkM2UwOWFlYmI3OGE2NjVhNTg2MzdhMmExZmE0OGU3NDZiYzU5NDA5In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihjcmVhdGUtdGFibGUgZnJlZS50ZXN0MS5hY2NvdW50cylcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTFcIn0ifQ - - eyJnYXMiOjI2NCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiVGFibGVDcmVhdGVkIn0sInJlcUtleSI6InVBWjAxUENtUFluN1Ewa3RkTGdtWmxGbnlRVFNrd2l0V05qdGUzVEN4TmMiLCJsb2dzIjoianVuYlJrd3hEMVhiUHBvTnNCZlN3NEJGYUEtcW1mempEMmhfOHhQTmczbyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE1fQ + - eyJnYXMiOjI2NCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiVGFibGVDcmVhdGVkIn0sInJlcUtleSI6InVBWjAxUENtUFluN1Ewa3RkTGdtWmxGbnlRVFNrd2l0V05qdGUzVEN4TmMiLCJsb2dzIjoianVuYlJrd3hEMVhiUHBvTnNCZlN3NEJGYUEtcW1mempEMmhfOHhQTmczbyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE0fQ - - eyJoYXNoIjoiWjZxajdIZnBSN0pnZkJFZGhsYU9BSTdjdDd1ZFM2dE5jVUF0RFZMSHNJbyIsInNpZ3MiOlt7InNpZyI6ImM5YzExMGE2MGI4M2JmMmM1OTFiMTMxMWJjOTdjNjJiNzkxZTcwNDYzM2RhY2EyMGNhYmE2MTRhNGQwYThkYmFlODJlNmQxOWQ2NDZlMWJmNGNlMWUyMDZjMTM4MmM4NGExMGI5Y2NkYWY2MzAzOGU1ZWJmMDk3ZmE3YzZjMTAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihmcmVlLnRlc3QxLmNyZWF0ZS1nbG9iYWwtYWNjb3VudHMpXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjEyXCJ9In0 - - eyJnYXMiOjU4MCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjpbeyJhbW91bnQiOjEwMDAwMDAsImRhdGEiOiJDcmVhdGVkIGFjY291bnQiLCJiYWxhbmNlIjoxMDAwMDAwLCJhY2NvdW50IjoiQWNjdDEifSx7ImFtb3VudCI6MCwiZGF0YSI6IkNyZWF0ZWQgYWNjb3VudCIsImJhbGFuY2UiOjAsImFjY291bnQiOiJBY2N0MiJ9XX0sInJlcUtleSI6Ilo2cWo3SGZwUjdKZ2ZCRWRobGFPQUk3Y3Q3dWRTNnROY1VBdERWTEhzSW8iLCJsb2dzIjoia0VIU2ZyQXRLQV9vdi1xZDV4cmpSSTFtX2phenRkSF9JbGVJWG9QNW9wNCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE4fQ + - eyJnYXMiOjU4MCwicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjpbeyJhbW91bnQiOjEwMDAwMDAsImRhdGEiOiJDcmVhdGVkIGFjY291bnQiLCJiYWxhbmNlIjoxMDAwMDAwLCJhY2NvdW50IjoiQWNjdDEifSx7ImFtb3VudCI6MCwiZGF0YSI6IkNyZWF0ZWQgYWNjb3VudCIsImJhbGFuY2UiOjAsImFjY291bnQiOiJBY2N0MiJ9XX0sInJlcUtleSI6Ilo2cWo3SGZwUjdKZ2ZCRWRobGFPQUk3Y3Q3dWRTNnROY1VBdERWTEhzSW8iLCJsb2dzIjoia0VIU2ZyQXRLQV9vdi1xZDV4cmpSSTFtX2phenRkSF9JbGVJWG9QNW9wNCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjE3fQ - - eyJoYXNoIjoicFBrLWxFUE1jRnRDWXdXR2ZaejV2bGdzZ1ZYV3dYbXhmQVJ6bkFCbUVONCIsInNpZ3MiOlt7InNpZyI6IjM3YjI4MmY1YWQ0YWY0Yzk2YmE1NzA5YWEzOTI2NTU1YjU5MDEwYzczZmVmZTUwNzQyMGYyODVjZTI1MmQ5ZjM1YzQ5NjAxYTgwMDYxZGU2NzEzNTcxNzY2MTNmODIyODQxMDU0MjliZTVkOTEzNWMzODAxMzcyN2UyMmI3ZjA2In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihmcmVlLnRlc3QxLnRyYW5zZmVyIFxcXCJBY2N0MVxcXCIgXFxcIkFjY3QyXFxcIiAxLjAwKVwifX0sXCJzaWduZXJzXCI6W3tcInB1YktleVwiOlwiMzY4ODIwZjgwYzMyNGJiYzdjMmIwNjEwNjg4YTdkYTQzZTM5ZjkxZDExODczMjY3MWNkOWM3NTAwZmY0M2NjYVwifV0sXCJtZXRhXCI6e1wiY3JlYXRpb25UaW1lXCI6MCxcInR0bFwiOjg2NDAwLFwiZ2FzTGltaXRcIjoxMDAwMCxcImNoYWluSWRcIjpcIjBcIixcImdhc1ByaWNlXCI6MS4wZS0yLFwic2VuZGVyXCI6XCJzZW5kZXIwMFwifSxcIm5vbmNlXCI6XCIxM1wifSJ9 - - eyJnYXMiOjQwNywicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiV3JpdGUgc3VjY2VlZGVkIn0sInJlcUtleSI6InBQay1sRVBNY0Z0Q1l3V0dmWno1dmxnc2dWWFd3WG14ZkFSem5BQm1FTjQiLCJsb2dzIjoib3hWd2tvU21xM2JZeVh5aHYwT0V3ZTN2c0tGbWlkRTBtTEotQ2FZWVhRayIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjIxfQ + - eyJnYXMiOjQwNywicmVzdWx0Ijp7InN0YXR1cyI6InN1Y2Nlc3MiLCJkYXRhIjoiV3JpdGUgc3VjY2VlZGVkIn0sInJlcUtleSI6InBQay1sRVBNY0Z0Q1l3V0dmWno1dmxnc2dWWFd3WG14ZkFSem5BQm1FTjQiLCJsb2dzIjoib3hWd2tvU21xM2JZeVh5aHYwT0V3ZTN2c0tGbWlkRTBtTEotQ2FZWVhRayIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjIwfQ - - eyJoYXNoIjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsInNpZ3MiOlt7InNpZyI6IjZhODRiMWRkNGFkNDE5ZGY3YThhODA4NGYwNWEyZDM5YzExNTBmMjI5ZTM3OTFlM2UwY2E0OTkyZDkwNGNhOGVlMTk4MTljNTE3YTVjNjM5M2E3ZmYyNWI1NjdiNjJjOTYwZTFiYmI4ZTE2YjZiMWU2YmRkNDU1Njk3ODc1MDA5In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAncHJldi1ibG9jay1oYXNoIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTRcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNWMDlUbHhfZURIQWdYZkY1WS1jcG1MMVBTWFFsTERKRWc5MUJKczBieWMifSwicmVxS2V5IjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsImxvZ3MiOiJUVVVlWFJmRFlnQlZTdjFZU0ktU3lfRVdtcHRaWXZqQlNmY1ZMc2ZzcVpVIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MjR9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNWMDlUbHhfZURIQWdYZkY1WS1jcG1MMVBTWFFsTERKRWc5MUJKczBieWMifSwicmVxS2V5IjoiX2RneUxfSGtlZGJFZjl5UTY5Wkhhc2g2M01JVUw2ZktibzBqeXJJRWhPYyIsImxvZ3MiOiJUVVVlWFJmRFlnQlZTdjFZU0ktU3lfRVdtcHRaWXZqQlNmY1ZMc2ZzcVpVIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MjN9 - - eyJoYXNoIjoiTzhoWU1TVUhnSkNPRXFoTy0yRFRNRGJhTzBIZmx6VjM0UHRzM0dlUHBJUSIsInNpZ3MiOlt7InNpZyI6ImMxYjQ5OTQwNTQ0MjZmNzE2NWM2NmZjNjY0MzE0N2M1N2QxYTczYzM3NjEwMjU4OGU0M2QyMzA1ZjBhY2FhYTQyMDRkZGRmNGRhMWFiMzk0OTdkY2FiM2FjZWU1NmQ0NmQ3NzJkNDZkNjAyNmU5ZjQ4MGFmMWNiMWIyNWFmYzA3In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnYmxvY2stdGltZSAoY2hhaW4tZGF0YSkpXCJ9fSxcInNpZ25lcnNcIjpbe1wicHViS2V5XCI6XCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJ9XSxcIm1ldGFcIjp7XCJjcmVhdGlvblRpbWVcIjowLFwidHRsXCI6ODY0MDAsXCJnYXNMaW1pdFwiOjEwMDAwLFwiY2hhaW5JZFwiOlwiMFwiLFwiZ2FzUHJpY2VcIjoxLjBlLTIsXCJzZW5kZXJcIjpcInNlbmRlcjAwXCJ9LFwibm9uY2VcIjpcIjE1XCJ9In0 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJ0aW1lIjoiMTk3MC0wMS0wMVQwMDowMDowMFoifX0sInJlcUtleSI6Ik84aFlNU1VIZ0pDT0VxaE8tMkRUTURiYU8wSGZselYzNFB0czNHZVBwSVEiLCJsb2dzIjoidTdKNDU3dGdzNDJ1dGhjOU1TbWtkaTkxT2tUb2FCNFpGei1QUWtSajJhdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI3fQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJ0aW1lIjoiMTk3MC0wMS0wMVQwMDowMDowMFoifX0sInJlcUtleSI6Ik84aFlNU1VIZ0pDT0VxaE8tMkRUTURiYU8wSGZselYzNFB0czNHZVBwSVEiLCJsb2dzIjoidTdKNDU3dGdzNDJ1dGhjOU1TbWtkaTkxT2tUb2FCNFpGei1QUWtSajJhdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI2fQ - - eyJoYXNoIjoiSGFsbTJLYUV5Qm5weXJqMkxHMmJQcVZDUmZBYk8yWHZzZWlnaURaZElLOCIsInNpZ3MiOlt7InNpZyI6ImI0MDNlZWI3ODI0NzA0OWU0NjEzNGQzYWQ0MWZlMTAwNWMxM2I0NzNhNjUzZGNmNTVlN2ZmMzIzOGU5N2VkYmRmZTMyZmFmODczODViYTc0MmNmMDFmYmFkMDU2ODEwNWVjNDhhMDk1MzIyNWJmMmY0ODJjNjhiMjkyZGNmOTAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnYmxvY2staGVpZ2h0IChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTZcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MX0sInJlcUtleSI6IkhhbG0yS2FFeUJucHlyajJMRzJiUHFWQ1JmQWJPMlh2c2VpZ2lEWmRJSzgiLCJsb2dzIjoiaEtSOEZUYkhSVnhxV092TTZWXzZ1dUdMSVA3T2loV25RR3dFSnV0REF0cyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjMwfQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MX0sInJlcUtleSI6IkhhbG0yS2FFeUJucHlyajJMRzJiUHFWQ1JmQWJPMlh2c2VpZ2lEWmRJSzgiLCJsb2dzIjoiaEtSOEZUYkhSVnhxV092TTZWXzZ1dUdMSVA3T2loV25RR3dFSnV0REF0cyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjI5fQ - - eyJoYXNoIjoiRVI0TlZZaFp1Z3BJeXR6TFhQWjJUZ18wUGc5T3NvTEtva1RxN0R3WGpLdyIsInNpZ3MiOlt7InNpZyI6IjJlNDZjMWMzZDQ0YTQ3YzdiZDY2ZTM1MWNhZDBmY2JjYmMyMDk1ZWJhYTk5MzY4NjRmZmZhOTVlNTJhNjE5MDlkMTBlODY3Y2RhMjFmNTcyZjMxODhmYjNmNjUxYTAzMzY3NWM5ZTk2NDFhNDBlM2EwNGNlMmUyMDk4NjQ2NjAzIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnZ2FzLWxpbWl0IChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTdcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MTAwMDB9LCJyZXFLZXkiOiJFUjROVlloWnVncEl5dHpMWFBaMlRnXzBQZzlPc29MS29rVHE3RHdYakt3IiwibG9ncyI6IklwcDE1S0QtdlZXS3JwanVDM0NBWHk3cTZia1hudURIbF82TmFiaGVyd1EiLCJtZXRhRGF0YSI6bnVsbCwiY29udGludWF0aW9uIjpudWxsLCJ0eElkIjozM30 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MTAwMDB9LCJyZXFLZXkiOiJFUjROVlloWnVncEl5dHpMWFBaMlRnXzBQZzlPc29MS29rVHE3RHdYakt3IiwibG9ncyI6IklwcDE1S0QtdlZXS3JwanVDM0NBWHk3cTZia1hudURIbF82TmFiaGVyd1EiLCJtZXRhRGF0YSI6bnVsbCwiY29udGludWF0aW9uIjpudWxsLCJ0eElkIjozMn0 - - eyJoYXNoIjoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsInNpZ3MiOlt7InNpZyI6IjIwNmZkMmMzYTBkMzBjMDhlN2FhY2U4ZGZmNmQ1MTIxYWZhMTA3NThhM2M3YTFhNDc2NTE1YmFlMjNiNmNiZmM5NjRiNjhkYmYxMzU5MzVhYWNiYzNlZmYzMzczZWE4YmUxMmI0OTdmOTU1NjU5MDQ3NDAxNTQ0ZTUyMDNjMjA4In1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnZ2FzLXByaWNlIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMThcIn0ifQ - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MS4wZS0yfSwicmVxS2V5Ijoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsImxvZ3MiOiJaUDhDRmdiOEZQUkQ0Q3E2MFV0aUp3aU9oaDduRFU3YXFBNnQtbDFFbS1NIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MzZ9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6MS4wZS0yfSwicmVxS2V5Ijoia21ldS1LajJudVNMcHZzNmVsNVdiY0d6VnZ3ZjlaSjd2LTJCa2g4UmVlQSIsImxvZ3MiOiJaUDhDRmdiOEZQUkQ0Q3E2MFV0aUp3aU9oaDduRFU3YXFBNnQtbDFFbS1NIiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6MzV9 - - eyJoYXNoIjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsInNpZ3MiOlt7InNpZyI6IjhiNGU0MjZiMDMwMGYwOTJmMWJhZDVkYTY2MWEzYjBmZWE0ZjUwNTAyZmI3ODZjOWQyOTZhNTgwZTRmOGViMTc1Njc5YjQ4NDQwMDAyNjQ2MTc2OWRjMzI4MzkxYTQzM2E5NjAxY2ZhMzk5ZDQyNmUxYTdhMmUwOWYxNzYyNzAxIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnY2hhaW4taWQgKGNoYWluLWRhdGEpKVwifX0sXCJzaWduZXJzXCI6W3tcInB1YktleVwiOlwiMzY4ODIwZjgwYzMyNGJiYzdjMmIwNjEwNjg4YTdkYTQzZTM5ZjkxZDExODczMjY3MWNkOWM3NTAwZmY0M2NjYVwifV0sXCJtZXRhXCI6e1wiY3JlYXRpb25UaW1lXCI6MCxcInR0bFwiOjg2NDAwLFwiZ2FzTGltaXRcIjoxMDAwMCxcImNoYWluSWRcIjpcIjBcIixcImdhc1ByaWNlXCI6MS4wZS0yLFwic2VuZGVyXCI6XCJzZW5kZXIwMFwifSxcIm5vbmNlXCI6XCIxOVwifSJ9 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IjAifSwicmVxS2V5IjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsImxvZ3MiOiItNEMyR2Myc0hJWE9sREt0cFBZNGZpaEI0dndWc0NPYnpPc0JxOFAyNEQ0IiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6Mzl9 + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IjAifSwicmVxS2V5IjoiU2REQTV6VXVPWEJOZEQ5cnpzYWEzU1NRTENUTTdVWWNPeWhoaWxGUlNURSIsImxvZ3MiOiItNEMyR2Myc0hJWE9sREt0cFBZNGZpaEI0dndWc0NPYnpPc0JxOFAyNEQ0IiwibWV0YURhdGEiOm51bGwsImNvbnRpbnVhdGlvbiI6bnVsbCwidHhJZCI6Mzh9 - - eyJoYXNoIjoiV2dudUNnNkxfbDZsemJqV3RCZk1FdVB0dHlfdUdjTnJVb2w1SEdSRU9fbyIsInNpZ3MiOlt7InNpZyI6IjgxNzAxZTJiMDQ4MzdjMDk1NDY3NGNiNWM2YzcxMGJhZGZlNzA5MjJiYTM0YTEyNDVjMWZmZDJmY2Q2NTQ4NzExZjY2Y2FmNTc1Njk2ZjU2NmQzYWQ3ZGNlMzgxZGQxN2M1Njc0OWQwM2M3OWQ5NmI1OWIxNGQ3ZjAwMTE0NjBhIn1dLCJjbWQiOiJ7XCJuZXR3b3JrSWRcIjpudWxsLFwicGF5bG9hZFwiOntcImV4ZWNcIjp7XCJkYXRhXCI6e1widGVzdC1hZG1pbi1rZXlzZXRcIjpbXCIzNjg4MjBmODBjMzI0YmJjN2MyYjA2MTA2ODhhN2RhNDNlMzlmOTFkMTE4NzMyNjcxY2Q5Yzc1MDBmZjQzY2NhXCJdfSxcImNvZGVcIjpcIihhdCAnc2VuZGVyIChjaGFpbi1kYXRhKSlcIn19LFwic2lnbmVyc1wiOlt7XCJwdWJLZXlcIjpcIjM2ODgyMGY4MGMzMjRiYmM3YzJiMDYxMDY4OGE3ZGE0M2UzOWY5MWQxMTg3MzI2NzFjZDljNzUwMGZmNDNjY2FcIn1dLFwibWV0YVwiOntcImNyZWF0aW9uVGltZVwiOjAsXCJ0dGxcIjo4NjQwMCxcImdhc0xpbWl0XCI6MTAwMDAsXCJjaGFpbklkXCI6XCIwXCIsXCJnYXNQcmljZVwiOjEuMGUtMixcInNlbmRlclwiOlwic2VuZGVyMDBcIn0sXCJub25jZVwiOlwiMTEwXCJ9In0 - - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNlbmRlcjAwIn0sInJlcUtleSI6IldnbnVDZzZMX2w2bHpiald0QmZNRXVQdHR5X3VHY05yVW9sNUhHUkVPX28iLCJsb2dzIjoiVl96OG10RjdtMVpNRWJiQUNtZlFLbWFLejdhZF9qWjhYbXhaYV9KMTRWWSIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjQyfQ + - eyJnYXMiOjcsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6InNlbmRlcjAwIn0sInJlcUtleSI6IldnbnVDZzZMX2w2bHpiald0QmZNRXVQdHR5X3VHY05yVW9sNUhHUkVPX28iLCJsb2dzIjoiVl96OG10RjdtMVpNRWJiQUNtZlFLbWFLejdhZF9qWjhYbXhaYV9KMTRWWSIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjQxfQ minerData: eyJhY2NvdW50IjoiTm9NaW5lciIsInByZWRpY2F0ZSI6IjwiLCJwdWJsaWMta2V5cyI6W119 transactionsHash: FridPvHieVs4XE7B2Fu_wSShUOA694ZeAn1OJlZB3qw - outputsHash: -hLAWIRrf747i8MSDVAsRcqs7YnVV9X_17YZq57stTE - payloadHash: MbN2D7TjjwSF3CGpBMMtgm1KNd_8XRv3336M3s6X7xY - coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoidG9fdGsyTzltM2lvblJyU1IwQ1dCY2tScGliS0NQbWpWSnRsS2daZVUxdyIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 + outputsHash: vX0s27SREHzRmQtTfd7iDrV5s4b24jK05vu7aaFCz_k + payloadHash: rB-uufI8Yz1hNWJnMKvRcjBhNTLcyU2ub4JaBeo2mD0 + coinbase: eyJnYXMiOjAsInJlc3VsdCI6eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6IldyaXRlIHN1Y2NlZWRlZCJ9LCJyZXFLZXkiOiJJbVZGZEZFdFdYbHZOelJJZWs4MllsUklTV1Z1VkdweVQzZE1hRTVHVWxKVGRYa3dTMWxJUkhFeFNtY2kiLCJsb2dzIjoibFdaVWZjX0dKdGxUUy1LeDAtYm00aXRfSWE5bnNGZG5jZ2NwSE0td091OCIsIm1ldGFEYXRhIjpudWxsLCJjb250aW51YXRpb24iOm51bGwsInR4SWQiOjd9 diff --git a/test/golden/transfer-accounts-expected.txt b/test/golden/transfer-accounts-expected.txt index 07354a0aba..410fa34fca 100644 --- a/test/golden/transfer-accounts-expected.txt +++ b/test/golden/transfer-accounts-expected.txt @@ -1,4 +1,4 @@ -- output: BNiectSkmcr9CxdfPSjl6nyDkCJlV0iCpNhUk4vRXcs +- output: s0GHumQ2cht2jXZZYlcqPhNcNtAUsP4zVU_R9MXuq-g cmd: coinbase - output: noxWe0aOpl3J20QHMVJP8EvPGG8kftv63GeIjvJwrXQ cmd: diff --git a/tools/ea/Ea.hs b/tools/ea/Ea.hs index 5b4cd9c91f..1e15bb079e 100644 --- a/tools/ea/Ea.hs +++ b/tools/ea/Ea.hs @@ -234,11 +234,9 @@ genTxModules = void $ do putStrLn "Done." where gen tag remeds = genTxModule tag $ upgrades <> remeds - genOtherTxs = gen "Other" - ["pact/coin-contract/remediations/devother/remediations.yaml"] - + genOtherTxs = gen "Other" [] genDevTxs = gen "Development" - ["pact/coin-contract/remediations/devnet/remediations.yaml"] + ["pact/coin-contract/remediations/devother/remediations.yaml"] genMain :: Int -> IO () genMain chain = gen ("Mainnet" <> sshow chain) From afd67e801f266546bf40a3cc5d70f7b803552b51 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Wed, 8 Jul 2020 11:30:20 -0400 Subject: [PATCH 39/48] remove hie.yaml --- hie.yaml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 hie.yaml diff --git a/hie.yaml b/hie.yaml deleted file mode 100644 index 7b37c70587..0000000000 --- a/hie.yaml +++ /dev/null @@ -1 +0,0 @@ -cradle: {cabal: {component: "chainweb:test:chainweb-tests"}} \ No newline at end of file From cd552ae9855845fea0f7853f312cbbc6cdf0a925 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Wed, 8 Jul 2020 11:32:24 -0400 Subject: [PATCH 40/48] revert whitespace changes --- src/Chainweb/Rosetta/RestAPI/Server.hs | 1 + test/Chainweb/Test/Pact/SPV.hs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/Chainweb/Rosetta/RestAPI/Server.hs b/src/Chainweb/Rosetta/RestAPI/Server.hs index 7134e5a5f2..e32ee65720 100644 --- a/src/Chainweb/Rosetta/RestAPI/Server.hs +++ b/src/Chainweb/Rosetta/RestAPI/Server.hs @@ -154,6 +154,7 @@ blockH blockH v cutDb ps crs (BlockReq net (PartialBlockId bheight bhash)) = runExceptT work >>= either throwRosetta pure where + block :: BlockHeader -> [Transaction] -> Block block bh txs = Block { _block_blockId = blockId bh diff --git a/test/Chainweb/Test/Pact/SPV.hs b/test/Chainweb/Test/Pact/SPV.hs index e213aa7b85..c17685e93d 100644 --- a/test/Chainweb/Test/Pact/SPV.hs +++ b/test/Chainweb/Test/Pact/SPV.hs @@ -301,6 +301,9 @@ burnGen time pidv sid tid = do putMVar pidv pid `finally` writeIORef ref1 True return $ Vector.singleton cmd + + + tx1Code = [text| (coin.transfer-crosschain From ca30b4d73cabc249a9aa9c9fc61d7846c966f2ac Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Wed, 8 Jul 2020 11:54:44 -0400 Subject: [PATCH 41/48] add note about 20-chain upgrades --- src/Chainweb/Pact/TransactionExec.hs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Chainweb/Pact/TransactionExec.hs b/src/Chainweb/Pact/TransactionExec.hs index 30dbcf7cc8..aa142ab029 100644 --- a/src/Chainweb/Pact/TransactionExec.hs +++ b/src/Chainweb/Pact/TransactionExec.hs @@ -473,6 +473,13 @@ applyTwentyChainUpgrade v cid bh infoLog $ "Applying 20-chain upgrades on chain " <> sshow cid let txs = fmap payloadObj <$> txlist + + -- + -- Note (emily): This function does not need to care about + -- module caching, because it is already seeded with the correct cache + -- state, and is not updating the module cache, unlike 'applyUpgrades'. + -- + traverse_ applyTx txs | otherwise = return () where From 97400fed83677f983a9a0f5446683e4ff91fa91a Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Wed, 8 Jul 2020 12:04:45 -0400 Subject: [PATCH 42/48] bad merge --- test/Chainweb/Test/Pact/Utils.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Chainweb/Test/Pact/Utils.hs b/test/Chainweb/Test/Pact/Utils.hs index 9ba5c5e547..df56fd4ff8 100644 --- a/test/Chainweb/Test/Pact/Utils.hs +++ b/test/Chainweb/Test/Pact/Utils.hs @@ -429,8 +429,8 @@ testPactCtxSQLite v cid bhdb pdb sqlenv conf = do , _psReorgLimit = fromIntegral $ _pactReorgLimit conf , _psOnFatalError = defaultOnFatalError mempty , _psVersion = v - , _psValidateHashesOnReplay = _pactRevalidate config - , _psAllowReadsInLocal = _pactAllowReadsInLocal config + , _psValidateHashesOnReplay = _pactRevalidate conf + , _psAllowReadsInLocal = _pactAllowReadsInLocal conf , _psIsBatch = False , _psCheckpointerDepth = 0 } From 88f94ad5a3e3a91cd890b268e1d74db7704964b9 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Wed, 8 Jul 2020 18:53:28 -0400 Subject: [PATCH 43/48] remove comment + whitespace --- src/Chainweb/Rosetta/RestAPI/Server.hs | 1 - test/Chainweb/Test/Utils.hs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Chainweb/Rosetta/RestAPI/Server.hs b/src/Chainweb/Rosetta/RestAPI/Server.hs index e32ee65720..7134e5a5f2 100644 --- a/src/Chainweb/Rosetta/RestAPI/Server.hs +++ b/src/Chainweb/Rosetta/RestAPI/Server.hs @@ -154,7 +154,6 @@ blockH blockH v cutDb ps crs (BlockReq net (PartialBlockId bheight bhash)) = runExceptT work >>= either throwRosetta pure where - block :: BlockHeader -> [Transaction] -> Block block bh txs = Block { _block_blockId = blockId bh diff --git a/test/Chainweb/Test/Utils.hs b/test/Chainweb/Test/Utils.hs index 93dfe42d20..b5f4781f6a 100644 --- a/test/Chainweb/Test/Utils.hs +++ b/test/Chainweb/Test/Utils.hs @@ -138,7 +138,6 @@ import Data.Coerce (coerce) import Data.Foldable import qualified Data.HashMap.Strict as HashMap import Data.List (sortOn,isInfixOf) --- import Data.Streaming.Network (HostPreference) import qualified Data.Text as T import qualified Data.Text.Encoding as T import Data.Tree From 409587754a4aeb010745abf42913e4ffb87499bf Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 9 Jul 2020 12:51:56 -0400 Subject: [PATCH 44/48] update header --- src/Chainweb/Rosetta/Utils.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Chainweb/Rosetta/Utils.hs b/src/Chainweb/Rosetta/Utils.hs index 064d455389..c10fc737f0 100644 --- a/src/Chainweb/Rosetta/Utils.hs +++ b/src/Chainweb/Rosetta/Utils.hs @@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} -- | --- Module: Chainweb.Rosetta.Util +-- Module: Chainweb.Rosetta.Utils -- Copyright: Copyright © 2018 - 2020 Kadena LLC. -- License: MIT -- Maintainer: Linda Ortega From c906aa004e5e91b8f32684e5f1fb3daeac0cadd9 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 9 Jul 2020 13:45:45 -0400 Subject: [PATCH 45/48] remove some cruft --- test/Chainweb/Test/Rosetta/RestAPI.hs | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index a2dea7ce81..c7fec91e5c 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -122,7 +122,7 @@ accountBalanceTests tio envIo = resp1 <- accountBalance cenv req checkBalance resp1 99999998.9453 where - req = AccountBalanceReq nid aid Nothing + req = AccountBalanceReq nid (AccountId "sender00" Nothing Nothing) Nothing checkBalance resp bal1 = do let b0 = head $ _accountBalanceResp_balances resp @@ -374,24 +374,11 @@ networkStatusTests tio envIo = kda :: Currency kda = Currency "KDA" 12 Nothing -snid :: SubNetworkId -snid = SubNetworkId - { _subNetworkId_metadata = Nothing - , _subNetworkId_network = "0" - } - nid :: NetworkId nid = NetworkId { _networkId_blockchain = "kadena" , _networkId_network = "fastTimedCPM-peterson" - , _networkId_subNetworkId = Just snid - } - -aid :: AccountId -aid = AccountId - { _accountId_address = "sender00" - , _accountId_subAccount = Nothing - , _accountId_metadata = Nothing + , _networkId_subNetworkId = Just (SubNetworkId "0" Nothing) } genesisId :: BlockId @@ -400,7 +387,7 @@ genesisId = BlockId 0 "rdfJIktp_WL0oMr8Wr6lH49YkERAJ9MlFp0RPLMXPDE" rosettaVersion :: RosettaNodeVersion rosettaVersion = RosettaNodeVersion { _version_rosettaVersion = "1.3.1" - , _version_nodeVersion = "1.9" + , _version_nodeVersion = "2.0" , _version_middlewareVersion = Nothing , _version_metadata = Just $ HM.fromList [ "node-api-version" A..= ("0.0" :: Text) From 3697c8415004efc64d7876c33e9013bd34a3d662 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 9 Jul 2020 16:15:35 -0400 Subject: [PATCH 46/48] Update test/Chainweb/Test/Rosetta/RestAPI.hs Co-authored-by: Linda Ortega --- test/Chainweb/Test/Rosetta/RestAPI.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index c7fec91e5c..c57e9c2203 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -412,7 +412,7 @@ operationStatuses = -- validateOp :: Word64 - -- ^ tx idx + -- ^ op idx -> Text -- ^ operation type -> Text From e2cefe9b1bb8d6a758063041f9001990bdbd6cea Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 9 Jul 2020 16:39:32 -0400 Subject: [PATCH 47/48] address linda's comments --- test/Chainweb/Test/Rosetta/RestAPI.hs | 28 +++++++++++---------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index c57e9c2203..0d25329e7d 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -328,20 +328,16 @@ networkOptionsTests _ envIo = version @=? rosettaVersion step "Check that response errors are a subset of valid errors" - (respErrors resp `subset` rosettaFailures) @? - "allowable errors must coincide with failure list" + respErrors resp @?= rosettaFailures step "Check that response statuses are a subset of valid statuses" - (_allow_operationStatuses allow `subset` operationStatuses) @? - "allowed operation statuses coincide" + _allow_operationStatuses allow @?= operationStatuses step "Check that response op types are a subset of op types" - (_allow_operationTypes allow `subset` allowedOperations) @? - "allowed operations coincide" + _allow_operationTypes allow @?= operationTypes where req0 = NetworkReq nid Nothing respErrors = _allow_errors . _networkOptionsResp_allow - allowedOperations = _operationStatus_status <$> operationStatuses -- | Rosetta network status tests -- @@ -402,10 +398,14 @@ operationStatuses :: [OperationStatus] operationStatuses = [ OperationStatus "Successful" True , OperationStatus "Remediation" True - , OperationStatus "CoinbaseReward" True - , OperationStatus "FundTx" True - , OperationStatus "GasPayment" True - , OperationStatus "TransferOrCreateAcct" True + ] + +operationTypes :: [Text] +operationTypes = + [ "CoinbaseReward" + , "FundTx" + , "GasPayment" + , "TransferOrCreateAcct" ] -- | Validate all useful data for a tx operation @@ -492,12 +492,6 @@ extractMetadata rk (PollResponses pr) = case HM.lookup rk pr of _ -> assertFailure "impossible: empty metadata" _ -> assertFailure "test transfer did not succeed" --- | Tell whether a list is a subset of --- another list --- -subset :: (Foldable f, Eq a) => f a -> f a -> Bool -subset as bs = all (`elem` bs) as - -- | A composition of an index into a k-v structure with aeson values -- and conversion to non-JSONified structured, asserting test failure if -- it fails to decode as the give type @a@. From 79ce35df2c5e3d33d7b68eb8caa845ccd7271713 Mon Sep 17 00:00:00 2001 From: Emily Pillmore Date: Thu, 9 Jul 2020 16:42:24 -0400 Subject: [PATCH 48/48] add note --- test/Chainweb/Test/Rosetta/RestAPI.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/Chainweb/Test/Rosetta/RestAPI.hs b/test/Chainweb/Test/Rosetta/RestAPI.hs index 0d25329e7d..626da1ea6a 100644 --- a/test/Chainweb/Test/Rosetta/RestAPI.hs +++ b/test/Chainweb/Test/Rosetta/RestAPI.hs @@ -93,6 +93,12 @@ tests rdb = testGroupSch "Chainweb.Test.Rosetta.RestAPI" go -- * Mempool Transaction: cant test reasonably without DOS'ing the mempool -- * Construction Metadata: N/A -- + -- Note: + -- + -- * Tests run in sequence, but still interact with each other because + -- confirmation depths are not validated for each tx. Checking account + -- balances between two different tests is futile. + -- tgroup tio envIo = fmap (\test -> test tio envIo) [ accountBalanceTests