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

Externally commit script utxo #903

Merged
merged 75 commits into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
150135d
Create another external commit scenario for scripts
ffakenz May 26, 2023
8050947
WIP: draft a spending tx for script
ch1bo May 26, 2023
16c538c
Follow up on temporary sanity check: Spend the script on L1
ffakenz May 27, 2023
196ce32
Fix script tx to be spent on L1
ffakenz May 30, 2023
cf8183d
Add script info as part of draft commit tx request
ffakenz Jun 1, 2023
f09a597
Add protocol parameters, systemStart and epochInfo as arguments to mk…
ffakenz Jun 2, 2023
d3fa15a
Minor formatting change
ffakenz Jun 2, 2023
3d43a47
Split commitTx into tx body builder and tx builder
ffakenz Jun 2, 2023
535589e
Finish commit external script e2e spec
ffakenz Jun 2, 2023
1f1c32e
Minor formatting changes
ffakenz Jun 2, 2023
275cd3d
Fix golden files for rest server
ffakenz Jun 5, 2023
0c5dc65
Make collateral to come from the node
ffakenz Jun 6, 2023
315ba70
Remove extra param to draftScriptTx
v0d1ch Jun 7, 2023
492c06e
Commit from two script utxos
v0d1ch Jun 7, 2023
02437fb
WIP: Start to model proper type for committing multiple scripts
v0d1ch Jun 7, 2023
9706c83
Fix collateralTxIns to use the internal wallet utxo instead of the he…
ffakenz Jun 7, 2023
fb65055
Alter api to be able to draft a commit using multiple scripts
ffakenz Jun 7, 2023
936351d
WIP: Working scripts commit with mempty user utxo
v0d1ch Jun 7, 2023
83cf07f
WIP: Working scripts commit with mempty user utxo
ffakenz Jun 8, 2023
f92a62d
Generalize draftTx to work both for regular and script utxo
ffakenz Jun 8, 2023
97047da
Check we can draft a commit tx using many regular and many script utxos
ffakenz Jun 8, 2023
69dd93f
Remove collateralTxIns and pparams from draftTx
ffakenz Jun 8, 2023
56b84f5
Unify types in draft commit tx request to not be cardano specific
ffakenz Jun 8, 2023
5ff5857
Reject commit transaction requests including UTxO addressed to the in…
v0d1ch Jun 9, 2023
24c9e8d
WIP: Remove tags from http server types
v0d1ch Jun 8, 2023
1bb4e46
Add tag to request as it is needed to validate the api schema.
ffakenz Jun 12, 2023
bb4c7c7
Add plain old json schema validation for draft commit request
ffakenz Jun 12, 2023
c993ab3
WIP: Draft a prop_validateJSONSchema function
ch1bo Jun 12, 2023
899fa08
Remove tag from request + Fix api schema validation for /commit
ffakenz Jun 12, 2023
3c3f45b
Fix logs and rest api schema validation.
ffakenz Jun 13, 2023
d9d6f92
PR review: Alter the RestServer DraftUTxO type
v0d1ch Jun 13, 2023
85c775f
Apply review request
ffakenz Jun 14, 2023
e21e203
Simplify draftCommitTx handler signature to take ScriptWitness instea…
ffakenz Jun 14, 2023
7a07aad
Refactor draftCommitTx to be simpler as per request for review
ffakenz Jun 14, 2023
8da0a39
Alter PlutusV2Script api entry
v0d1ch Jun 14, 2023
a5144af
Do not use ReasonablySized for DraftCommitTxResponse test
v0d1ch Jun 14, 2023
7f63ef2
Rename FailedToDraftTxWalletUtxoDetected to SpendingNodeUtxoForbidden
v0d1ch Jun 14, 2023
f31f33e
Simplify the way we create script outputs
v0d1ch Jun 14, 2023
44740ba
Remove api.yaml mention from the file itself
v0d1ch Jun 15, 2023
502d95a
Do not validate http endpoints and re-generate DraftCommitTxResponse
v0d1ch Jun 15, 2023
8cfaffe
Improve on api docs display and add missing docusaurus logger
v0d1ch Jun 15, 2023
6018ed6
Don't pass faucet pub key, query for it inside of a function.
v0d1ch Jun 15, 2023
5afdee1
Reduce temp folder name length
v0d1ch Jun 15, 2023
b60e549
Update schema path
v0d1ch Jun 15, 2023
a6cc66a
Rebase fix
v0d1ch Jun 15, 2023
c157837
Remove unnecessary comment on chain module
ffakenz Jun 20, 2023
c51fa43
Replace DraftUTxO with a UTxO like type with witness
ffakenz Jun 20, 2023
841293e
Add deriving json instance on UTxO'
ffakenz Jun 21, 2023
fad1fd8
Include an example for a draft commit api request
ffakenz Jun 21, 2023
cfacdfa
Fix after rebase
ffakenz Jun 21, 2023
861ceb1
Refactor draftCommitTx interface to take UTxO' like type as argument …
ffakenz Jun 21, 2023
b743123
Fix examples for draft commit request in api yaml
ffakenz Jun 21, 2023
0bdcab3
Update hydra-node/json-schemas/api.yaml
ffakenz Jun 23, 2023
1013af3
Update hydra-node/src/Hydra/Chain.hs
ffakenz Jun 23, 2023
0c0f212
Update hydra-node/test/Hydra/JSONSchema.hs
ffakenz Jun 23, 2023
54c8ac6
Update hydra-node/json-schemas/api.yaml
ffakenz Jun 23, 2023
0fb2c36
Update hydra-node/json-schemas/api.yaml
ffakenz Jun 23, 2023
482cc00
Apply first round of request for review
ffakenz Jun 23, 2023
27d5fb8
Remove http-conduit and http-types in favor of http-client
v0d1ch Jun 23, 2023
10d7a4a
Pass full file name with extension to JSONSchema property validations
ffakenz Jun 23, 2023
e352c04
Make externalCommit function accept `UTxO' TxOutWithWitness`
v0d1ch Jun 23, 2023
9581551
Be clear we are using 4 utxos
v0d1ch Jun 23, 2023
28ec806
WIP: remove rawCommitTxBody function
v0d1ch Jun 26, 2023
c688d5a
Generate script inputs arbitrarily
ffakenz Jun 26, 2023
bd4b511
Alter the api.yaml type for utxos
v0d1ch Jun 26, 2023
2de83ac
Remove abstract tx type param and use a fixed Tx type in DraftCommitT…
v0d1ch Jun 26, 2023
f2594da
Document possible responses
v0d1ch Jun 26, 2023
8597b0b
PR review comments
v0d1ch Jun 26, 2023
627f678
Change signature of commitTx and commit functions
ch1bo Jun 26, 2023
0baafbd
Simplify commit scripts from external e2e scenario
ch1bo Jun 26, 2023
859ae45
Fix ScriptData instances
ch1bo Jun 26, 2023
6c4c428
Use prop_validateJSONSchema in HydraLoggingSpec
ch1bo Jun 26, 2023
d2d11ba
Remove commented code
ffakenz Jun 27, 2023
5a9845b
Introduce a wrapper around externalCommit
v0d1ch Jun 27, 2023
cc4ab7d
Remove HasCallstack
v0d1ch Jun 27, 2023
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
4 changes: 1 addition & 3 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
"start": "yarn dummy-spec && docusaurus start",
"validate:inputs": "./validate-api.js publish '/' '../hydra-node/golden/ReasonablySized (ClientInput (Tx BabbageEra)).json'",
"validate:outputs": "./validate-api.js subscribe '/' '../hydra-node/golden/ReasonablySized (TimedServerOutput (Tx BabbageEra)).json'",
"validate:commit-inputs": "./validate-api.js publish '/commit' '../hydra-node/golden/ReasonablySized (DraftCommitTxRequest (Tx BabbageEra)).json'",
"validate:commit-outputs": "./validate-api.js subscribe '/commit' '../hydra-node/golden/ReasonablySized (DraftCommitTxResponse (Tx BabbageEra)).json'",
"validate": "yarn validate:inputs && yarn validate:outputs && yarn validate:commit-inputs && yarn validate:commit-outputs",
"validate": "yarn validate:inputs && yarn validate:outputs",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
Expand Down
4 changes: 3 additions & 1 deletion hydra-cardano-api/src/Cardano/Api/UTxO.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ newtype UTxO' out = UTxO
, Foldable
, Semigroup
, Monoid
, ToJSON
, FromJSON
)

instance Traversable UTxO' where
Expand All @@ -46,7 +48,7 @@ fromPairs :: [(TxIn, out)] -> UTxO' out
fromPairs = UTxO . Map.fromList

-- | Create a 'UTxO' from a single unspent transaction output.
singleton :: (TxIn, TxOut CtxUTxO Era) -> UTxO
singleton :: (TxIn, out) -> UTxO' out
singleton (i, o) = UTxO $ Map.singleton i o

-- | Find an 'out' for a given 'TxIn'.
Expand Down
6 changes: 6 additions & 0 deletions hydra-cardano-api/src/Hydra/Cardano/Api/PlutusScript.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import Hydra.Cardano.Api.Prelude

import qualified Cardano.Ledger.Alonzo.Language as Ledger
import qualified Cardano.Ledger.Alonzo.Scripts as Ledger
import qualified Data.ByteString.Short as SBS
import qualified PlutusLedgerApi.Common as Plutus
import Test.QuickCheck (listOf)

-- * Type Conversions

Expand Down Expand Up @@ -49,3 +51,7 @@ instance IsPlutusScriptLanguage lang => FromJSON (PlutusScript lang) where
case deserialiseFromTextEnvelope (proxyToAsType Proxy) env of
Left e -> fail $ show e
Right a -> pure a

instance Arbitrary (PlutusScript lang) where
arbitrary =
PlutusScriptSerialised . SBS.pack <$> listOf arbitrary
33 changes: 26 additions & 7 deletions hydra-cardano-api/src/Hydra/Cardano/Api/ScriptData.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import qualified Cardano.Ledger.Alonzo.Data as Ledger
import qualified Cardano.Ledger.Alonzo.TxWitness as Ledger
import Codec.Serialise (deserialiseOrFail, serialise)
import Control.Arrow (left)
import Data.Aeson (Value (String))
import Data.Aeson (Value (String), withText)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Base16 as Base16
import qualified Data.Map as Map
import qualified PlutusLedgerApi.V2 as Plutus
import Test.QuickCheck (arbitrarySizedNatural, choose, oneof, scale, sized, vector)

-- * Extras

Expand Down Expand Up @@ -96,13 +98,30 @@ instance FromJSON ScriptData where
bytes <- Base16.decode (encodeUtf8 text)
left show $ deserialiseOrFail $ fromStrict bytes

-- NOTE: We are okay with storing the data and re-serializing + hashing it into
-- 'HashableScriptData' in these ToJSON/FromJSON instances as the serialization
-- ambiguity addressed by 'HashableScriptData' is long overboard if we are
-- dealing with JSON.
instance Arbitrary ScriptData where
arbitrary =
scale (`div` 2) $
oneof
[ ScriptDataConstructor <$> arbitrarySizedNatural <*> arbitrary
, ScriptDataNumber <$> arbitrary
, ScriptDataBytes <$> arbitraryBS
, ScriptDataList <$> arbitrary
, ScriptDataMap <$> arbitrary
]
where
arbitraryBS = sized $ \n ->
BS.pack <$> (choose (0, min n 64) >>= vector)

instance ToJSON HashableScriptData where
toJSON = toJSON . getScriptData
toJSON = String . decodeUtf8 . Base16.encode . serialiseToCBOR

instance FromJSON HashableScriptData where
parseJSON = fmap unsafeHashableScriptData . parseJSON
parseJSON =
withText "HashableScriptData" $ \text -> do
bytes <- either (fail . show) pure $ Base16.decode $ encodeUtf8 text
either (fail . show) pure $ deserialiseFromCBOR (proxyToAsType Proxy) bytes

instance Arbitrary HashableScriptData where
arbitrary =
-- NOTE: Safe to use here as the data was not available in serialized form.
unsafeHashableScriptData <$> arbitrary
4 changes: 3 additions & 1 deletion hydra-cluster/hydra-cluster.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ library
, directory
, filepath
, hspec-expectations
, http-client
, hydra-cardano-api
, hydra-node
, hydra-plutus
Expand All @@ -159,6 +160,7 @@ library
, unix
, unordered-containers
, websockets
, plutus-ledger-api:{plutus-ledger-api, plutus-ledger-api-testlib} >=1.1.1.0

ghc-options: -haddock

Expand Down Expand Up @@ -238,7 +240,7 @@ test-suite tests
, lens
, lens-aeson
, ouroboros-network
, plutus-ledger-api
, plutus-ledger-api:{plutus-ledger-api, plutus-ledger-api-testlib} >=1.1.1.0
, process
, QuickCheck
, say
Expand Down
68 changes: 57 additions & 11 deletions hydra-cluster/src/Hydra/Cluster/Faucet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Hydra.Cluster.Faucet where

import Hydra.Cardano.Api
import Hydra.Prelude
import Test.Hydra.Prelude

import qualified Cardano.Api.UTxO as UTxO
import CardanoClient (
Expand All @@ -24,7 +25,7 @@ import CardanoNode (RunningNode (..))
import Control.Exception (IOException)
import Control.Monad.Class.MonadThrow (Handler (Handler), catches)
import Control.Tracer (Tracer, traceWith)
import qualified Data.Map as Map
import qualified Data.Map.Strict as Map
import GHC.IO.Exception (IOErrorType (ResourceExhausted), IOException (ioe_type))
import Hydra.Chain.Direct.ScriptRegistry (
publishHydraScripts,
Expand Down Expand Up @@ -62,27 +63,19 @@ seedFromFaucet ::
Marked ->
Tracer IO FaucetLog ->
IO UTxO
seedFromFaucet RunningNode{networkId, nodeSocket} receivingVerificationKey lovelace marked tracer = do
seedFromFaucet node@RunningNode{networkId, nodeSocket} receivingVerificationKey lovelace marked tracer = do
(faucetVk, faucetSk) <- keysFor Faucet
retryOnExceptions tracer $ submitSeedTx faucetVk faucetSk
waitForPayment networkId nodeSocket lovelace receivingAddress
where
submitSeedTx faucetVk faucetSk = do
faucetUTxO <- findUTxO faucetVk
faucetUTxO <- findFaucetUTxO node lovelace
let changeAddress = ShelleyAddressInEra (buildAddress faucetVk networkId)
buildTransaction networkId nodeSocket changeAddress faucetUTxO [] [theOutput] >>= \case
Left e -> throwIO $ FaucetFailedToBuildTx{reason = e}
Right body -> do
submitTransaction networkId nodeSocket (sign faucetSk body)

findUTxO faucetVk = do
faucetUTxO <- queryUTxO networkId nodeSocket QueryTip [buildAddress faucetVk networkId]
let foundUTxO = UTxO.filter (\o -> txOutLovelace o >= lovelace) faucetUTxO
when (null foundUTxO) $
throwIO $
FaucetHasNotEnoughFunds{faucetUTxO}
pure foundUTxO

receivingAddress = buildAddress receivingVerificationKey networkId

theOutput =
Expand All @@ -96,6 +89,16 @@ seedFromFaucet RunningNode{networkId, nodeSocket} receivingVerificationKey lovel
Fuel -> TxOutDatumHash markerDatumHash
Normal -> TxOutDatumNone

findFaucetUTxO :: RunningNode -> Lovelace -> IO UTxO
findFaucetUTxO RunningNode{networkId, nodeSocket} lovelace = do
(faucetVk, _) <- keysFor Faucet
faucetUTxO <- queryUTxO networkId nodeSocket QueryTip [buildAddress faucetVk networkId]
let foundUTxO = UTxO.filter (\o -> txOutLovelace o >= lovelace) faucetUTxO
when (null foundUTxO) $
throwIO $
FaucetHasNotEnoughFunds{faucetUTxO}
pure foundUTxO

-- | Like 'seedFromFaucet', but without returning the seeded 'UTxO'.
seedFromFaucet_ ::
RunningNode ->
Expand Down Expand Up @@ -140,6 +143,49 @@ returnFundsToFaucet tracer node@RunningNode{networkId, nodeSocket} sender = do
Left e -> throwIO $ FaucetFailedToBuildTx{reason = e}
Right body -> pure body

-- Use the Faucet utxo to create the output at specified address
createOutputAtAddress ::
ToScriptData a =>
RunningNode ->
ProtocolParameters ->
AddressInEra ->
a ->
IO (TxIn, TxOut CtxUTxO)
createOutputAtAddress node@RunningNode{networkId, nodeSocket} pparams atAddress datum = do
(faucetVk, faucetSk) <- keysFor Faucet
-- we don't care which faucet utxo we use here so just pass lovelace 0 to grab
-- any present utxo
utxo <- findFaucetUTxO node 0
buildTransaction
networkId
nodeSocket
(changeAddress faucetVk)
utxo
collateralTxIns
[output]
>>= \case
Left e ->
throwErrorAsException e
Right body -> do
let tx = makeSignedTransaction [makeShelleyKeyWitness body (WitnessPaymentKey faucetSk)] body
submitTransaction networkId nodeSocket tx
newUtxo <- awaitTransaction networkId nodeSocket tx
case UTxO.find (\out -> txOutAddress out == atAddress) newUtxo of
Nothing -> failure $ "Could not find script output: " <> decodeUtf8 (encodePretty newUtxo)
Just u -> pure u
where
collateralTxIns = mempty

changeAddress vk = mkVkAddress networkId vk

output =
mkTxOutAutoBalance
pparams
atAddress
mempty
(mkTxOutDatumHash datum)
ReferenceScriptNone

-- | Build and sign tx and return the calculated fee.
-- - Signing key should be the key of a sender
-- - Address is used as a change address.
Expand Down
Loading