Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Increment validator and corresponding mutations #1715

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion hydra-cluster/config/devnet/genesis-shelley.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"keyDeposit": 0,
"maxBlockBodySize": 65536,
"maxBlockHeaderSize": 1100,
"maxTxSize": 16384,
"maxTxSize": 17700,
"minFeeA": 44,
"minFeeB": 155381,
"minPoolCost": 0,
Expand Down
14 changes: 8 additions & 6 deletions hydra-cluster/src/Hydra/Cluster/Faucet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,14 @@ createOutputAtAddress node@RunningNode{networkId, nodeSocket} atAddress datum va
pparams <- queryProtocolParameters networkId nodeSocket QueryTip
let collateralTxIns = mempty
let output =
mkTxOutAutoBalance
pparams
atAddress
val
datum
ReferenceScriptNone
-- TODO: improve this so we don't autobalance and then reset the value
modifyTxOutValue (const val) $
mkTxOutAutoBalance
pparams
atAddress
val
datum
ReferenceScriptNone
buildTransaction
networkId
nodeSocket
Expand Down
17 changes: 10 additions & 7 deletions hydra-cluster/src/Hydra/Cluster/Scenarios.hs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ singlePartyCommitsScriptBlueprint tracer workDir node hydraScriptsTxId =
send n1 $ input "Init" []
headId <- waitMatch (10 * blockTime) n1 $ headIsInitializingWith (Set.fromList [alice])

(clientPayload, scriptUTxO) <- prepareScriptPayload
(clientPayload, scriptUTxO) <- prepareScriptPayload 3_000_000

res <-
runReq defaultHttpConfig $
Expand All @@ -418,7 +418,7 @@ singlePartyCommitsScriptBlueprint tracer workDir node hydraScriptsTxId =
pure $ v ^? key "utxo"
lockedUTxO `shouldBe` Just (toJSON scriptUTxO)
-- incrementally commit script to a running Head
(clientPayload', scriptUTxO') <- prepareScriptPayload
(clientPayload', scriptUTxO') <- prepareScriptPayload 2_000_000

res' <-
runReq defaultHttpConfig $
Expand All @@ -444,12 +444,12 @@ singlePartyCommitsScriptBlueprint tracer workDir node hydraScriptsTxId =
waitFor hydraTracer 10 [n1] $
output "GetUTxOResponse" ["headId" .= headId, "utxo" .= (scriptUTxO <> scriptUTxO')]
where
prepareScriptPayload = do
prepareScriptPayload val = do
let script = alwaysSucceedingNAryFunction 3
let serializedScript = PlutusScriptSerialised script
let scriptAddress = mkScriptAddress networkId serializedScript
let datumHash = mkTxOutDatumHash ()
(scriptIn, scriptOut) <- createOutputAtAddress node scriptAddress datumHash (lovelaceToValue 0)
(scriptIn, scriptOut) <- createOutputAtAddress node scriptAddress datumHash (lovelaceToValue val)
let scriptUTxO = UTxO.singleton (scriptIn, scriptOut)

let scriptWitness =
Expand Down Expand Up @@ -701,7 +701,9 @@ canCommit :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO ()
canCommit tracer workDir node hydraScriptsTxId =
(`finally` returnFundsToFaucet tracer node Alice) $ do
refuelIfNeeded tracer node Alice 30_000_000
let contestationPeriod = UnsafeContestationPeriod 1
-- NOTE: it is important to provide _large_ enough contestation period so that
-- increment tx can be submitted before the deadline
let contestationPeriod = UnsafeContestationPeriod 5
aliceChainConfig <-
chainConfigFor Alice workDir nodeSocket hydraScriptsTxId [] contestationPeriod
<&> setNetworkId networkId
Expand Down Expand Up @@ -752,7 +754,7 @@ canRecoverDeposit tracer workDir node hydraScriptsTxId =
refuelIfNeeded tracer node Alice 30_000_000
refuelIfNeeded tracer node Bob 30_000_000
-- NOTE: this value is also used to determine the deposit deadline
let deadline = 1
let deadline = 5
let contestationPeriod = UnsafeContestationPeriod deadline
aliceChainConfig <-
chainConfigFor Alice workDir nodeSocket hydraScriptsTxId [Bob] contestationPeriod
Expand Down Expand Up @@ -802,7 +804,8 @@ canRecoverDeposit tracer workDir node hydraScriptsTxId =

let path = BSC.unpack $ urlEncode False $ encodeUtf8 $ T.pack $ show (getTxId $ getTxBody tx)
-- NOTE: we need to wait for the deadline to pass before we can recover the deposit
threadDelay $ fromIntegral (deadline * 2)
-- NOTE: for some reason threadDelay on MacOS behaves differently than on Linux so we need + 1 here
threadDelay $ fromIntegral (deadline * 2 + 1)

recoverResp <-
parseUrlThrow ("DELETE " <> hydraNodeBaseUrl n1 <> "/commits/" <> path)
Expand Down
54 changes: 25 additions & 29 deletions hydra-node/src/Hydra/Chain/Direct/State.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ module Hydra.Chain.Direct.State where
import Hydra.Prelude hiding (init)

import Cardano.Api.UTxO qualified as UTxO
import Data.Fixed (Milli)
import Data.Map qualified as Map
import Data.Maybe (fromJust)
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
import GHC.IsList qualified as IsList
import Hydra.Cardano.Api (
AssetId (..),
Expand Down Expand Up @@ -122,7 +120,7 @@ import Hydra.Tx.OnChainId (OnChainId)
import Hydra.Tx.Recover (recoverTx)
import Hydra.Tx.Snapshot (genConfirmedSnapshot)
import Hydra.Tx.Utils (splitUTxO, verificationKeyToOnChainId)
import Test.Hydra.Tx.Fixture (testNetworkId)
import Test.Hydra.Tx.Fixture (depositDeadline, testNetworkId)
import Test.Hydra.Tx.Gen (
genOneUTxOFor,
genScriptRegistry,
Expand Down Expand Up @@ -517,17 +515,17 @@ increment ctx spendableUTxO headId headParameters incrementingSnapshot depositTx
Just deposit
| null deposit ->
Left SnapshotIncrementUTxOIsNull
| otherwise -> Right $ incrementTx scriptRegistry ownVerificationKey headId headParameters headUTxO sn (UTxO.singleton (depositedIn, depositedOut)) upperValiditySlot
| otherwise -> Right $ incrementTx scriptRegistry ownVerificationKey headId headParameters headUTxO sn (UTxO.singleton (depositedIn, depositedOut)) upperValiditySlot sigs
where
headScript = fromPlutusScript @PlutusScriptV2 Head.validatorScript
depositScript = fromPlutusScript @PlutusScriptV2 Deposit.validatorScript

Snapshot{utxoToCommit} = sn

sn =
(sn, sigs) =
case incrementingSnapshot of
ConfirmedSnapshot{snapshot} -> snapshot
_ -> getSnapshot incrementingSnapshot
ConfirmedSnapshot{snapshot, signatures} -> (snapshot, signatures)
_ -> (getSnapshot incrementingSnapshot, mempty)

ChainContext{ownVerificationKey, scriptRegistry} = ctx

Expand Down Expand Up @@ -988,7 +986,7 @@ genChainStateWithTx =

genIncrementWithState :: Gen (ChainContext, ChainState, UTxO, Tx, ChainTransition)
genIncrementWithState = do
(ctx, _, st, utxo, tx) <- genIncrementTx maxGenParties
(ctx, st, utxo, tx) <- genIncrementTx maxGenParties
pure (ctx, Open st, utxo, tx, Increment)

genDecrementWithState :: Gen (ChainContext, ChainState, UTxO, Tx, ChainTransition)
Expand Down Expand Up @@ -1069,6 +1067,9 @@ genHydraContextFor n = do
, ctxScriptRegistry
}

instance Arbitrary HydraContext where
arbitrary = genHydraContext maxGenParties

-- | Get all peer-specific 'ChainContext's from a 'HydraContext'. NOTE: This
-- assumes that 'HydraContext' has same length 'ctxVerificationKeys' and
-- 'ctxHydraSigningKeys'.
Expand Down Expand Up @@ -1177,43 +1178,38 @@ genCollectComTx = do
let spendableUTxO = getKnownUTxO stInitialized
pure (cctx, committedUTxO, stInitialized, mempty, unsafeCollect cctx headId (ctxHeadParameters ctx) utxoToCollect spendableUTxO)

genDepositTx :: Gen (UTxO, Tx)
genDepositTx = do
ctx <- genHydraContextFor 1
genDepositTx :: Int -> Gen (HydraContext, OpenState, UTxO, Tx)
genDepositTx numParties = do
ctx <- genHydraContextFor numParties
utxo <- genUTxOAdaOnlyOfSize 1 `suchThat` (not . null)
(_, OpenState{headId}) <- genStOpen ctx
deadline <- posixSecondsToUTCTime . realToFrac <$> (arbitrary :: Gen Milli)
let tx = depositTx (ctxNetworkId ctx) headId CommitBlueprintTx{blueprintTx = txSpendingUTxO utxo, lookupUTxO = utxo} deadline
pure (utxo, tx)
(_, st@OpenState{headId}) <- genStOpen ctx
let tx = depositTx (ctxNetworkId ctx) headId CommitBlueprintTx{blueprintTx = txSpendingUTxO utxo, lookupUTxO = utxo} depositDeadline
pure (ctx, st, utxo <> utxoFromTx tx, tx)

genRecoverTx ::
Gen (UTxO, Tx)
genRecoverTx = do
(_depositedUTxO, txDeposit) <- genDepositTx
(_, _, depositedUTxO, txDeposit) <- genDepositTx 1
let DepositObservation{deposited} =
fromJust $ observeDepositTx testNetworkId txDeposit
-- TODO: generate multiple various slots after deadline
let tx = recoverTx (getTxId $ getTxBody txDeposit) deposited 100
pure (utxoFromTx txDeposit, tx)
pure (depositedUTxO, tx)

genIncrementTx :: Int -> Gen (ChainContext, [TxOut CtxUTxO], OpenState, UTxO, Tx)
genIncrementTx :: Int -> Gen (ChainContext, OpenState, UTxO, Tx)
genIncrementTx numParties = do
(_utxo, txDeposit) <- genDepositTx
ctx <- genHydraContextFor numParties
(ctx, st@OpenState{headId}, utxo, txDeposit) <- genDepositTx numParties
cctx <- pickChainContext ctx
let DepositObservation{deposited, depositTxId} = fromJust $ observeDepositTx (ctxNetworkId ctx) txDeposit
(_, st@OpenState{headId}) <- genStOpen ctx
let DepositObservation{deposited, depositTxId, deadline} = fromJust $ observeDepositTx (ctxNetworkId ctx) txDeposit
let openUTxO = getKnownUTxO st
let version = 1
snapshot <- genConfirmedSnapshot headId 2 version openUTxO (Just deposited) Nothing (ctxHydraSigningKeys ctx)
let depositUTxO = utxoFromTx txDeposit
slotNo <- arbitrary
let version = 0
snapshot <- genConfirmedSnapshot headId version 1 openUTxO (Just deposited) Nothing (ctxHydraSigningKeys ctx)
let slotNo = slotNoFromUTCTime systemStart slotLength (posixToUTCTime deadline)
pure
( cctx
, maybe mempty toList (utxoToCommit $ getSnapshot snapshot)
, st
, depositUTxO
, unsafeIncrement cctx (openUTxO <> depositUTxO) headId (ctxHeadParameters ctx) snapshot depositTxId slotNo
, utxo
, unsafeIncrement cctx (openUTxO <> utxo) headId (ctxHeadParameters ctx) snapshot depositTxId slotNo
)

genDecrementTx :: Int -> Gen (ChainContext, [TxOut CtxUTxO], OpenState, UTxO, Tx)
Expand Down
28 changes: 26 additions & 2 deletions hydra-node/test/Hydra/Chain/Direct/StateSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import Hydra.Chain.Direct.State (
genDepositTx,
genFanoutTx,
genHydraContext,
genIncrementTx,
genInitTx,
genRecoverTx,
genStInitial,
Expand Down Expand Up @@ -348,6 +349,10 @@ spec = parallel $ do
Nothing ->
False & counterexample ("observeRecoverTx ignored transaction: " <> renderTxWithUTxO utxo tx)

describe "increment" $ do
-- propBelowSizeLimit maxTxSize forAllIncrement
propIsValid forAllIncrement

describe "decrement" $ do
propBelowSizeLimit maxTxSize forAllDecrement
propIsValid forAllDecrement
Expand Down Expand Up @@ -646,7 +651,9 @@ forAllDeposit ::
(UTxO -> Tx -> property) ->
Property
forAllDeposit action = do
forAllShrink genDepositTx shrink $ uncurry action
forAllShrink (genDepositTx maximumNumberOfParties) shrink $ \(_ctx, st, depositUTxO, tx) ->
let utxo = getKnownUTxO st <> depositUTxO
in action utxo tx

forAllRecover ::
Testable property =>
Expand All @@ -655,6 +662,23 @@ forAllRecover ::
forAllRecover action = do
forAllShrink genRecoverTx shrink $ uncurry action

forAllIncrement ::
Testable property =>
(UTxO -> Tx -> property) ->
Property
forAllIncrement action = do
forAllIncrement' $ \utxo tx ->
action utxo tx

forAllIncrement' ::
Testable property =>
(UTxO -> Tx -> property) ->
Property
forAllIncrement' action = do
forAllShrink (genIncrementTx maximumNumberOfParties) shrink $ \(ctx, st, incrementUTxO, tx) ->
let utxo = getKnownUTxO st <> getKnownUTxO ctx <> incrementUTxO
in action utxo tx

forAllDecrement ::
Testable property =>
(UTxO -> Tx -> property) ->
Expand All @@ -669,7 +693,7 @@ forAllDecrement' ::
Property
forAllDecrement' action = do
forAllShrink (genDecrementTx maximumNumberOfParties) shrink $ \(ctx, distributed, st, _, tx) ->
let utxo = getKnownUTxO st <> getKnownUTxO ctx
let utxo = getKnownUTxO st <> getKnownUTxO ctx <> utxo
in action distributed utxo tx

forAllClose ::
Expand Down
Loading
Loading