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

Use a faucet to distribute funds #227

Merged
merged 29 commits into from
Feb 25, 2022
Merged

Use a faucet to distribute funds #227

merged 29 commits into from
Feb 25, 2022

Conversation

ch1bo
Copy link
Collaborator

@ch1bo ch1bo commented Feb 22, 2022

❄️ Introduce well-known Actor = Faucet | Alice | Bob | Carol keys as data type

❄️ Introduce seedFromFaucet to distribute funds from the Faucet actor, either Marked (as fuel) or Normal, which queries the faucet UTXO and spends it as requested.

❄️ Update all tests to use seedFromFaucet instead of the genesis/prepare commit transactions

❄️ Update the demo to use the same style of fund distribution in seed-devnet.sh. Drop the haskell exe for seeding to only have one way to maintain.

❄️ Benchmarks are working now. Needed to keep using mkGenesisTx and distribute funds to all clients in the benchmark dataset in one transaction.


-- | Directly retrieve the amount of 'Lovelace' stored in a 'TxOut'.
txOutLovelace :: TxOut ctx era -> Lovelace
txOutLovelace (TxOut _ v _) = txOutValueToLovelace v
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this one. Just saw that there exists selectLovelace recently. You opinions?

hydra-cluster/bench/Bench/EndToEnd.hs Outdated Show resolved Hide resolved
@ch1bo ch1bo marked this pull request as ready for review February 23, 2022 17:21
@ch1bo ch1bo mentioned this pull request Feb 24, 2022
@github-actions
Copy link

github-actions bot commented Feb 24, 2022

Unit Test Results

    6 files  ±0    76 suites  ±0   5m 56s ⏱️ -31s
200 tests ±0  198 ✔️ ±0  2 💤 ±0  0 ±0 

Results for commit e327adf. ± Comparison against base commit ac72d7b.

♻️ This comment has been updated with latest results.

@ch1bo ch1bo force-pushed the ch1bo/faucet-distribution branch 3 times, most recently from 160add8 to 1a650f2 Compare February 24, 2022 18:12
let addr = buildAddress vk defaultNetworkId
bytes = serialiseToRawBytes addr
in (encodeBase16 bytes, availableInitialFunds)

copyCredential parentDir file = do
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice cleanup in this module 🙏

Copy link
Contributor

@abailly-iohk abailly-iohk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly minor comments and suggestions to clarify naming/usage and improve readability.
I have one major concern though regarding the semantics of the genDatasetConstantUTxO which seems incorrect to me, probably because I am missing something.

seedCommit "bob" 500000000
seedCommit "carol" 250000000
seedFaucet "alice" 1000000000 # 1000 Ada to commit
seedFaucet "alice" 100000000 true # 100 Ada marked as "fuel"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Avoid "boolean blindness" and use some variable or string instead of true

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anything evaluating to "truthy" by bash's if would work here. Bash is not really typed, but I suppose I can make this "fuel" or so?

seedNetwork :: RunningNode -> Dataset -> IO ()
seedNetwork node@(RunningNode _ nodeSocket) Dataset{fundingTransaction, clientDatasets} = do
-- Submit the funding transaction first
submit defaultNetworkId nodeSocket fundingTransaction
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: remove the comment which is just paraphrasing the quite explicit line of code below

submit defaultNetworkId nodeSocket fundingTransaction
void $ waitForTransaction defaultNetworkId nodeSocket fundingTransaction
-- Then, fuel all clients with some 100 ADA
forM_ clientDatasets $ \ClientDataset{signingKey} -> do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: rather than having a comment, how about

forM_ clientDatasets fuelClientWith100Ada
  where
    fuelClientWith100Ada = ...

mconcat <$> mapConcurrently (uncurry clientProcessTransactionsSequence) processors
where
clientProcessTransactionsSequence (Dataset{transactionsSequence}, client) clientId = do
let numberOfTxs = length transactionsSequence
clientProcessTransactionsSequence (ClientDataset{txSequence}, client) clientId = do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: why rename the field transactionsSequence to txSequence? Now the clientProcessTransactionsSequence feels a bit odd.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true. I should have renamed also the function or not rename at all. Why rename? I typed it a couple times during this change and typed it wrong > 50% of those times. The plural s just before Sequence somehow trips my typing. Also we use the abbreviation transaction -> tx pervasively in this code base, so I thought I'll shorten it up.

I will change it back if you insist!?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I am fine with tx but then perhaps rename the other function which is also a mouthful

@@ -76,6 +72,19 @@ queryUTxOByTxIn networkId socket inputs =
)
in UTxO.fromApi <$> runQuery networkId socket query

-- | Query the whole UTxO from node. Useful for debugging, but should obviously
-- not be used in production code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂

let cardanoKeys = [aliceCardanoVk]
withIOManager $ \iocp -> do
withDirectChain (contramap (FromDirectChain "alice") tracer) magic iocp nodeSocket aliceKeys alice cardanoKeys (putMVar alicesCallback) $ \Chain{postTx} -> do
postSeedPayment (Testnet magic) pparams availableInitialFunds nodeSocket aliceCardanoSk 100_000_000
void $ seedFromFaucet (Testnet magic) node aliceCardanoVk 100_000_000 Marked
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proposal: Rather than exposing the seedFromFaucet function with an additional parameter, expose 2 different functions with explicit names, eg. createFuelUTxO and createCommitUTxO or something. Additional parameters controlling the branching of a function increases the cognitive load of the function's user or reader

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this. The parameter does not control the branching of this function, rather what the thing you get from the faucet will be. Similar to the amount or whom it is payed to. I admit that the naming is not good and maybe data Marked = Fuel | NotMarked would be a better name?

waitForNodesConnected tracer [n1]
withHydraNode tracer bobSkPath [aliceVkPath, carolVkPath] tmpDir nodeSocket 2 bobSk [aliceVk, carolVk] allNodeIds $ \n2 ->
withHydraNode tracer carolSkPath [aliceVkPath, bobVkPath] tmpDir nodeSocket 3 carolSk [aliceVk, bobVk] allNodeIds $ \n3 -> do
-- Funds to be used as fuel by Hydra protocol transactions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: This comment here strengthens my belief an explicit function would be better.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or a better name for the Marked data constructor. In my book having more functions is not making things strictly less complex.

What do you think about this invocation and dropping the comment (as it should be clear from the names):
seedFromFaucet_ defaultNetworkId node aliceCardanoVk 100_000_000 Fuel?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer less parameters, plus the _ is a haskell convention which is widespread but maybe not that explicit in the long run. And it's repeated several times across different files. But I won't make it a casus belli so will let you decide.

& counterexample ("\ntransactions: " <> jsonString transactionsSequence)
& counterexample ("\nutxo: " <> jsonString initialUTxO)
forAll arbitrary $ \(Positive n) -> do
idempotentIOProperty $ do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discovery: Did not know about this function, looks interesting and useful.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me neither.. before yesterday :)

void $ waitForPayment networkId socket amountToPay addr
(RunningCluster ClusterConfig{networkId} (node : _)) -> do
(vk, _) <- keysFor Alice
void $ seedFromFaucet networkId node vk 100_000_000 Normal
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice improvement in the size and complexity of the function 🎉

hydra-node/src/Hydra/Chain/Direct/Wallet.hs Show resolved Hide resolved
where
generateEnvironment = do
refreshSystemStart cfg args
let topology = mkTopology $ peers $ ports cfg
Aeson.encodeFile (stateDirectory </> nodeTopologyFile args) topology

cleanupSocketFile =
whenM (doesFileExist socketFile) $
removeFile socketFile
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this now necessary 🤔 ?

Copy link
Collaborator

@KtorZ KtorZ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work. I've got maybe one side question: what happens if the faucet runs out of the money? Not the practical implications of it but, what sort of errors are we welcomed with? Is it made clear that we are running out of money?

Asking this because of a bad memory of several hours debugging some failing e2e tests in cardano-wallet only to figure out that we had no more funds in the faucet which was causing tests to fail.

@ch1bo
Copy link
Collaborator Author

ch1bo commented Feb 25, 2022

Nice work. I've got maybe one side question: what happens if the faucet runs out of the money? Not the practical implications of it but, what sort of errors are we welcomed with? Is it made clear that we are running out of money?

Asking this because of a bad memory of several hours debugging some failing e2e tests in cardano-wallet only to figure out that we had no more funds in the faucet which was causing tests to fail.

Good question. Haven't tried. I fear it would block because it retry forever. 😬

@ch1bo ch1bo merged commit 5d4582f into master Feb 25, 2022
@ch1bo ch1bo deleted the ch1bo/faucet-distribution branch February 25, 2022 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants