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

Import schnorrkel plutus #1742

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
22 changes: 22 additions & 0 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,25 @@ program-options
constraints:
quickcheck-instances==0.3.31,
data-default==0.7.1.3

source-repository-package
type: git
location: https://github.com/locallycompact/cardano-base
tag: 1a800a0c1392935256aebabf6c1fdefe5e8b34ae
--sha256: sha256-LXYzVyWHWBS361NR4pL/Jbilnv48z6ZozltaL2/ym2s=
subdir:
cardano-crypto-class

source-repository-package
type: git
location: https://github.com/locallycompact/plutus
tag: b117b4460b5b5da2a599db8693b18dacd811bb91
--sha256: sha256-GUPwIwbTOy/eTBhjOwrR+XwJsML/jmBlAf1qU6zWvd8=
subdir:
prettyprinter-configurable
plutus-core
plutus-ledger-api
plutus-tx-plugin
plutus-tx

allow-newer: cardano-crypto-class
103 changes: 102 additions & 1 deletion hydra-cluster/src/Hydra/Cluster/Scenarios.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import CardanoClient (
QueryPoint (QueryTip),
RunningNode (..),
buildTransaction,
buildTransactionWithBody,
queryProtocolParameters,
queryTip,
queryUTxOFor,
submitTx,
Expand Down Expand Up @@ -42,6 +44,9 @@ import Hydra.Cardano.Api (
TxId,
UTxO,
addTxIns,
addTxInsCollateral,
addTxOuts,
createAndValidateTransactionBody,
defaultTxBodyContent,
getTxBody,
getTxId,
Expand All @@ -51,10 +56,13 @@ import Hydra.Cardano.Api (
mkScriptAddress,
mkScriptDatum,
mkScriptWitness,
mkTxIn,
mkTxOutAutoBalance,
mkTxOutDatumHash,
mkVkAddress,
scriptWitnessInCtx,
selectLovelace,
setTxFee,
signTx,
toScriptData,
txOutValue,
Expand All @@ -66,6 +74,7 @@ import Hydra.Cardano.Api (
pattern TxOut,
pattern TxOutDatumNone,
)
import Hydra.Cardano.Api.Pretty (renderTxWithUTxO)
import Hydra.Cluster.Faucet (FaucetLog, createOutputAtAddress, seedFromFaucet, seedFromFaucet_)
import Hydra.Cluster.Faucet qualified as Faucet
import Hydra.Cluster.Fixture (Actor (..), actorName, alice, aliceSk, aliceVk, bob, bobSk, bobVk, carol, carolSk)
Expand All @@ -77,7 +86,7 @@ import Hydra.Logging (Tracer, traceWith)
import Hydra.Options (DirectChainConfig (..), networkId, startChainFrom)
import Hydra.Tx (HeadId, IsTx (balance), Party, txId)
import Hydra.Tx.ContestationPeriod (ContestationPeriod (UnsafeContestationPeriod), fromNominalDiffTime)
import Hydra.Tx.Utils (dummyValidatorScript, verificationKeyToOnChainId)
import Hydra.Tx.Utils (dummyValidatorScript, schnorrkelValidatorScript, verificationKeyToOnChainId)
import HydraNode (
HydraClient (..),
HydraNodeLog,
Expand Down Expand Up @@ -381,6 +390,98 @@ singlePartyCommitsFromExternal tracer workDir node hydraScriptsTxId =
where
RunningNode{nodeSocket, blockTime} = node

singlePartyUsesSchnorrkelScriptOnL2 ::
Tracer IO EndToEndLog ->
FilePath ->
RunningNode ->
[TxId] ->
IO ()
singlePartyUsesSchnorrkelScriptOnL2 tracer workDir node hydraScriptsTxId =
( `finally`
do
returnFundsToFaucet tracer node Alice
returnFundsToFaucet tracer node AliceFunds
)
$ do
refuelIfNeeded tracer node Alice 250_000_000
aliceChainConfig <- chainConfigFor Alice workDir nodeSocket hydraScriptsTxId [] $ UnsafeContestationPeriod 100
let hydraNodeId = 1
let hydraTracer = contramap FromHydraNode tracer
withHydraNode hydraTracer aliceChainConfig workDir hydraNodeId aliceSk [] [1] $ \n1 -> do
send n1 $ input "Init" []
headId <- waitMatch (10 * blockTime) n1 $ headIsInitializingWith (Set.fromList [alice])

(walletVk, walletSk) <- keysFor AliceFunds

-- Create money on L1
utxoToCommit <- seedFromFaucet node walletVk 100_000_000 (contramap FromFaucet tracer)

-- Push it into L2
requestCommitTx n1 utxoToCommit
<&> signTx walletSk >>= \tx -> do
submitTx node tx

-- Check UTxO is present in L2
waitFor hydraTracer (10 * blockTime) [n1] $
output "HeadIsOpen" ["utxo" .= toJSON utxoToCommit, "headId" .= headId]

pparams <- queryProtocolParameters networkId nodeSocket QueryTip

-- Send the UTxO to a script; in preparation for running the script
let serializedScript = dummyValidatorScript
-- TODO: Use this one.
-- let serializedScript = schnorrkelValidatorScript
let scriptAddress = mkScriptAddress networkId serializedScript
let scriptOutput =
mkTxOutAutoBalance
pparams
scriptAddress
(lovelaceToValue 0) -- Autobalanced
(mkTxOutDatumHash ())
ReferenceScriptNone

Right tx <- buildTransaction networkId nodeSocket (mkVkAddress networkId walletVk) utxoToCommit [] [scriptOutput]

let signedL2tx = signTx walletSk tx
send n1 $ input "NewTx" ["transaction" .= signedL2tx]

waitMatch 10 n1 $ \v -> do
guard $ v ^? key "tag" == Just "SnapshotConfirmed"
guard $
toJSON signedL2tx
`elem` (v ^.. key "snapshot" . key "confirmed" . values)

-- Finally, take money from the script
let scriptWitness =
BuildTxWith $
ScriptWitness scriptWitnessInCtx $
mkScriptWitness serializedScript (mkScriptDatum ()) (toScriptData ())

-- Note: Bug! autobalancing breaks the script business
-- tx <- either (failure . show) pure =<< buildTransactionWithBody networkId nodeSocket (mkVkAddress networkId walletVk) body utxoToCommit

let txIn = mkTxIn signedL2tx 0
let body =
defaultTxBodyContent
& addTxIns [(txIn, scriptWitness)]

-- Note: Fix! Use `createAndValidateTransactionBody` instead. This
-- means we _can_ construct the tx; but it doesn't submit (because it
-- isn't balanced! And it's missing collateral, etc...
txBody <- either (failure . show) pure (createAndValidateTransactionBody body)
let tx = makeSignedTransaction [] txBody
let signedL2tx = signTx walletSk tx

send n1 $ input "NewTx" ["transaction" .= signedL2tx]

waitMatch 10 n1 $ \v -> do
guard $ v ^? key "tag" == Just "SnapshotConfirmed"
guard $
toJSON signedL2tx
`elem` (v ^.. key "snapshot" . key "confirmed" . values)
where
RunningNode{networkId, nodeSocket, blockTime} = node

singlePartyCommitsScriptBlueprint ::
Tracer IO EndToEndLog ->
FilePath ->
Expand Down
6 changes: 6 additions & 0 deletions hydra-cluster/test/Test/EndToEndSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import Hydra.Cluster.Scenarios (
singlePartyCommitsFromExternalTxBlueprint,
singlePartyCommitsScriptBlueprint,
singlePartyHeadFullLifeCycle,
singlePartyUsesSchnorrkelScriptOnL2,
testPreventResumeReconfiguredPeer,
threeNodesNoErrorsOnOpen,
)
Expand Down Expand Up @@ -178,6 +179,11 @@ spec = around (showLogsOnFailure "EndToEndSpec") $ do
withCardanoNodeDevnet (contramap FromCardanoNode tracer) tmpDir $ \node ->
publishHydraScriptsAs node Faucet
>>= singlePartyCommitsFromExternal tracer tmpDir node
it "can use a schnorrkel script on L2" $ \tracer -> do
withClusterTempDir $ \tmpDir -> do
withCardanoNodeDevnet (contramap FromCardanoNode tracer) tmpDir $ \node ->
publishHydraScriptsAs node Faucet
>>= singlePartyUsesSchnorrkelScriptOnL2 tracer tmpDir node
it "can submit a signed user transaction" $ \tracer -> do
withClusterTempDir $ \tmpDir -> do
withCardanoNodeDevnet (contramap FromCardanoNode tracer) tmpDir $ \node ->
Expand Down
40 changes: 28 additions & 12 deletions hydra-node/src/Hydra/Chain/CardanoClient.hs
Original file line number Diff line number Diff line change
Expand Up @@ -63,26 +63,19 @@ mkCardanoClient networkId nodeSocket =

-- * Tx Construction / Submission

-- | Construct a simple payment consuming some inputs and producing some
-- outputs (no certificates or withdrawals involved).
--
-- On success, the returned transaction is fully balanced. On error, return
-- `TxBodyErrorAutoBalance`.
buildTransaction ::
buildTransactionWithBody ::
-- | Current network identifier
NetworkId ->
-- | Filepath to the cardano-node's domain socket
SocketPath ->
-- | Change address to send
AddressInEra ->
-- | Body
TxBodyContent BuildTx ->
-- | Unspent transaction outputs to spend.
UTxO ->
-- | Collateral inputs.
[TxIn] ->
-- | Outputs to create.
[TxOut CtxTx] ->
IO (Either (TxBodyErrorAutoBalance Era) Tx)
buildTransaction networkId socket changeAddress utxoToSpend collateral outs = do
buildTransactionWithBody networkId socket changeAddress body utxoToSpend = do
pparams <- queryProtocolParameters networkId socket QueryTip
systemStart <- querySystemStart networkId socket QueryTip
eraHistory <- queryEraHistory networkId socket QueryTip
Expand All @@ -98,9 +91,32 @@ buildTransaction networkId socket changeAddress utxoToSpend collateral outs = do
mempty
mempty
(UTxO.toApi utxoToSpend)
(bodyContent pparams)
body
changeAddress
Nothing

-- | Construct a simple payment consuming some inputs and producing some
-- outputs (no certificates or withdrawals involved).
--
-- On success, the returned transaction is fully balanced. On error, return
-- `TxBodyErrorAutoBalance`.
buildTransaction ::
-- | Current network identifier
NetworkId ->
-- | Filepath to the cardano-node's domain socket
SocketPath ->
-- | Change address to send
AddressInEra ->
-- | Unspent transaction outputs to spend.
UTxO ->
-- | Collateral inputs.
[TxIn] ->
-- | Outputs to create.
[TxOut CtxTx] ->
IO (Either (TxBodyErrorAutoBalance Era) Tx)
buildTransaction networkId socket changeAddress utxoToSpend collateral outs = do
pparams <- queryProtocolParameters networkId socket QueryTip
buildTransactionWithBody networkId socket changeAddress (bodyContent pparams) utxoToSpend
where
-- NOTE: 'makeTransactionBodyAutoBalance' overwrites this.
dummyFeeForBalancing = TxFeeExplicit 0
Expand Down
18 changes: 17 additions & 1 deletion hydra-plutus/src/Hydra/Contract/Dummy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,28 @@

module Hydra.Contract.Dummy where

import Hydra.Prelude
import Hydra.Cardano.Api (PlutusScriptVersion (PlutusScriptV3))
import Hydra.Plutus.Extras (ValidatorType, scriptValidatorHash, wrapValidator)
import Hydra.Prelude hiding ((==))

import Hydra.Cardano.Api (PlutusScript, pattern PlutusScriptSerialised)
import Hydra.Plutus.Extras (ValidatorType, wrapValidator)
import PlutusLedgerApi.V3 (BuiltinData, ScriptContext, serialiseCompiledCode, toOpaque)
import PlutusTx (CompiledCode, compile)
import PlutusTx.Builtins (schnorrkel)
import PlutusTx.Prelude (Eq (..))

schnorrkelValidator :: BuiltinData -> BuiltinData -> ScriptContext -> Bool
schnorrkelValidator _ _ _ = "" == schnorrkel ""

schnorrkelValidatorScript :: PlutusScript
schnorrkelValidatorScript = PlutusScriptSerialised $ serialiseCompiledCode compiledDummyValidator

compiledSchnorrkelValidator :: CompiledCode ValidatorType
compiledSchnorrkelValidator =
$$(PlutusTx.compile [||fakeWrap schnorrkelValidator||])
where
wrap = wrapValidator @BuiltinData @BuiltinData

dummyValidator :: BuiltinData -> BuiltinData -> ScriptContext -> Bool
dummyValidator _ _ _ = True
Expand Down
4 changes: 4 additions & 0 deletions hydra-tx/src/Hydra/Ledger/Cardano/Builder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ addTxInsSpending :: [TxIn] -> TxBodyContent BuildTx -> TxBodyContent BuildTx
addTxInsSpending ins =
addTxIns ((,BuildTxWith $ KeyWitness KeyWitnessForSpending) <$> ins)

changePParams :: PParams (ShelleyLedgerEra Era) -> TxBodyContent BuildTx -> TxBodyContent BuildTx
changePParams pparams tx =
tx{txProtocolParams = BuildTxWith $ Just $ LedgerProtocolParameters pparams}

-- | Mint tokens with given plutus minting script and redeemer.
mintTokens :: ToScriptData redeemer => PlutusScript -> redeemer -> [(AssetName, Quantity)] -> TxBodyContent BuildTx -> TxBodyContent BuildTx
mintTokens script redeemer assets = addTxMintValue newTokens
Expand Down
3 changes: 2 additions & 1 deletion hydra-tx/src/Hydra/Tx/Utils.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Hydra.Tx.Utils (
module Hydra.Tx.Utils,
dummyValidatorScript,
schnorrkelValidatorScript,
) where

import Hydra.Cardano.Api
Expand All @@ -13,7 +14,7 @@ import Control.Lens ((.~), (^.))
import Data.Map.Strict qualified as Map
import Data.Maybe.Strict (StrictMaybe (..))
import GHC.IsList (IsList (..))
import Hydra.Contract.Dummy (dummyValidatorScript)
import Hydra.Contract.Dummy (dummyValidatorScript, schnorrkelValidatorScript)
import Hydra.Contract.Util (hydraHeadV1)
import Hydra.Tx.OnChainId (OnChainId (..))
import Ouroboros.Consensus.Shelley.Eras qualified as Ledger
Expand Down
Loading