Initial commit
This commit is contained in:
commit
c76e19b502
15
README.md
Normal file
15
README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# <p align="center">Hydra Head Demo, Reflex-DOM edition</p>
|
||||
|
||||
This is an extended, graphical re-implementation of the original [Hydra Heads demo](https://github.com/input-output-hk/hydra-poc/tree/master/demo) implemented with [Reflex FRP](https://reflex-frp.org/).
|
||||
It allows starting and closing a head with an arbitrary number of nodes, each with some initial amount of Ada to perform transactions within the head.
|
||||
|
||||
# Running
|
||||
|
||||
To run the demo enter a Nix shell and run it with `cabal`:
|
||||
|
||||
```
|
||||
$ nix-shell -A shells.ghc default.nix
|
||||
$ cabal run
|
||||
```
|
||||
|
||||
The demo can then be viewed in Chrome at `http://localhost:3003/`.
|
37
default.nix
Normal file
37
default.nix
Normal file
@ -0,0 +1,37 @@
|
||||
# default.nix
|
||||
{ system ? builtins.currentSystem }:
|
||||
let
|
||||
nix-thunk = import ./dep/nix-thunk { };
|
||||
sources = nix-thunk.mapSubdirectories nix-thunk.thunkSource ./dep;
|
||||
reflex-platform = import sources.reflex-platform { inherit system; };
|
||||
hydra-poc = import sources.hydra-poc { };
|
||||
in reflex-platform.project ({ pkgs, ... }:
|
||||
let haskellLib = pkgs.haskell.lib;
|
||||
in {
|
||||
packages = { hydra-head-demo = ./.; };
|
||||
|
||||
shellToolOverrides = ghc: super: {
|
||||
};
|
||||
|
||||
overrides = self: super: {
|
||||
hydra-head-demo = haskellLib.overrideCabal super.hydra-head-demo (drv: {
|
||||
librarySystemDepends = (drv.librarySystemDepends or [ ]) ++ [
|
||||
hydra-poc.cardano-node.cardano-node
|
||||
hydra-poc.cardano-node.cardano-cli
|
||||
hydra-poc.hsPkgs.hydra-node.components.exes.hydra-node
|
||||
hydra-poc.hsPkgs.hydra-node.components.exes.hydra-tools
|
||||
pkgs.jq
|
||||
pkgs.coreutils
|
||||
];
|
||||
});
|
||||
};
|
||||
|
||||
useWarp = true;
|
||||
|
||||
withHoogle = true;
|
||||
|
||||
shells = {
|
||||
ghc = [ "hydra-head-demo" ];
|
||||
ghcjs = [ ];
|
||||
};
|
||||
})
|
203
demo/LICENSE
Normal file
203
demo/LICENSE
Normal file
@ -0,0 +1,203 @@
|
||||
[Original license of https://github.com/input-output-hk/hydra-poc below.]
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [2021-2022] [IOG]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
5
demo/credentials/faucet.sk
Normal file
5
demo/credentials/faucet.sk
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "PaymentSigningKeyShelley_ed25519",
|
||||
"description": "Payment Signing Key",
|
||||
"cborHex": "5820a5e4238b67ebb1108c52a01ac850bbce82c915d77bad94331892f3edf612883c"
|
||||
}
|
5
demo/credentials/faucet.vk
Normal file
5
demo/credentials/faucet.vk
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "PaymentVerificationKeyShelley_ed25519",
|
||||
"description": "Payment Verification Key",
|
||||
"cborHex": "5820ce13cd433cdcb3dfb00c04e216956aeb622dcd7f282b03304d9fc9de804723b2"
|
||||
}
|
BIN
demo/devnet/byron-delegate.key
Normal file
BIN
demo/devnet/byron-delegate.key
Normal file
Binary file not shown.
8
demo/devnet/byron-delegation.cert
Normal file
8
demo/devnet/byron-delegation.cert
Normal file
@ -0,0 +1,8 @@
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"NclXQiNNEpaaLdSxP3VFeOPIfSuFqBcNtmv8/7fftBKtgW1Aig7UqHJ/czsywkWFFVmBYPRnGjXspUl3wEMvuQ=="
|
||||
, "delegatePk":
|
||||
"24ejRK+kCDs1g4f3PcodFEUFVgNFWtfmuoEtVQf8/Ii2j2ruXHebJmZZPrwtAdbJYwDiSEvsHr95+BAF1ifGsA=="
|
||||
, "cert":
|
||||
"498c72e35ef30cd4657b48bfcc0a84a555a67981e3b6104a0d1708ab84510367d81e1ba3f47619565b1ee1098e31dcb8eb648d8030e061b568de113fdf3d6a09"
|
||||
}
|
79
demo/devnet/cardano-node.json
Normal file
79
demo/devnet/cardano-node.json
Normal file
@ -0,0 +1,79 @@
|
||||
{
|
||||
"Protocol": "Cardano",
|
||||
|
||||
"ByronGenesisFile": "genesis-byron.json",
|
||||
"ShelleyGenesisFile": "genesis-shelley.json",
|
||||
"AlonzoGenesisFile": "genesis-alonzo.json",
|
||||
|
||||
"ApplicationName": "cardano-sl",
|
||||
"ApplicationVersion": 1,
|
||||
"MaxKnownMajorProtocolVersion": 2,
|
||||
"LastKnownBlockVersion-Alt": 0,
|
||||
"LastKnownBlockVersion-Major": 6,
|
||||
"LastKnownBlockVersion-Minor": 0,
|
||||
|
||||
"TestShelleyHardForkAtEpoch": 0,
|
||||
"TestAllegraHardForkAtEpoch": 0,
|
||||
"TestMaryHardForkAtEpoch": 0,
|
||||
"TestAlonzoHardForkAtEpoch": 0,
|
||||
"TestBabbageHardForkAtEpoch": 0,
|
||||
|
||||
"RequiresNetworkMagic": "RequiresNoMagic",
|
||||
|
||||
"minSeverity": "Info",
|
||||
"defaultBackends": ["KatipBK"],
|
||||
"defaultScribes": [[ "StdoutSK", "stdout" ]],
|
||||
"setupBackends": ["KatipBK"],
|
||||
"setupScribes": [
|
||||
{
|
||||
"scFormat": "ScJson",
|
||||
"scKind": "StdoutSK",
|
||||
"scName": "stdout",
|
||||
"scRotation": null
|
||||
}
|
||||
],
|
||||
|
||||
"TurnOnLogMetrics": true,
|
||||
"TurnOnLogging": true,
|
||||
|
||||
"TracingVerbosity": "NormalVerbosity",
|
||||
"TraceBlockFetchClient": false,
|
||||
"TraceBlockFetchDecisions": false,
|
||||
"TraceBlockFetchProtocol": false,
|
||||
"TraceBlockFetchProtocolSerialised": false,
|
||||
"TraceBlockFetchServer": false,
|
||||
"TraceChainDb": true,
|
||||
"TraceChainSyncBlockServer": false,
|
||||
"TraceChainSyncClient": false,
|
||||
"TraceChainSyncHeaderServer": false,
|
||||
"TraceChainSyncProtocol": false,
|
||||
"TraceDNSResolver": false,
|
||||
"TraceDNSSubscription": false,
|
||||
"TraceErrorPolicy": false,
|
||||
"TraceForge": true,
|
||||
"TraceHandshake": false,
|
||||
"TraceIpSubscription": false,
|
||||
"TraceLocalChainSyncProtocol": true,
|
||||
"TraceLocalErrorPolicy": false,
|
||||
"TraceLocalHandshake": false,
|
||||
"TraceLocalTxSubmissionProtocol": true,
|
||||
"TraceLocalTxSubmissionServer": true,
|
||||
"TraceMempool": true,
|
||||
"TraceMux": false,
|
||||
"TraceTxInbound": false,
|
||||
"TraceTxOutbound": false,
|
||||
"TraceTxSubmissionProtocol": false,
|
||||
|
||||
"options": {
|
||||
"mapBackends": {
|
||||
"cardano.node.metrics": [ "EKGViewBK" ],
|
||||
"cardano.node.resources": [ "EKGViewBK" ]
|
||||
},
|
||||
"mapSubtrace": {
|
||||
"cardano.node.metrics": { "subtrace": "Neutral" }
|
||||
}
|
||||
},
|
||||
|
||||
"TestEnableDevelopmentHardForkEras": true,
|
||||
"TestEnableDevelopmentNetworkProtocols": true
|
||||
}
|
365
demo/devnet/genesis-alonzo.json
Normal file
365
demo/devnet/genesis-alonzo.json
Normal file
@ -0,0 +1,365 @@
|
||||
{
|
||||
"collateralPercentage": 150,
|
||||
"costModels": {
|
||||
"PlutusV1": {
|
||||
"addInteger-cpu-arguments-intercept": 197209,
|
||||
"addInteger-cpu-arguments-slope": 0,
|
||||
"addInteger-memory-arguments-intercept": 1,
|
||||
"addInteger-memory-arguments-slope": 1,
|
||||
"appendByteString-cpu-arguments-intercept": 396231,
|
||||
"appendByteString-cpu-arguments-slope": 621,
|
||||
"appendByteString-memory-arguments-intercept": 0,
|
||||
"appendByteString-memory-arguments-slope": 1,
|
||||
"appendString-cpu-arguments-intercept": 150000,
|
||||
"appendString-cpu-arguments-slope": 1000,
|
||||
"appendString-memory-arguments-intercept": 0,
|
||||
"appendString-memory-arguments-slope": 1,
|
||||
"bData-cpu-arguments": 150000,
|
||||
"bData-memory-arguments": 32,
|
||||
"blake2b_256-cpu-arguments-intercept": 2477736,
|
||||
"blake2b_256-cpu-arguments-slope": 29175,
|
||||
"blake2b_256-memory-arguments": 4,
|
||||
"cekApplyCost-exBudgetCPU": 29773,
|
||||
"cekApplyCost-exBudgetMemory": 100,
|
||||
"cekBuiltinCost-exBudgetCPU": 29773,
|
||||
"cekBuiltinCost-exBudgetMemory": 100,
|
||||
"cekConstCost-exBudgetCPU": 29773,
|
||||
"cekConstCost-exBudgetMemory": 100,
|
||||
"cekDelayCost-exBudgetCPU": 29773,
|
||||
"cekDelayCost-exBudgetMemory": 100,
|
||||
"cekForceCost-exBudgetCPU": 29773,
|
||||
"cekForceCost-exBudgetMemory": 100,
|
||||
"cekLamCost-exBudgetCPU": 29773,
|
||||
"cekLamCost-exBudgetMemory": 100,
|
||||
"cekStartupCost-exBudgetCPU": 100,
|
||||
"cekStartupCost-exBudgetMemory": 100,
|
||||
"cekVarCost-exBudgetCPU": 29773,
|
||||
"cekVarCost-exBudgetMemory": 100,
|
||||
"chooseData-cpu-arguments": 150000,
|
||||
"chooseData-memory-arguments": 32,
|
||||
"chooseList-cpu-arguments": 150000,
|
||||
"chooseList-memory-arguments": 32,
|
||||
"chooseUnit-cpu-arguments": 150000,
|
||||
"chooseUnit-memory-arguments": 32,
|
||||
"consByteString-cpu-arguments-intercept": 150000,
|
||||
"consByteString-cpu-arguments-slope": 1000,
|
||||
"consByteString-memory-arguments-intercept": 0,
|
||||
"consByteString-memory-arguments-slope": 1,
|
||||
"constrData-cpu-arguments": 150000,
|
||||
"constrData-memory-arguments": 32,
|
||||
"decodeUtf8-cpu-arguments-intercept": 150000,
|
||||
"decodeUtf8-cpu-arguments-slope": 1000,
|
||||
"decodeUtf8-memory-arguments-intercept": 0,
|
||||
"decodeUtf8-memory-arguments-slope": 8,
|
||||
"divideInteger-cpu-arguments-constant": 148000,
|
||||
"divideInteger-cpu-arguments-model-arguments-intercept": 425507,
|
||||
"divideInteger-cpu-arguments-model-arguments-slope": 118,
|
||||
"divideInteger-memory-arguments-intercept": 0,
|
||||
"divideInteger-memory-arguments-minimum": 1,
|
||||
"divideInteger-memory-arguments-slope": 1,
|
||||
"encodeUtf8-cpu-arguments-intercept": 150000,
|
||||
"encodeUtf8-cpu-arguments-slope": 1000,
|
||||
"encodeUtf8-memory-arguments-intercept": 0,
|
||||
"encodeUtf8-memory-arguments-slope": 8,
|
||||
"equalsByteString-cpu-arguments-constant": 150000,
|
||||
"equalsByteString-cpu-arguments-intercept": 112536,
|
||||
"equalsByteString-cpu-arguments-slope": 247,
|
||||
"equalsByteString-memory-arguments": 1,
|
||||
"equalsData-cpu-arguments-intercept": 150000,
|
||||
"equalsData-cpu-arguments-slope": 10000,
|
||||
"equalsData-memory-arguments": 1,
|
||||
"equalsInteger-cpu-arguments-intercept": 136542,
|
||||
"equalsInteger-cpu-arguments-slope": 1326,
|
||||
"equalsInteger-memory-arguments": 1,
|
||||
"equalsString-cpu-arguments-constant": 1000,
|
||||
"equalsString-cpu-arguments-intercept": 150000,
|
||||
"equalsString-cpu-arguments-slope": 1000,
|
||||
"equalsString-memory-arguments": 1,
|
||||
"fstPair-cpu-arguments": 150000,
|
||||
"fstPair-memory-arguments": 32,
|
||||
"headList-cpu-arguments": 150000,
|
||||
"headList-memory-arguments": 32,
|
||||
"iData-cpu-arguments": 150000,
|
||||
"iData-memory-arguments": 32,
|
||||
"ifThenElse-cpu-arguments": 1,
|
||||
"ifThenElse-memory-arguments": 1,
|
||||
"indexByteString-cpu-arguments": 150000,
|
||||
"indexByteString-memory-arguments": 1,
|
||||
"lengthOfByteString-cpu-arguments": 150000,
|
||||
"lengthOfByteString-memory-arguments": 4,
|
||||
"lessThanByteString-cpu-arguments-intercept": 103599,
|
||||
"lessThanByteString-cpu-arguments-slope": 248,
|
||||
"lessThanByteString-memory-arguments": 1,
|
||||
"lessThanEqualsByteString-cpu-arguments-intercept": 103599,
|
||||
"lessThanEqualsByteString-cpu-arguments-slope": 248,
|
||||
"lessThanEqualsByteString-memory-arguments": 1,
|
||||
"lessThanEqualsInteger-cpu-arguments-intercept": 145276,
|
||||
"lessThanEqualsInteger-cpu-arguments-slope": 1366,
|
||||
"lessThanEqualsInteger-memory-arguments": 1,
|
||||
"lessThanInteger-cpu-arguments-intercept": 179690,
|
||||
"lessThanInteger-cpu-arguments-slope": 497,
|
||||
"lessThanInteger-memory-arguments": 1,
|
||||
"listData-cpu-arguments": 150000,
|
||||
"listData-memory-arguments": 32,
|
||||
"mapData-cpu-arguments": 150000,
|
||||
"mapData-memory-arguments": 32,
|
||||
"mkCons-cpu-arguments": 150000,
|
||||
"mkCons-memory-arguments": 32,
|
||||
"mkNilData-cpu-arguments": 150000,
|
||||
"mkNilData-memory-arguments": 32,
|
||||
"mkNilPairData-cpu-arguments": 150000,
|
||||
"mkNilPairData-memory-arguments": 32,
|
||||
"mkPairData-cpu-arguments": 150000,
|
||||
"mkPairData-memory-arguments": 32,
|
||||
"modInteger-cpu-arguments-constant": 148000,
|
||||
"modInteger-cpu-arguments-model-arguments-intercept": 425507,
|
||||
"modInteger-cpu-arguments-model-arguments-slope": 118,
|
||||
"modInteger-memory-arguments-intercept": 0,
|
||||
"modInteger-memory-arguments-minimum": 1,
|
||||
"modInteger-memory-arguments-slope": 1,
|
||||
"multiplyInteger-cpu-arguments-intercept": 61516,
|
||||
"multiplyInteger-cpu-arguments-slope": 11218,
|
||||
"multiplyInteger-memory-arguments-intercept": 0,
|
||||
"multiplyInteger-memory-arguments-slope": 1,
|
||||
"nullList-cpu-arguments": 150000,
|
||||
"nullList-memory-arguments": 32,
|
||||
"quotientInteger-cpu-arguments-constant": 148000,
|
||||
"quotientInteger-cpu-arguments-model-arguments-intercept": 425507,
|
||||
"quotientInteger-cpu-arguments-model-arguments-slope": 118,
|
||||
"quotientInteger-memory-arguments-intercept": 0,
|
||||
"quotientInteger-memory-arguments-minimum": 1,
|
||||
"quotientInteger-memory-arguments-slope": 1,
|
||||
"remainderInteger-cpu-arguments-constant": 148000,
|
||||
"remainderInteger-cpu-arguments-model-arguments-intercept": 425507,
|
||||
"remainderInteger-cpu-arguments-model-arguments-slope": 118,
|
||||
"remainderInteger-memory-arguments-intercept": 0,
|
||||
"remainderInteger-memory-arguments-minimum": 1,
|
||||
"remainderInteger-memory-arguments-slope": 1,
|
||||
"sha2_256-cpu-arguments-intercept": 2477736,
|
||||
"sha2_256-cpu-arguments-slope": 29175,
|
||||
"sha2_256-memory-arguments": 4,
|
||||
"sha3_256-cpu-arguments-intercept": 0,
|
||||
"sha3_256-cpu-arguments-slope": 82363,
|
||||
"sha3_256-memory-arguments": 4,
|
||||
"sliceByteString-cpu-arguments-intercept": 150000,
|
||||
"sliceByteString-cpu-arguments-slope": 5000,
|
||||
"sliceByteString-memory-arguments-intercept": 0,
|
||||
"sliceByteString-memory-arguments-slope": 1,
|
||||
"sndPair-cpu-arguments": 150000,
|
||||
"sndPair-memory-arguments": 32,
|
||||
"subtractInteger-cpu-arguments-intercept": 197209,
|
||||
"subtractInteger-cpu-arguments-slope": 0,
|
||||
"subtractInteger-memory-arguments-intercept": 1,
|
||||
"subtractInteger-memory-arguments-slope": 1,
|
||||
"tailList-cpu-arguments": 150000,
|
||||
"tailList-memory-arguments": 32,
|
||||
"trace-cpu-arguments": 150000,
|
||||
"trace-memory-arguments": 32,
|
||||
"unBData-cpu-arguments": 150000,
|
||||
"unBData-memory-arguments": 32,
|
||||
"unConstrData-cpu-arguments": 150000,
|
||||
"unConstrData-memory-arguments": 32,
|
||||
"unIData-cpu-arguments": 150000,
|
||||
"unIData-memory-arguments": 32,
|
||||
"unListData-cpu-arguments": 150000,
|
||||
"unListData-memory-arguments": 32,
|
||||
"unMapData-cpu-arguments": 150000,
|
||||
"unMapData-memory-arguments": 32,
|
||||
"verifyEd25519Signature-cpu-arguments-intercept": 3345831,
|
||||
"verifyEd25519Signature-cpu-arguments-slope": 1,
|
||||
"verifyEd25519Signature-memory-arguments": 1
|
||||
},
|
||||
"PlutusV2": {
|
||||
"addInteger-cpu-arguments-intercept": 205665,
|
||||
"addInteger-cpu-arguments-slope": 812,
|
||||
"addInteger-memory-arguments-intercept": 1,
|
||||
"addInteger-memory-arguments-slope": 1,
|
||||
"appendByteString-cpu-arguments-intercept": 1000,
|
||||
"appendByteString-cpu-arguments-slope": 571,
|
||||
"appendByteString-memory-arguments-intercept": 0,
|
||||
"appendByteString-memory-arguments-slope": 1,
|
||||
"appendString-cpu-arguments-intercept": 1000,
|
||||
"appendString-cpu-arguments-slope": 24177,
|
||||
"appendString-memory-arguments-intercept": 4,
|
||||
"appendString-memory-arguments-slope": 1,
|
||||
"bData-cpu-arguments": 1000,
|
||||
"bData-memory-arguments": 32,
|
||||
"blake2b_256-cpu-arguments-intercept": 117366,
|
||||
"blake2b_256-cpu-arguments-slope": 10475,
|
||||
"blake2b_256-memory-arguments": 4,
|
||||
"cekApplyCost-exBudgetCPU": 23000,
|
||||
"cekApplyCost-exBudgetMemory": 100,
|
||||
"cekBuiltinCost-exBudgetCPU": 23000,
|
||||
"cekBuiltinCost-exBudgetMemory": 100,
|
||||
"cekConstCost-exBudgetCPU": 23000,
|
||||
"cekConstCost-exBudgetMemory": 100,
|
||||
"cekDelayCost-exBudgetCPU": 23000,
|
||||
"cekDelayCost-exBudgetMemory": 100,
|
||||
"cekForceCost-exBudgetCPU": 23000,
|
||||
"cekForceCost-exBudgetMemory": 100,
|
||||
"cekLamCost-exBudgetCPU": 23000,
|
||||
"cekLamCost-exBudgetMemory": 100,
|
||||
"cekStartupCost-exBudgetCPU": 100,
|
||||
"cekStartupCost-exBudgetMemory": 100,
|
||||
"cekVarCost-exBudgetCPU": 23000,
|
||||
"cekVarCost-exBudgetMemory": 100,
|
||||
"chooseData-cpu-arguments": 19537,
|
||||
"chooseData-memory-arguments": 32,
|
||||
"chooseList-cpu-arguments": 175354,
|
||||
"chooseList-memory-arguments": 32,
|
||||
"chooseUnit-cpu-arguments": 46417,
|
||||
"chooseUnit-memory-arguments": 4,
|
||||
"consByteString-cpu-arguments-intercept": 221973,
|
||||
"consByteString-cpu-arguments-slope": 511,
|
||||
"consByteString-memory-arguments-intercept": 0,
|
||||
"consByteString-memory-arguments-slope": 1,
|
||||
"constrData-cpu-arguments": 89141,
|
||||
"constrData-memory-arguments": 32,
|
||||
"decodeUtf8-cpu-arguments-intercept": 497525,
|
||||
"decodeUtf8-cpu-arguments-slope": 14068,
|
||||
"decodeUtf8-memory-arguments-intercept": 4,
|
||||
"decodeUtf8-memory-arguments-slope": 2,
|
||||
"divideInteger-cpu-arguments-constant": 196500,
|
||||
"divideInteger-cpu-arguments-model-arguments-intercept": 453240,
|
||||
"divideInteger-cpu-arguments-model-arguments-slope": 220,
|
||||
"divideInteger-memory-arguments-intercept": 0,
|
||||
"divideInteger-memory-arguments-minimum": 1,
|
||||
"divideInteger-memory-arguments-slope": 1,
|
||||
"encodeUtf8-cpu-arguments-intercept": 1000,
|
||||
"encodeUtf8-cpu-arguments-slope": 28662,
|
||||
"encodeUtf8-memory-arguments-intercept": 4,
|
||||
"encodeUtf8-memory-arguments-slope": 2,
|
||||
"equalsByteString-cpu-arguments-constant": 245000,
|
||||
"equalsByteString-cpu-arguments-intercept": 216773,
|
||||
"equalsByteString-cpu-arguments-slope": 62,
|
||||
"equalsByteString-memory-arguments": 1,
|
||||
"equalsData-cpu-arguments-intercept": 1060367,
|
||||
"equalsData-cpu-arguments-slope": 12586,
|
||||
"equalsData-memory-arguments": 1,
|
||||
"equalsInteger-cpu-arguments-intercept": 208512,
|
||||
"equalsInteger-cpu-arguments-slope": 421,
|
||||
"equalsInteger-memory-arguments": 1,
|
||||
"equalsString-cpu-arguments-constant": 187000,
|
||||
"equalsString-cpu-arguments-intercept": 1000,
|
||||
"equalsString-cpu-arguments-slope": 52998,
|
||||
"equalsString-memory-arguments": 1,
|
||||
"fstPair-cpu-arguments": 80436,
|
||||
"fstPair-memory-arguments": 32,
|
||||
"headList-cpu-arguments": 43249,
|
||||
"headList-memory-arguments": 32,
|
||||
"iData-cpu-arguments": 1000,
|
||||
"iData-memory-arguments": 32,
|
||||
"ifThenElse-cpu-arguments": 80556,
|
||||
"ifThenElse-memory-arguments": 1,
|
||||
"indexByteString-cpu-arguments": 57667,
|
||||
"indexByteString-memory-arguments": 4,
|
||||
"lengthOfByteString-cpu-arguments": 1000,
|
||||
"lengthOfByteString-memory-arguments": 10,
|
||||
"lessThanByteString-cpu-arguments-intercept": 197145,
|
||||
"lessThanByteString-cpu-arguments-slope": 156,
|
||||
"lessThanByteString-memory-arguments": 1,
|
||||
"lessThanEqualsByteString-cpu-arguments-intercept": 197145,
|
||||
"lessThanEqualsByteString-cpu-arguments-slope": 156,
|
||||
"lessThanEqualsByteString-memory-arguments": 1,
|
||||
"lessThanEqualsInteger-cpu-arguments-intercept": 204924,
|
||||
"lessThanEqualsInteger-cpu-arguments-slope": 473,
|
||||
"lessThanEqualsInteger-memory-arguments": 1,
|
||||
"lessThanInteger-cpu-arguments-intercept": 208896,
|
||||
"lessThanInteger-cpu-arguments-slope": 511,
|
||||
"lessThanInteger-memory-arguments": 1,
|
||||
"listData-cpu-arguments": 52467,
|
||||
"listData-memory-arguments": 32,
|
||||
"mapData-cpu-arguments": 64832,
|
||||
"mapData-memory-arguments": 32,
|
||||
"mkCons-cpu-arguments": 65493,
|
||||
"mkCons-memory-arguments": 32,
|
||||
"mkNilData-cpu-arguments": 22558,
|
||||
"mkNilData-memory-arguments": 32,
|
||||
"mkNilPairData-cpu-arguments": 16563,
|
||||
"mkNilPairData-memory-arguments": 32,
|
||||
"mkPairData-cpu-arguments": 76511,
|
||||
"mkPairData-memory-arguments": 32,
|
||||
"modInteger-cpu-arguments-constant": 196500,
|
||||
"modInteger-cpu-arguments-model-arguments-intercept": 453240,
|
||||
"modInteger-cpu-arguments-model-arguments-slope": 220,
|
||||
"modInteger-memory-arguments-intercept": 0,
|
||||
"modInteger-memory-arguments-minimum": 1,
|
||||
"modInteger-memory-arguments-slope": 1,
|
||||
"multiplyInteger-cpu-arguments-intercept": 69522,
|
||||
"multiplyInteger-cpu-arguments-slope": 11687,
|
||||
"multiplyInteger-memory-arguments-intercept": 0,
|
||||
"multiplyInteger-memory-arguments-slope": 1,
|
||||
"nullList-cpu-arguments": 60091,
|
||||
"nullList-memory-arguments": 32,
|
||||
"quotientInteger-cpu-arguments-constant": 196500,
|
||||
"quotientInteger-cpu-arguments-model-arguments-intercept": 453240,
|
||||
"quotientInteger-cpu-arguments-model-arguments-slope": 220,
|
||||
"quotientInteger-memory-arguments-intercept": 0,
|
||||
"quotientInteger-memory-arguments-minimum": 1,
|
||||
"quotientInteger-memory-arguments-slope": 1,
|
||||
"remainderInteger-cpu-arguments-constant": 196500,
|
||||
"remainderInteger-cpu-arguments-model-arguments-intercept": 453240,
|
||||
"remainderInteger-cpu-arguments-model-arguments-slope": 220,
|
||||
"remainderInteger-memory-arguments-intercept": 0,
|
||||
"remainderInteger-memory-arguments-minimum": 1,
|
||||
"remainderInteger-memory-arguments-slope": 1,
|
||||
"serialiseData-cpu-arguments-intercept": 1159724,
|
||||
"serialiseData-cpu-arguments-slope": 392670,
|
||||
"serialiseData-memory-arguments-intercept": 0,
|
||||
"serialiseData-memory-arguments-slope": 2,
|
||||
"sha2_256-cpu-arguments-intercept": 806990,
|
||||
"sha2_256-cpu-arguments-slope": 30482,
|
||||
"sha2_256-memory-arguments": 4,
|
||||
"sha3_256-cpu-arguments-intercept": 1927926,
|
||||
"sha3_256-cpu-arguments-slope": 82523,
|
||||
"sha3_256-memory-arguments": 4,
|
||||
"sliceByteString-cpu-arguments-intercept": 265318,
|
||||
"sliceByteString-cpu-arguments-slope": 0,
|
||||
"sliceByteString-memory-arguments-intercept": 4,
|
||||
"sliceByteString-memory-arguments-slope": 0,
|
||||
"sndPair-cpu-arguments": 85931,
|
||||
"sndPair-memory-arguments": 32,
|
||||
"subtractInteger-cpu-arguments-intercept": 205665,
|
||||
"subtractInteger-cpu-arguments-slope": 812,
|
||||
"subtractInteger-memory-arguments-intercept": 1,
|
||||
"subtractInteger-memory-arguments-slope": 1,
|
||||
"tailList-cpu-arguments": 41182,
|
||||
"tailList-memory-arguments": 32,
|
||||
"trace-cpu-arguments": 212342,
|
||||
"trace-memory-arguments": 32,
|
||||
"unBData-cpu-arguments": 31220,
|
||||
"unBData-memory-arguments": 32,
|
||||
"unConstrData-cpu-arguments": 32696,
|
||||
"unConstrData-memory-arguments": 32,
|
||||
"unIData-cpu-arguments": 43357,
|
||||
"unIData-memory-arguments": 32,
|
||||
"unListData-cpu-arguments": 32247,
|
||||
"unListData-memory-arguments": 32,
|
||||
"unMapData-cpu-arguments": 38314,
|
||||
"unMapData-memory-arguments": 32,
|
||||
"verifyEcdsaSecp256k1Signature-cpu-arguments": 35892428,
|
||||
"verifyEcdsaSecp256k1Signature-memory-arguments": 10,
|
||||
"verifyEd25519Signature-cpu-arguments-intercept": 9462713,
|
||||
"verifyEd25519Signature-cpu-arguments-slope": 1021,
|
||||
"verifyEd25519Signature-memory-arguments": 10,
|
||||
"verifySchnorrSecp256k1Signature-cpu-arguments-intercept": 38887044,
|
||||
"verifySchnorrSecp256k1Signature-cpu-arguments-slope": 32947,
|
||||
"verifySchnorrSecp256k1Signature-memory-arguments": 10
|
||||
}
|
||||
},
|
||||
"executionPrices": {
|
||||
"prMem": 5.77e-2,
|
||||
"prSteps": 7.21e-5
|
||||
},
|
||||
"lovelacePerUTxOWord": 34482,
|
||||
"maxBlockExUnits": {
|
||||
"exUnitsMem": 80000000,
|
||||
"exUnitsSteps": 40000000000
|
||||
},
|
||||
"maxCollateralInputs": 3,
|
||||
"maxTxExUnits": {
|
||||
"exUnitsMem": 16000000,
|
||||
"exUnitsSteps": 10000000000
|
||||
},
|
||||
"maxValueSize": 5000
|
||||
}
|
36
demo/devnet/genesis-byron.json
Normal file
36
demo/devnet/genesis-byron.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"protocolConsts": {
|
||||
"k": 2160,
|
||||
"protocolMagic": 42
|
||||
},
|
||||
"startTime": 1657186415,
|
||||
"blockVersionData": {
|
||||
"scriptVersion": 0,
|
||||
"slotDuration": "250",
|
||||
"maxBlockSize": "2000000",
|
||||
"maxHeaderSize": "2000000",
|
||||
"maxTxSize": "4096",
|
||||
"maxProposalSize": "700",
|
||||
"mpcThd": "20000000000000",
|
||||
"heavyDelThd": "300000000000",
|
||||
"updateVoteThd": "1000000000000",
|
||||
"updateProposalThd": "100000000000000",
|
||||
"updateImplicit": "10000",
|
||||
"softforkRule": {
|
||||
"initThd": "900000000000000",
|
||||
"minThd": "600000000000000",
|
||||
"thdDecrement": "50000000000000"
|
||||
},
|
||||
"txFeePolicy": {
|
||||
"summand": "155381000000000",
|
||||
"multiplier": "43000000000"
|
||||
},
|
||||
"unlockStakeEpoch": "18446744073709551615"
|
||||
},
|
||||
"bootStakeholders": {
|
||||
"7a4519c93d7be4577dd85bd524c644e6b809e44eae0457b43128c1c7": 1
|
||||
},
|
||||
"heavyDelegation": {},
|
||||
"nonAvvmBalances": {},
|
||||
"avvmDistr": {}
|
||||
}
|
65
demo/devnet/genesis-shelley.json
Normal file
65
demo/devnet/genesis-shelley.json
Normal file
@ -0,0 +1,65 @@
|
||||
{
|
||||
"epochLength": 432000,
|
||||
"activeSlotsCoeff": 1.0,
|
||||
"slotLength": 0.1,
|
||||
"securityParam": 2160,
|
||||
"genDelegs": {},
|
||||
"initialFunds": {
|
||||
"00813c32c92aad21770ff8001de0918f598df8c06775f77f8e8839d2a0074a515f7f32bf31a4f41c7417a8136e8152bfb42f06d71b389a6896": 900000000000,
|
||||
"609783be7d3c54f11377966dfabc9284cd6c32fca1cd42ef0a4f1cc45b": 900000000000
|
||||
},
|
||||
"maxKESEvolutions": 60,
|
||||
"maxLovelaceSupply": 2000000000000,
|
||||
"networkId": "Testnet",
|
||||
"networkMagic": 42,
|
||||
"protocolParams": {
|
||||
"a0": 0.0,
|
||||
"decentralisationParam": 0,
|
||||
"eMax": 18,
|
||||
"extraEntropy": {
|
||||
"tag": "NeutralNonce"
|
||||
},
|
||||
"keyDeposit": 0,
|
||||
"maxBlockBodySize": 65536,
|
||||
"maxBlockHeaderSize": 1100,
|
||||
"maxTxSize": 16384,
|
||||
"minFeeA": 44,
|
||||
"minFeeB": 155381,
|
||||
"minPoolCost": 0,
|
||||
"minUTxOValue": 0,
|
||||
"nOpt": 100,
|
||||
"poolDeposit": 0,
|
||||
"protocolVersion": {
|
||||
"major": 7,
|
||||
"minor": 0
|
||||
},
|
||||
"rho": 0.1,
|
||||
"tau": 0.1
|
||||
},
|
||||
"slotsPerKESPeriod": 129600,
|
||||
"staking": {
|
||||
"pools": {
|
||||
"8a219b698d3b6e034391ae84cee62f1d76b6fbc45ddfe4e31e0d4b60": {
|
||||
"cost": 0,
|
||||
"margin": 0.0,
|
||||
"metadata": null,
|
||||
"owners": [],
|
||||
"pledge": 0,
|
||||
"publicKey": "8a219b698d3b6e034391ae84cee62f1d76b6fbc45ddfe4e31e0d4b60",
|
||||
"relays": [],
|
||||
"rewardAccount": {
|
||||
"credential": {
|
||||
"key hash": "b6ffb20cf821f9286802235841d4348a2c2bafd4f73092b7de6655ea"
|
||||
},
|
||||
"network": "Testnet"
|
||||
},
|
||||
"vrf": "fec17ed60cbf2ec5be3f061fb4de0b6ef1f20947cfbfce5fb2783d12f3f69ff5"
|
||||
}
|
||||
},
|
||||
"stake": {
|
||||
"074a515f7f32bf31a4f41c7417a8136e8152bfb42f06d71b389a6896": "8a219b698d3b6e034391ae84cee62f1d76b6fbc45ddfe4e31e0d4b60"
|
||||
}
|
||||
},
|
||||
"systemStart": "2022-07-07T09:33:35Z",
|
||||
"updateQuorum": 2
|
||||
}
|
5
demo/devnet/kes.skey
Normal file
5
demo/devnet/kes.skey
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "KesSigningKey_ed25519_kes_2^6",
|
||||
"description": "KES Signing Key",
|
||||
"cborHex": "590260a199f16b11da6c7f5c1e0f1eb0b9bbe278d3d8f35bfd50d0951c2ff94d0344cd57df5f64c9bac1dd60b4482f9c636168f40737d526625a2ec82f22ec0c72de0013f86ef743a7bba0286db6ddf3d85bf8e49ddbf14d9d3b7ee22f4857c77b740948f84f2e72f6bcf91f405e34ea50a2c53fa4876b43cfce2bcfe87c06a903de8bb33d968ca7930b67d0c23f5cb2d74e422d773ba80e388de384691000d6ba8a9b4dc7d3187f76048fbef9a52b72d80d835bb76eced7c0e0cdc5b58869b73c095dffa01db4ff51765afcead565395a5ed1cf74e5f2134d61076fece21aacd080bbbfaab94125401d7bbc74eafc7e7e3a2235f59dc03d6e332e53d558493a1e22213b92c77b1328ff1b83855da704fc366bf4415490602481d1939136eeaf252c65184912a779d9d94a90e32b72c1877ef60b6d79e707ce5a762acb4bed46436efe4fe62aae50b39068cc508a09427c92791cbcbea44318529cc68d297ca24e1b73b2394c385ec63fcd85ed56eec3de48860a1ec950aad4f91cbf741dbd7bf1d3c278875bd20e31ff5372339f6aa5280ad9b8bf3514889ac44600fe57ca0b535d6dc6b0b981e079595aad186ee0be9b07e837391ab165e4ca406601c876a86e246a3f53311e21199cccc0b080f28d18f4dc6987731e10e4ade00df7c6921c5ef3022b6f49a29ba307a2c8f4bd2ba42fcfa0aad68a2f0ad31fff69a99d3471f9036d3f5817a3edfeff7fc3c14e1151d767aaa043481cfd1a6ee55e8e5d7853ecdaf9da2bb36c716beae8d706bc648a790d4697e1d044a11a49f305ab8bc64a094bd81bda7395fe6f77dd5557c39919dd9bb9cf22a87fe47408ae3ec2247007d015a5"
|
||||
}
|
5
demo/devnet/opcert.cert
Normal file
5
demo/devnet/opcert.cert
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "NodeOperationalCertificate",
|
||||
"description": "",
|
||||
"cborHex": "828458204cd49bb05e9885142fe7af1481107995298771fd1a24e72b506a4d600ee2b3120000584089fc9e9f551b2ea873bf31643659d049152d5c8e8de86be4056370bccc5fa62dd12e3f152f1664e614763e46eaa7a17ed366b5cef19958773d1ab96941442e0b58205a3d778e76741a009e29d23093cfe046131808d34d7c864967b515e98dfc3583"
|
||||
}
|
5
demo/devnet/vrf.skey
Normal file
5
demo/devnet/vrf.skey
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"type": "VrfSigningKey_PraosVRF",
|
||||
"description": "VRF Signing Key",
|
||||
"cborHex": "5840899795b70e9f34b737159fe21a6170568d6031e187f0cc84555c712b7c29b45cb882007593ef70f86e5c0948561a3b8e8851529a4f98975f2b24e768dda38ce2"
|
||||
}
|
21
demo/prepare-devnet.sh
Executable file
21
demo/prepare-devnet.sh
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Prepare a "devnet" directory holding credentials, a dummy topology and
|
||||
# "up-to-date" genesis files. If the directory exists, it is wiped out.
|
||||
set -e
|
||||
|
||||
BASEDIR=$(dirname $(realpath $0))
|
||||
TARGETDIR="${BASEDIR}/../devnet"
|
||||
|
||||
[ -d "$TARGETDIR" ] && { echo "Cleaning up directory $TARGETDIR" ; rm -r $TARGETDIR ; }
|
||||
|
||||
cp -af "$BASEDIR/devnet/" "$TARGETDIR"
|
||||
cp -af "$BASEDIR/credentials" "$TARGETDIR"
|
||||
cp -af "$BASEDIR/protocol-parameters.json" "$TARGETDIR"
|
||||
echo '{"Producers": []}' > "$TARGETDIR/topology.json"
|
||||
sed -i "s/\"startTime\": [0-9]*/\"startTime\": $(date +%s)/" "$TARGETDIR/genesis-byron.json" && \
|
||||
sed -i "s/\"systemStart\": \".*\"/\"systemStart\": \"$(date -u +%FT%TZ)\"/" "$TARGETDIR/genesis-shelley.json"
|
||||
|
||||
find $TARGETDIR -type f -exec chmod 0400 {} \;
|
||||
mkdir "$TARGETDIR/ipc"
|
||||
echo "Prepared devnet, you can start the cluster now"
|
386
demo/protocol-parameters.json
Normal file
386
demo/protocol-parameters.json
Normal file
@ -0,0 +1,386 @@
|
||||
{
|
||||
"collateralPercentage": 150,
|
||||
"costModels": {
|
||||
"PlutusScriptV1": {
|
||||
"addInteger-cpu-arguments-intercept": 197209,
|
||||
"addInteger-cpu-arguments-slope": 0,
|
||||
"addInteger-memory-arguments-intercept": 1,
|
||||
"addInteger-memory-arguments-slope": 1,
|
||||
"appendByteString-cpu-arguments-intercept": 396231,
|
||||
"appendByteString-cpu-arguments-slope": 621,
|
||||
"appendByteString-memory-arguments-intercept": 0,
|
||||
"appendByteString-memory-arguments-slope": 1,
|
||||
"appendString-cpu-arguments-intercept": 150000,
|
||||
"appendString-cpu-arguments-slope": 1000,
|
||||
"appendString-memory-arguments-intercept": 0,
|
||||
"appendString-memory-arguments-slope": 1,
|
||||
"bData-cpu-arguments": 150000,
|
||||
"bData-memory-arguments": 32,
|
||||
"blake2b_256-cpu-arguments-intercept": 2477736,
|
||||
"blake2b_256-cpu-arguments-slope": 29175,
|
||||
"blake2b_256-memory-arguments": 4,
|
||||
"cekApplyCost-exBudgetCPU": 29773,
|
||||
"cekApplyCost-exBudgetMemory": 100,
|
||||
"cekBuiltinCost-exBudgetCPU": 29773,
|
||||
"cekBuiltinCost-exBudgetMemory": 100,
|
||||
"cekConstCost-exBudgetCPU": 29773,
|
||||
"cekConstCost-exBudgetMemory": 100,
|
||||
"cekDelayCost-exBudgetCPU": 29773,
|
||||
"cekDelayCost-exBudgetMemory": 100,
|
||||
"cekForceCost-exBudgetCPU": 29773,
|
||||
"cekForceCost-exBudgetMemory": 100,
|
||||
"cekLamCost-exBudgetCPU": 29773,
|
||||
"cekLamCost-exBudgetMemory": 100,
|
||||
"cekStartupCost-exBudgetCPU": 100,
|
||||
"cekStartupCost-exBudgetMemory": 100,
|
||||
"cekVarCost-exBudgetCPU": 29773,
|
||||
"cekVarCost-exBudgetMemory": 100,
|
||||
"chooseData-cpu-arguments": 150000,
|
||||
"chooseData-memory-arguments": 32,
|
||||
"chooseList-cpu-arguments": 150000,
|
||||
"chooseList-memory-arguments": 32,
|
||||
"chooseUnit-cpu-arguments": 150000,
|
||||
"chooseUnit-memory-arguments": 32,
|
||||
"consByteString-cpu-arguments-intercept": 150000,
|
||||
"consByteString-cpu-arguments-slope": 1000,
|
||||
"consByteString-memory-arguments-intercept": 0,
|
||||
"consByteString-memory-arguments-slope": 1,
|
||||
"constrData-cpu-arguments": 150000,
|
||||
"constrData-memory-arguments": 32,
|
||||
"decodeUtf8-cpu-arguments-intercept": 150000,
|
||||
"decodeUtf8-cpu-arguments-slope": 1000,
|
||||
"decodeUtf8-memory-arguments-intercept": 0,
|
||||
"decodeUtf8-memory-arguments-slope": 8,
|
||||
"divideInteger-cpu-arguments-constant": 148000,
|
||||
"divideInteger-cpu-arguments-model-arguments-intercept": 425507,
|
||||
"divideInteger-cpu-arguments-model-arguments-slope": 118,
|
||||
"divideInteger-memory-arguments-intercept": 0,
|
||||
"divideInteger-memory-arguments-minimum": 1,
|
||||
"divideInteger-memory-arguments-slope": 1,
|
||||
"encodeUtf8-cpu-arguments-intercept": 150000,
|
||||
"encodeUtf8-cpu-arguments-slope": 1000,
|
||||
"encodeUtf8-memory-arguments-intercept": 0,
|
||||
"encodeUtf8-memory-arguments-slope": 8,
|
||||
"equalsByteString-cpu-arguments-constant": 150000,
|
||||
"equalsByteString-cpu-arguments-intercept": 112536,
|
||||
"equalsByteString-cpu-arguments-slope": 247,
|
||||
"equalsByteString-memory-arguments": 1,
|
||||
"equalsData-cpu-arguments-intercept": 150000,
|
||||
"equalsData-cpu-arguments-slope": 10000,
|
||||
"equalsData-memory-arguments": 1,
|
||||
"equalsInteger-cpu-arguments-intercept": 136542,
|
||||
"equalsInteger-cpu-arguments-slope": 1326,
|
||||
"equalsInteger-memory-arguments": 1,
|
||||
"equalsString-cpu-arguments-constant": 1000,
|
||||
"equalsString-cpu-arguments-intercept": 150000,
|
||||
"equalsString-cpu-arguments-slope": 1000,
|
||||
"equalsString-memory-arguments": 1,
|
||||
"fstPair-cpu-arguments": 150000,
|
||||
"fstPair-memory-arguments": 32,
|
||||
"headList-cpu-arguments": 150000,
|
||||
"headList-memory-arguments": 32,
|
||||
"iData-cpu-arguments": 150000,
|
||||
"iData-memory-arguments": 32,
|
||||
"ifThenElse-cpu-arguments": 1,
|
||||
"ifThenElse-memory-arguments": 1,
|
||||
"indexByteString-cpu-arguments": 150000,
|
||||
"indexByteString-memory-arguments": 1,
|
||||
"lengthOfByteString-cpu-arguments": 150000,
|
||||
"lengthOfByteString-memory-arguments": 4,
|
||||
"lessThanByteString-cpu-arguments-intercept": 103599,
|
||||
"lessThanByteString-cpu-arguments-slope": 248,
|
||||
"lessThanByteString-memory-arguments": 1,
|
||||
"lessThanEqualsByteString-cpu-arguments-intercept": 103599,
|
||||
"lessThanEqualsByteString-cpu-arguments-slope": 248,
|
||||
"lessThanEqualsByteString-memory-arguments": 1,
|
||||
"lessThanEqualsInteger-cpu-arguments-intercept": 145276,
|
||||
"lessThanEqualsInteger-cpu-arguments-slope": 1366,
|
||||
"lessThanEqualsInteger-memory-arguments": 1,
|
||||
"lessThanInteger-cpu-arguments-intercept": 179690,
|
||||
"lessThanInteger-cpu-arguments-slope": 497,
|
||||
"lessThanInteger-memory-arguments": 1,
|
||||
"listData-cpu-arguments": 150000,
|
||||
"listData-memory-arguments": 32,
|
||||
"mapData-cpu-arguments": 150000,
|
||||
"mapData-memory-arguments": 32,
|
||||
"mkCons-cpu-arguments": 150000,
|
||||
"mkCons-memory-arguments": 32,
|
||||
"mkNilData-cpu-arguments": 150000,
|
||||
"mkNilData-memory-arguments": 32,
|
||||
"mkNilPairData-cpu-arguments": 150000,
|
||||
"mkNilPairData-memory-arguments": 32,
|
||||
"mkPairData-cpu-arguments": 150000,
|
||||
"mkPairData-memory-arguments": 32,
|
||||
"modInteger-cpu-arguments-constant": 148000,
|
||||
"modInteger-cpu-arguments-model-arguments-intercept": 425507,
|
||||
"modInteger-cpu-arguments-model-arguments-slope": 118,
|
||||
"modInteger-memory-arguments-intercept": 0,
|
||||
"modInteger-memory-arguments-minimum": 1,
|
||||
"modInteger-memory-arguments-slope": 1,
|
||||
"multiplyInteger-cpu-arguments-intercept": 61516,
|
||||
"multiplyInteger-cpu-arguments-slope": 11218,
|
||||
"multiplyInteger-memory-arguments-intercept": 0,
|
||||
"multiplyInteger-memory-arguments-slope": 1,
|
||||
"nullList-cpu-arguments": 150000,
|
||||
"nullList-memory-arguments": 32,
|
||||
"quotientInteger-cpu-arguments-constant": 148000,
|
||||
"quotientInteger-cpu-arguments-model-arguments-intercept": 425507,
|
||||
"quotientInteger-cpu-arguments-model-arguments-slope": 118,
|
||||
"quotientInteger-memory-arguments-intercept": 0,
|
||||
"quotientInteger-memory-arguments-minimum": 1,
|
||||
"quotientInteger-memory-arguments-slope": 1,
|
||||
"remainderInteger-cpu-arguments-constant": 148000,
|
||||
"remainderInteger-cpu-arguments-model-arguments-intercept": 425507,
|
||||
"remainderInteger-cpu-arguments-model-arguments-slope": 118,
|
||||
"remainderInteger-memory-arguments-intercept": 0,
|
||||
"remainderInteger-memory-arguments-minimum": 1,
|
||||
"remainderInteger-memory-arguments-slope": 1,
|
||||
"sha2_256-cpu-arguments-intercept": 2477736,
|
||||
"sha2_256-cpu-arguments-slope": 29175,
|
||||
"sha2_256-memory-arguments": 4,
|
||||
"sha3_256-cpu-arguments-intercept": 0,
|
||||
"sha3_256-cpu-arguments-slope": 82363,
|
||||
"sha3_256-memory-arguments": 4,
|
||||
"sliceByteString-cpu-arguments-intercept": 150000,
|
||||
"sliceByteString-cpu-arguments-slope": 5000,
|
||||
"sliceByteString-memory-arguments-intercept": 0,
|
||||
"sliceByteString-memory-arguments-slope": 1,
|
||||
"sndPair-cpu-arguments": 150000,
|
||||
"sndPair-memory-arguments": 32,
|
||||
"subtractInteger-cpu-arguments-intercept": 197209,
|
||||
"subtractInteger-cpu-arguments-slope": 0,
|
||||
"subtractInteger-memory-arguments-intercept": 1,
|
||||
"subtractInteger-memory-arguments-slope": 1,
|
||||
"tailList-cpu-arguments": 150000,
|
||||
"tailList-memory-arguments": 32,
|
||||
"trace-cpu-arguments": 150000,
|
||||
"trace-memory-arguments": 32,
|
||||
"unBData-cpu-arguments": 150000,
|
||||
"unBData-memory-arguments": 32,
|
||||
"unConstrData-cpu-arguments": 150000,
|
||||
"unConstrData-memory-arguments": 32,
|
||||
"unIData-cpu-arguments": 150000,
|
||||
"unIData-memory-arguments": 32,
|
||||
"unListData-cpu-arguments": 150000,
|
||||
"unListData-memory-arguments": 32,
|
||||
"unMapData-cpu-arguments": 150000,
|
||||
"unMapData-memory-arguments": 32,
|
||||
"verifyEd25519Signature-cpu-arguments-intercept": 3345831,
|
||||
"verifyEd25519Signature-cpu-arguments-slope": 1,
|
||||
"verifyEd25519Signature-memory-arguments": 1
|
||||
},
|
||||
"PlutusScriptV2": {
|
||||
"addInteger-cpu-arguments-intercept": 205665,
|
||||
"addInteger-cpu-arguments-slope": 812,
|
||||
"addInteger-memory-arguments-intercept": 1,
|
||||
"addInteger-memory-arguments-slope": 1,
|
||||
"appendByteString-cpu-arguments-intercept": 1000,
|
||||
"appendByteString-cpu-arguments-slope": 571,
|
||||
"appendByteString-memory-arguments-intercept": 0,
|
||||
"appendByteString-memory-arguments-slope": 1,
|
||||
"appendString-cpu-arguments-intercept": 1000,
|
||||
"appendString-cpu-arguments-slope": 24177,
|
||||
"appendString-memory-arguments-intercept": 4,
|
||||
"appendString-memory-arguments-slope": 1,
|
||||
"bData-cpu-arguments": 1000,
|
||||
"bData-memory-arguments": 32,
|
||||
"blake2b_256-cpu-arguments-intercept": 117366,
|
||||
"blake2b_256-cpu-arguments-slope": 10475,
|
||||
"blake2b_256-memory-arguments": 4,
|
||||
"cekApplyCost-exBudgetCPU": 23000,
|
||||
"cekApplyCost-exBudgetMemory": 100,
|
||||
"cekBuiltinCost-exBudgetCPU": 23000,
|
||||
"cekBuiltinCost-exBudgetMemory": 100,
|
||||
"cekConstCost-exBudgetCPU": 23000,
|
||||
"cekConstCost-exBudgetMemory": 100,
|
||||
"cekDelayCost-exBudgetCPU": 23000,
|
||||
"cekDelayCost-exBudgetMemory": 100,
|
||||
"cekForceCost-exBudgetCPU": 23000,
|
||||
"cekForceCost-exBudgetMemory": 100,
|
||||
"cekLamCost-exBudgetCPU": 23000,
|
||||
"cekLamCost-exBudgetMemory": 100,
|
||||
"cekStartupCost-exBudgetCPU": 100,
|
||||
"cekStartupCost-exBudgetMemory": 100,
|
||||
"cekVarCost-exBudgetCPU": 23000,
|
||||
"cekVarCost-exBudgetMemory": 100,
|
||||
"chooseData-cpu-arguments": 19537,
|
||||
"chooseData-memory-arguments": 32,
|
||||
"chooseList-cpu-arguments": 175354,
|
||||
"chooseList-memory-arguments": 32,
|
||||
"chooseUnit-cpu-arguments": 46417,
|
||||
"chooseUnit-memory-arguments": 4,
|
||||
"consByteString-cpu-arguments-intercept": 221973,
|
||||
"consByteString-cpu-arguments-slope": 511,
|
||||
"consByteString-memory-arguments-intercept": 0,
|
||||
"consByteString-memory-arguments-slope": 1,
|
||||
"constrData-cpu-arguments": 89141,
|
||||
"constrData-memory-arguments": 32,
|
||||
"decodeUtf8-cpu-arguments-intercept": 497525,
|
||||
"decodeUtf8-cpu-arguments-slope": 14068,
|
||||
"decodeUtf8-memory-arguments-intercept": 4,
|
||||
"decodeUtf8-memory-arguments-slope": 2,
|
||||
"divideInteger-cpu-arguments-constant": 196500,
|
||||
"divideInteger-cpu-arguments-model-arguments-intercept": 453240,
|
||||
"divideInteger-cpu-arguments-model-arguments-slope": 220,
|
||||
"divideInteger-memory-arguments-intercept": 0,
|
||||
"divideInteger-memory-arguments-minimum": 1,
|
||||
"divideInteger-memory-arguments-slope": 1,
|
||||
"encodeUtf8-cpu-arguments-intercept": 1000,
|
||||
"encodeUtf8-cpu-arguments-slope": 28662,
|
||||
"encodeUtf8-memory-arguments-intercept": 4,
|
||||
"encodeUtf8-memory-arguments-slope": 2,
|
||||
"equalsByteString-cpu-arguments-constant": 245000,
|
||||
"equalsByteString-cpu-arguments-intercept": 216773,
|
||||
"equalsByteString-cpu-arguments-slope": 62,
|
||||
"equalsByteString-memory-arguments": 1,
|
||||
"equalsData-cpu-arguments-intercept": 1060367,
|
||||
"equalsData-cpu-arguments-slope": 12586,
|
||||
"equalsData-memory-arguments": 1,
|
||||
"equalsInteger-cpu-arguments-intercept": 208512,
|
||||
"equalsInteger-cpu-arguments-slope": 421,
|
||||
"equalsInteger-memory-arguments": 1,
|
||||
"equalsString-cpu-arguments-constant": 187000,
|
||||
"equalsString-cpu-arguments-intercept": 1000,
|
||||
"equalsString-cpu-arguments-slope": 52998,
|
||||
"equalsString-memory-arguments": 1,
|
||||
"fstPair-cpu-arguments": 80436,
|
||||
"fstPair-memory-arguments": 32,
|
||||
"headList-cpu-arguments": 43249,
|
||||
"headList-memory-arguments": 32,
|
||||
"iData-cpu-arguments": 1000,
|
||||
"iData-memory-arguments": 32,
|
||||
"ifThenElse-cpu-arguments": 80556,
|
||||
"ifThenElse-memory-arguments": 1,
|
||||
"indexByteString-cpu-arguments": 57667,
|
||||
"indexByteString-memory-arguments": 4,
|
||||
"lengthOfByteString-cpu-arguments": 1000,
|
||||
"lengthOfByteString-memory-arguments": 10,
|
||||
"lessThanByteString-cpu-arguments-intercept": 197145,
|
||||
"lessThanByteString-cpu-arguments-slope": 156,
|
||||
"lessThanByteString-memory-arguments": 1,
|
||||
"lessThanEqualsByteString-cpu-arguments-intercept": 197145,
|
||||
"lessThanEqualsByteString-cpu-arguments-slope": 156,
|
||||
"lessThanEqualsByteString-memory-arguments": 1,
|
||||
"lessThanEqualsInteger-cpu-arguments-intercept": 204924,
|
||||
"lessThanEqualsInteger-cpu-arguments-slope": 473,
|
||||
"lessThanEqualsInteger-memory-arguments": 1,
|
||||
"lessThanInteger-cpu-arguments-intercept": 208896,
|
||||
"lessThanInteger-cpu-arguments-slope": 511,
|
||||
"lessThanInteger-memory-arguments": 1,
|
||||
"listData-cpu-arguments": 52467,
|
||||
"listData-memory-arguments": 32,
|
||||
"mapData-cpu-arguments": 64832,
|
||||
"mapData-memory-arguments": 32,
|
||||
"mkCons-cpu-arguments": 65493,
|
||||
"mkCons-memory-arguments": 32,
|
||||
"mkNilData-cpu-arguments": 22558,
|
||||
"mkNilData-memory-arguments": 32,
|
||||
"mkNilPairData-cpu-arguments": 16563,
|
||||
"mkNilPairData-memory-arguments": 32,
|
||||
"mkPairData-cpu-arguments": 76511,
|
||||
"mkPairData-memory-arguments": 32,
|
||||
"modInteger-cpu-arguments-constant": 196500,
|
||||
"modInteger-cpu-arguments-model-arguments-intercept": 453240,
|
||||
"modInteger-cpu-arguments-model-arguments-slope": 220,
|
||||
"modInteger-memory-arguments-intercept": 0,
|
||||
"modInteger-memory-arguments-minimum": 1,
|
||||
"modInteger-memory-arguments-slope": 1,
|
||||
"multiplyInteger-cpu-arguments-intercept": 69522,
|
||||
"multiplyInteger-cpu-arguments-slope": 11687,
|
||||
"multiplyInteger-memory-arguments-intercept": 0,
|
||||
"multiplyInteger-memory-arguments-slope": 1,
|
||||
"nullList-cpu-arguments": 60091,
|
||||
"nullList-memory-arguments": 32,
|
||||
"quotientInteger-cpu-arguments-constant": 196500,
|
||||
"quotientInteger-cpu-arguments-model-arguments-intercept": 453240,
|
||||
"quotientInteger-cpu-arguments-model-arguments-slope": 220,
|
||||
"quotientInteger-memory-arguments-intercept": 0,
|
||||
"quotientInteger-memory-arguments-minimum": 1,
|
||||
"quotientInteger-memory-arguments-slope": 1,
|
||||
"remainderInteger-cpu-arguments-constant": 196500,
|
||||
"remainderInteger-cpu-arguments-model-arguments-intercept": 453240,
|
||||
"remainderInteger-cpu-arguments-model-arguments-slope": 220,
|
||||
"remainderInteger-memory-arguments-intercept": 0,
|
||||
"remainderInteger-memory-arguments-minimum": 1,
|
||||
"remainderInteger-memory-arguments-slope": 1,
|
||||
"serialiseData-cpu-arguments-intercept": 1159724,
|
||||
"serialiseData-cpu-arguments-slope": 392670,
|
||||
"serialiseData-memory-arguments-intercept": 0,
|
||||
"serialiseData-memory-arguments-slope": 2,
|
||||
"sha2_256-cpu-arguments-intercept": 806990,
|
||||
"sha2_256-cpu-arguments-slope": 30482,
|
||||
"sha2_256-memory-arguments": 4,
|
||||
"sha3_256-cpu-arguments-intercept": 1927926,
|
||||
"sha3_256-cpu-arguments-slope": 82523,
|
||||
"sha3_256-memory-arguments": 4,
|
||||
"sliceByteString-cpu-arguments-intercept": 265318,
|
||||
"sliceByteString-cpu-arguments-slope": 0,
|
||||
"sliceByteString-memory-arguments-intercept": 4,
|
||||
"sliceByteString-memory-arguments-slope": 0,
|
||||
"sndPair-cpu-arguments": 85931,
|
||||
"sndPair-memory-arguments": 32,
|
||||
"subtractInteger-cpu-arguments-intercept": 205665,
|
||||
"subtractInteger-cpu-arguments-slope": 812,
|
||||
"subtractInteger-memory-arguments-intercept": 1,
|
||||
"subtractInteger-memory-arguments-slope": 1,
|
||||
"tailList-cpu-arguments": 41182,
|
||||
"tailList-memory-arguments": 32,
|
||||
"trace-cpu-arguments": 212342,
|
||||
"trace-memory-arguments": 32,
|
||||
"unBData-cpu-arguments": 31220,
|
||||
"unBData-memory-arguments": 32,
|
||||
"unConstrData-cpu-arguments": 32696,
|
||||
"unConstrData-memory-arguments": 32,
|
||||
"unIData-cpu-arguments": 43357,
|
||||
"unIData-memory-arguments": 32,
|
||||
"unListData-cpu-arguments": 32247,
|
||||
"unListData-memory-arguments": 32,
|
||||
"unMapData-cpu-arguments": 38314,
|
||||
"unMapData-memory-arguments": 32,
|
||||
"verifyEcdsaSecp256k1Signature-cpu-arguments": 35892428,
|
||||
"verifyEcdsaSecp256k1Signature-memory-arguments": 10,
|
||||
"verifyEd25519Signature-cpu-arguments-intercept": 9462713,
|
||||
"verifyEd25519Signature-cpu-arguments-slope": 1021,
|
||||
"verifyEd25519Signature-memory-arguments": 10,
|
||||
"verifySchnorrSecp256k1Signature-cpu-arguments-intercept": 38887044,
|
||||
"verifySchnorrSecp256k1Signature-cpu-arguments-slope": 32947,
|
||||
"verifySchnorrSecp256k1Signature-memory-arguments": 10
|
||||
}
|
||||
},
|
||||
"decentralization": null,
|
||||
"executionUnitPrices": {
|
||||
"priceMemory": 5.77e-2,
|
||||
"priceSteps": 7.21e-5
|
||||
},
|
||||
"extraPraosEntropy": null,
|
||||
"maxBlockBodySize": 65536,
|
||||
"maxBlockExecutionUnits": {
|
||||
"memory": 80000000,
|
||||
"steps": 40000000000
|
||||
},
|
||||
"maxBlockHeaderSize": 1100,
|
||||
"maxCollateralInputs": 3,
|
||||
"maxTxExecutionUnits": {
|
||||
"memory": 16000000,
|
||||
"steps": 10000000000
|
||||
},
|
||||
"maxTxSize": 16384,
|
||||
"maxValueSize": 5000,
|
||||
"minPoolCost": 0,
|
||||
"minUTxOValue": null,
|
||||
"monetaryExpansion": 1.78650067e-3,
|
||||
"poolPledgeInfluence": 0.1,
|
||||
"poolRetireMaxEpoch": 18,
|
||||
"protocolVersion": {
|
||||
"major": 7,
|
||||
"minor": 0
|
||||
},
|
||||
"stakeAddressDeposit": 400000,
|
||||
"stakePoolDeposit": 500000000,
|
||||
"stakePoolTargetNum": 50,
|
||||
"treasuryCut": 0.1,
|
||||
"txFeeFixed": 0,
|
||||
"txFeePerByte": 0,
|
||||
"utxoCostPerWord": 34488,
|
||||
"utxoCostPerByte": 4310
|
||||
}
|
2
dep/aeson-gadt-th/default.nix
Normal file
2
dep/aeson-gadt-th/default.nix
Normal file
@ -0,0 +1,2 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
import (import ./thunk.nix)
|
7
dep/aeson-gadt-th/github.json
Normal file
7
dep/aeson-gadt-th/github.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"owner": "obsidiansystems",
|
||||
"repo": "aeson-gadt-th",
|
||||
"private": false,
|
||||
"rev": "71a315a4873c2875ad737a3320320849bdcf8a2a",
|
||||
"sha256": "1sjl0a0ig0xfssl4bglakk1b7sj8wqz8hwbg7k2fk10qi7z5hb50"
|
||||
}
|
9
dep/aeson-gadt-th/thunk.nix
Normal file
9
dep/aeson-gadt-th/thunk.nix
Normal file
@ -0,0 +1,9 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||
} else (import <nixpkgs> {}).fetchFromGitHub {
|
||||
inherit owner repo rev sha256 fetchSubmodules private;
|
||||
};
|
||||
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||
in fetch json
|
2
dep/aeson/default.nix
Normal file
2
dep/aeson/default.nix
Normal file
@ -0,0 +1,2 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
import (import ./thunk.nix)
|
8
dep/aeson/github.json
Normal file
8
dep/aeson/github.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"owner": "haskell",
|
||||
"repo": "aeson",
|
||||
"branch": "aeson-1.5",
|
||||
"private": false,
|
||||
"rev": "78e838df44288ac7d7ac2cd77863d2c026d86dbb",
|
||||
"sha256": "181v1nz05jq992wgmz6ns7iwqx0c5w003hv5ki1kvc9zlg5dh3vf"
|
||||
}
|
9
dep/aeson/thunk.nix
Normal file
9
dep/aeson/thunk.nix
Normal file
@ -0,0 +1,9 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||
} else (import <nixpkgs> {}).fetchFromGitHub {
|
||||
inherit owner repo rev sha256 fetchSubmodules private;
|
||||
};
|
||||
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||
in fetch json
|
2
dep/constraints-extras/default.nix
Normal file
2
dep/constraints-extras/default.nix
Normal file
@ -0,0 +1,2 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
import (import ./thunk.nix)
|
8
dep/constraints-extras/github.json
Normal file
8
dep/constraints-extras/github.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"owner": "obsidiansystems",
|
||||
"repo": "constraints-extras",
|
||||
"branch": "release/0.3.2.0",
|
||||
"private": false,
|
||||
"rev": "42835fd9e1b4b3c4a72cd1237c04789f01c92dd0",
|
||||
"sha256": "0z7yfxxi4jywzhlkphs8ss3hd7fll8c90bbl6nr2bj63c87jx6sw"
|
||||
}
|
9
dep/constraints-extras/thunk.nix
Normal file
9
dep/constraints-extras/thunk.nix
Normal file
@ -0,0 +1,9 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||
} else (import <nixpkgs> {}).fetchFromGitHub {
|
||||
inherit owner repo rev sha256 fetchSubmodules private;
|
||||
};
|
||||
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||
in fetch json
|
2
dep/entropy/default.nix
Normal file
2
dep/entropy/default.nix
Normal file
@ -0,0 +1,2 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
import (import ./thunk.nix)
|
8
dep/entropy/github.json
Normal file
8
dep/entropy/github.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"owner": "obsidiansystems",
|
||||
"repo": "entropy",
|
||||
"branch": "aa/nonwindow-contexts",
|
||||
"private": false,
|
||||
"rev": "ddda007c44390d0ec8cad58810710864dee60ddd",
|
||||
"sha256": "00b7cqdqbjf953r5gmwmkn2mn36zdxqwx90xih925cni94vi4vw9"
|
||||
}
|
9
dep/entropy/thunk.nix
Normal file
9
dep/entropy/thunk.nix
Normal file
@ -0,0 +1,9 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||
} else (import <nixpkgs> {}).fetchFromGitHub {
|
||||
inherit owner repo rev sha256 fetchSubmodules private;
|
||||
};
|
||||
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||
in fetch json
|
2
dep/hydra-poc/default.nix
Normal file
2
dep/hydra-poc/default.nix
Normal file
@ -0,0 +1,2 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
import (import ./thunk.nix)
|
7
dep/hydra-poc/github.json
Normal file
7
dep/hydra-poc/github.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"owner": "input-output-hk",
|
||||
"repo": "hydra-poc",
|
||||
"private": false,
|
||||
"rev": "b0ebec965f27553a1c99e5457441219dcb9306d6",
|
||||
"sha256": "0i9sflwpy87hhrbb6c0wbjs1mj2nsln69yah6vnacb6l0j47ik4b"
|
||||
}
|
9
dep/hydra-poc/thunk.nix
Normal file
9
dep/hydra-poc/thunk.nix
Normal file
@ -0,0 +1,9 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||
} else (import <nixpkgs> {}).fetchFromGitHub {
|
||||
inherit owner repo rev sha256 fetchSubmodules private;
|
||||
};
|
||||
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||
in fetch json
|
2
dep/logging-effect/default.nix
Normal file
2
dep/logging-effect/default.nix
Normal file
@ -0,0 +1,2 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
import (import ./thunk.nix)
|
7
dep/logging-effect/github.json
Normal file
7
dep/logging-effect/github.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"owner": "ocharles",
|
||||
"repo": "logging-effect",
|
||||
"private": false,
|
||||
"rev": "efc856b62aec15f0087be0edb7ba621ed49b0bb1",
|
||||
"sha256": "13nr3zw39415js1af2vd322vhzwqb2rkrv7b5lkd97h211d7zbj9"
|
||||
}
|
9
dep/logging-effect/thunk.nix
Normal file
9
dep/logging-effect/thunk.nix
Normal file
@ -0,0 +1,9 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||
} else (import <nixpkgs> {}).fetchFromGitHub {
|
||||
inherit owner repo rev sha256 fetchSubmodules private;
|
||||
};
|
||||
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||
in fetch json
|
2
dep/nix-thunk/default.nix
Normal file
2
dep/nix-thunk/default.nix
Normal file
@ -0,0 +1,2 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
import (import ./thunk.nix)
|
7
dep/nix-thunk/github.json
Normal file
7
dep/nix-thunk/github.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"owner": "obsidiansystems",
|
||||
"repo": "nix-thunk",
|
||||
"private": false,
|
||||
"rev": "bd0de53129ca4ac5ce313a3e021edf3638a3a22c",
|
||||
"sha256": "0cn74ylcfr9v2w94jpga9v18jn6zafb9k996afszn59iqlcfi74q"
|
||||
}
|
12
dep/nix-thunk/thunk.nix
Normal file
12
dep/nix-thunk/thunk.nix
Normal file
@ -0,0 +1,12 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||
} else (import (builtins.fetchTarball {
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/3aad50c30c826430b0270fcf8264c8c41b005403.tar.gz";
|
||||
sha256 = "0xwqsf08sywd23x0xvw4c4ghq0l28w2ki22h0bdn766i16z9q2gr";
|
||||
}) {}).fetchFromGitHub {
|
||||
inherit owner repo rev sha256 fetchSubmodules private;
|
||||
};
|
||||
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||
in fetch json
|
2
dep/reflex-gadt-api/default.nix
Normal file
2
dep/reflex-gadt-api/default.nix
Normal file
@ -0,0 +1,2 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
import (import ./thunk.nix)
|
8
dep/reflex-gadt-api/github.json
Normal file
8
dep/reflex-gadt-api/github.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"owner": "reflex-frp",
|
||||
"repo": "reflex-gadt-api",
|
||||
"branch": "develop",
|
||||
"private": false,
|
||||
"rev": "69aca72b57a74fbf0d06a1b2ac1d247ce9aa207f",
|
||||
"sha256": "116c6lna8pkas95lclm4halagc4f6rxv5hmf7rnl10lxqi9m48qw"
|
||||
}
|
9
dep/reflex-gadt-api/thunk.nix
Normal file
9
dep/reflex-gadt-api/thunk.nix
Normal file
@ -0,0 +1,9 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||
} else (import <nixpkgs> {}).fetchFromGitHub {
|
||||
inherit owner repo rev sha256 fetchSubmodules private;
|
||||
};
|
||||
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||
in fetch json
|
2
dep/reflex-platform/default.nix
Normal file
2
dep/reflex-platform/default.nix
Normal file
@ -0,0 +1,2 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
import (import ./thunk.nix)
|
8
dep/reflex-platform/github.json
Normal file
8
dep/reflex-platform/github.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"owner": "reflex-frp",
|
||||
"repo": "reflex-platform",
|
||||
"branch": "release/0.9.2.0",
|
||||
"private": false,
|
||||
"rev": "123a6f487ca954fd983f6d4cd6b2a69d4c463d10",
|
||||
"sha256": "16q1rq0rwi6l28fv46q8m0hvb9rxrzf574j865vaz04xy8d5p1ya"
|
||||
}
|
12
dep/reflex-platform/thunk.nix
Normal file
12
dep/reflex-platform/thunk.nix
Normal file
@ -0,0 +1,12 @@
|
||||
# DO NOT HAND-EDIT THIS FILE
|
||||
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
|
||||
if !fetchSubmodules && !private then builtins.fetchTarball {
|
||||
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
|
||||
} else (import (builtins.fetchTarball {
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/3aad50c30c826430b0270fcf8264c8c41b005403.tar.gz";
|
||||
sha256 = "0xwqsf08sywd23x0xvw4c4ghq0l28w2ki22h0bdn766i16z9q2gr";
|
||||
}) {}).fetchFromGitHub {
|
||||
inherit owner repo rev sha256 fetchSubmodules private;
|
||||
};
|
||||
json = builtins.fromJSON (builtins.readFile ./github.json);
|
||||
in fetch json
|
4
hie.yaml
Normal file
4
hie.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
cradle:
|
||||
cabal:
|
||||
- path: "src"
|
||||
component: "exe:hydra-head-demo"
|
55
hydra-head-demo.cabal
Normal file
55
hydra-head-demo.cabal
Normal file
@ -0,0 +1,55 @@
|
||||
name: hydra-head-demo
|
||||
version: 0.1
|
||||
cabal-version: >= 1.8
|
||||
build-type: Simple
|
||||
|
||||
|
||||
executable hydra-head-demo
|
||||
main-is: Main.hs
|
||||
hs-source-dirs: src
|
||||
ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wincomplete-record-updates -O -threaded -fno-show-valid-hole-fits
|
||||
if impl(ghcjs)
|
||||
buildable: False
|
||||
other-modules: Hydra.ClientInput
|
||||
, Hydra.Devnet
|
||||
, Hydra.ServerOutput
|
||||
, Hydra.Types
|
||||
, Paths
|
||||
build-depends: base
|
||||
, process
|
||||
, async
|
||||
, which
|
||||
-- , monad-logger
|
||||
-- , logging-effect
|
||||
, prettyprinter
|
||||
, string-interpolate
|
||||
, containers
|
||||
, text
|
||||
, witherable
|
||||
-- , io-streams
|
||||
, some
|
||||
, directory
|
||||
, aeson
|
||||
, resource-pool
|
||||
, bytestring
|
||||
, uuid
|
||||
, time
|
||||
, reflex
|
||||
, reflex-dom
|
||||
, mtl
|
||||
, jsaddle
|
||||
|
||||
default-extensions:
|
||||
OverloadedStrings
|
||||
LambdaCase
|
||||
GADTs
|
||||
ScopedTypeVariables
|
||||
OverloadedStrings
|
||||
FlexibleContexts
|
||||
QuasiQuotes
|
||||
DeriveGeneric
|
||||
RecursiveDo
|
||||
RankNTypes
|
||||
PartialTypeSignatures
|
||||
TypeFamilies
|
||||
TypeApplications
|
26
src/Hydra/ClientInput.hs
Normal file
26
src/Hydra/ClientInput.hs
Normal file
@ -0,0 +1,26 @@
|
||||
-- |
|
||||
|
||||
module Hydra.ClientInput where
|
||||
|
||||
import GHC.Generics
|
||||
import Data.Aeson
|
||||
import qualified Data.Text as T
|
||||
import Hydra.Types
|
||||
|
||||
-- Copied and adapted from hydra-poc:hydra-node/src/hydra/ServerOutput.hs
|
||||
-- Anything that took effort was replaced by Value
|
||||
|
||||
data ClientInput
|
||||
= Init {contestationPeriod :: ContestationPeriod}
|
||||
| Abort
|
||||
| Commit {utxo :: WholeUTXO}
|
||||
| NewTx {transaction :: T.Text}
|
||||
| GetUTxO
|
||||
| Close
|
||||
| Contest
|
||||
| Fanout
|
||||
deriving (Eq, Generic, Show)
|
||||
|
||||
|
||||
instance ToJSON ClientInput
|
||||
instance FromJSON ClientInput
|
377
src/Hydra/Devnet.hs
Normal file
377
src/Hydra/Devnet.hs
Normal file
@ -0,0 +1,377 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE TupleSections #-}
|
||||
|
||||
-- |
|
||||
|
||||
module Hydra.Devnet
|
||||
( HydraScriptTxId
|
||||
, HydraKeyInfo(..)
|
||||
, SigningKey
|
||||
, KeyPair(..)
|
||||
, getCardanoAddress
|
||||
, seedAddressFromFaucetAndWait
|
||||
, publishReferenceScripts
|
||||
, queryAddressUTXOs
|
||||
, buildSignedHydraTx
|
||||
, generateKeys
|
||||
, cardanoNodePath
|
||||
, hydraNodePath
|
||||
, prepareDevnet
|
||||
, devnetMagic
|
||||
, minTxLovelace
|
||||
)
|
||||
|
||||
where
|
||||
|
||||
import System.Which
|
||||
import System.Directory
|
||||
import System.Process
|
||||
|
||||
import Control.Monad
|
||||
import Control.Monad.IO.Class
|
||||
import Data.Aeson
|
||||
|
||||
import Control.Concurrent
|
||||
|
||||
|
||||
import Data.Map (Map)
|
||||
|
||||
import Data.Bool
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Map as Map
|
||||
import Data.String.Interpolate (i)
|
||||
import Paths
|
||||
|
||||
import qualified Data.ByteString.Lazy.Char8 as BS
|
||||
|
||||
import Hydra.Types
|
||||
import qualified Data.UUID.V4 as UUIDV4
|
||||
import qualified Data.UUID as UUID
|
||||
import Data.UUID (UUID)
|
||||
import Data.Maybe (fromMaybe)
|
||||
|
||||
|
||||
devnetMagic :: Int
|
||||
devnetMagic = 42
|
||||
|
||||
prepareDevnet :: IO ()
|
||||
prepareDevnet = do
|
||||
output <- readCreateProcess (shell "[ -d devnet ] || ./demo/prepare-devnet.sh") ""
|
||||
putStrLn output
|
||||
|
||||
cardanoNodePath :: FilePath
|
||||
cardanoNodePath = $(staticWhich "cardano-node")
|
||||
|
||||
cardanoCliPath :: FilePath
|
||||
cardanoCliPath = $(staticWhich "cardano-cli")
|
||||
|
||||
hydraNodePath :: FilePath
|
||||
hydraNodePath = $(staticWhich "hydra-node")
|
||||
|
||||
jqPath :: FilePath
|
||||
jqPath = $(staticWhich "jq")
|
||||
|
||||
type TxId = T.Text
|
||||
|
||||
type HydraScriptTxId = T.Text
|
||||
|
||||
type DraftTx = FilePath
|
||||
type SignedTx = FilePath
|
||||
|
||||
devnetNetworkId :: Int
|
||||
devnetNetworkId = 42
|
||||
|
||||
generateKeys :: (MonadIO m) => m HydraKeyInfo
|
||||
generateKeys = do
|
||||
basePath <- liftIO getTempPath'
|
||||
HydraKeyInfo <$> generateCardanoKeys basePath <*> generateHydraKeys basePath
|
||||
|
||||
|
||||
type SigningKey = String
|
||||
type VerificationKey = String
|
||||
|
||||
data KeyPair = KeyPair
|
||||
{ _signingKey :: SigningKey
|
||||
, _verificationKey :: VerificationKey
|
||||
}
|
||||
deriving (Show,Read)
|
||||
|
||||
|
||||
data HydraKeyInfo = HydraKeyInfo
|
||||
{ _cardanoKeys :: KeyPair
|
||||
, _hydraKeys :: KeyPair
|
||||
}
|
||||
deriving (Show,Read)
|
||||
|
||||
-- | Generate Cardano keys. Calling with an e.g. "my/keys/alice"
|
||||
-- argument results in "my/keys/alice.cardano.{vk,sk}" keys being
|
||||
-- written.
|
||||
generateCardanoKeys :: (MonadIO m) => String -> m KeyPair
|
||||
generateCardanoKeys path = do
|
||||
output <- liftIO $
|
||||
readCreateProcess
|
||||
(proc cardanoCliPath [ "address"
|
||||
, "key-gen"
|
||||
, "--verification-key-file"
|
||||
, [i|#{path}.cardano.vk|]
|
||||
, "--signing-key-file"
|
||||
, [i|#{path}.cardano.sk|]
|
||||
])
|
||||
""
|
||||
liftIO $ putStrLn output
|
||||
pure $ KeyPair [i|#{path}.cardano.sk|] [i|#{path}.cardano.vk|]
|
||||
|
||||
-- | Generate Hydra keys. Calling with an e.g. "my/keys/alice"
|
||||
-- argument results in "my/keys/alice.hydra.{vk,sk}" keys being
|
||||
-- written.
|
||||
generateHydraKeys :: (MonadIO m) => String -> m KeyPair
|
||||
generateHydraKeys path = do
|
||||
output <- liftIO $
|
||||
readCreateProcess
|
||||
(proc hydraToolsPath [ "gen-hydra-key"
|
||||
, "--output-file"
|
||||
, [i|#{path}.hydra|]
|
||||
])
|
||||
""
|
||||
liftIO $ putStrLn output
|
||||
pure $ KeyPair [i|#{path}.hydra.sk|] [i|#{path}.hydra.vk|]
|
||||
|
||||
|
||||
publishReferenceScripts :: (MonadIO m) => m HydraScriptTxId
|
||||
publishReferenceScripts = do
|
||||
liftIO . putStrLn $ "Publishing reference scripts ('νInitial' & 'νCommit')..."
|
||||
fmap (T.strip . T.pack) $ liftIO $ readCreateProcess cp ""
|
||||
where
|
||||
cp = proc hydraNodePath [ "publish-scripts"
|
||||
, "--network-id"
|
||||
, show devnetNetworkId
|
||||
, "--node-socket"
|
||||
, "devnet/node.socket"
|
||||
, "--cardano-signing-key"
|
||||
, "devnet/credentials/faucet.sk"
|
||||
]
|
||||
|
||||
|
||||
waitForTxIn :: (MonadIO m) => TxIn -> m ()
|
||||
waitForTxIn txin = do
|
||||
liftIO . putStrLn $ "Waiting for utxo " <> show txin <> ".."
|
||||
liftIO waitFn
|
||||
where
|
||||
waitFn = do
|
||||
exists <- txInExists txin
|
||||
threadDelay 10000
|
||||
unless exists waitFn
|
||||
|
||||
txInExists :: TxIn -> IO Bool
|
||||
txInExists txin = do
|
||||
result <- fmap (T.strip . T.pack) $ readCreateProcess cp "" >>= readProcess jqPath (pure $ ".\"" <> asStr <> "\"")
|
||||
pure $ case result of
|
||||
"null" -> False
|
||||
_ -> True
|
||||
where
|
||||
asStr = T.unpack txin
|
||||
cp = (proc cardanoCliPath [ "query"
|
||||
, "utxo"
|
||||
, "--tx-in"
|
||||
, asStr
|
||||
, "--out-file"
|
||||
, "/dev/stdout"
|
||||
, "--testnet-magic"
|
||||
, "42"
|
||||
]) { env = Just [("CARDANO_NODE_SOCKET_PATH", "devnet/node.socket")] }
|
||||
|
||||
txInput :: Int -> TxId -> TxIn
|
||||
txInput index txid = txid <> "#" <> (T.pack . show) index
|
||||
|
||||
-- TODO: use this in checks?
|
||||
minTxLovelace :: Int
|
||||
minTxLovelace = 857690
|
||||
|
||||
queryAddressUTXOs :: MonadIO m => Address -> m WholeUTXO
|
||||
queryAddressUTXOs addr = liftIO $ do
|
||||
let queryProc =
|
||||
(proc cardanoCliPath [ "query"
|
||||
, "utxo"
|
||||
, "--address"
|
||||
, addr
|
||||
, "--testnet-magic"
|
||||
, "42"
|
||||
, "--out-file"
|
||||
, "/dev/stdout"
|
||||
])
|
||||
{ env = Just [("CARDANO_NODE_SOCKET_PATH", "devnet/node.socket")] }
|
||||
str <- readCreateProcess queryProc ""
|
||||
pure $ fromMaybe mempty $ decode $ BS.pack str
|
||||
|
||||
|
||||
getTempPath' :: IO FilePath
|
||||
getTempPath' = snd <$> getTempPath
|
||||
|
||||
getTempPath :: IO (UUID, FilePath)
|
||||
getTempPath = do
|
||||
createDirectoryIfMissing True "tmp"
|
||||
uid <- UUIDV4.nextRandom
|
||||
pure . (uid,) . ("tmp/" <>) . UUID.toString $ uid
|
||||
|
||||
-- TODO(skylar): Check lovelace vs the full amount!
|
||||
buildSignedHydraTx :: SigningKey -> Address -> Address -> Map TxIn Lovelace -> Lovelace -> IO String
|
||||
buildSignedHydraTx signingKey fromAddr toAddr txInAmounts amount = do
|
||||
let fullAmount = sum txInAmounts
|
||||
txBodyPath <- snd <$> getTempPath
|
||||
void $ readCreateProcess (proc cardanoCliPath
|
||||
([ "transaction"
|
||||
, "build-raw"
|
||||
, "--babbage-era"
|
||||
]
|
||||
<> (concatMap (\txin -> ["--tx-in", T.unpack txin]) . Map.keys $ txInAmounts)
|
||||
<>
|
||||
[ "--tx-out"
|
||||
, [i|#{toAddr}+#{amount}|]
|
||||
, "--tx-out"
|
||||
, [i|#{fromAddr}+#{fullAmount - amount}|]
|
||||
, "--fee"
|
||||
, "0"
|
||||
, "--out-file"
|
||||
, txBodyPath
|
||||
]))
|
||||
""
|
||||
readCreateProcess
|
||||
(proc cardanoCliPath
|
||||
[ "transaction"
|
||||
, "sign"
|
||||
, "--tx-body-file"
|
||||
, txBodyPath
|
||||
, "--signing-key-file"
|
||||
, signingKey
|
||||
, "--out-file"
|
||||
, "/dev/stdout"
|
||||
])
|
||||
""
|
||||
-- { env = Just [("CARDANO_NODE_SOCKET_PATH", "devnet/node.socket")] }
|
||||
|
||||
-- | Convenience for getting faucet Output for seeding
|
||||
getFirstTxIn :: Address -> IO TxIn
|
||||
getFirstTxIn addr =
|
||||
readCreateProcess cp "" >>= readProcess jqPath ["-r", "keys[0]"] >>= \a -> pure $ T.strip $ T.pack a
|
||||
where
|
||||
cp = (proc cardanoCliPath [ "query"
|
||||
, "utxo"
|
||||
, "--address"
|
||||
, addr
|
||||
, "--testnet-magic"
|
||||
, "42"
|
||||
, "--out-file"
|
||||
, "/dev/stdout"
|
||||
]) { env = Just [("CARDANO_NODE_SOCKET_PATH", "devnet/node.socket")] }
|
||||
|
||||
|
||||
getCardanoAddress :: VerificationKey -> IO Address
|
||||
getCardanoAddress keyPath =
|
||||
readCreateProcess cp ""
|
||||
where
|
||||
cp = (proc cardanoCliPath [ "address"
|
||||
, "build"
|
||||
, "--payment-verification-key-file"
|
||||
, keyPath
|
||||
, "--testnet-magic"
|
||||
, "42"
|
||||
]) { env = Just [("CARDANO_NODE_SOCKET_PATH", "devnet/node.socket")] }
|
||||
|
||||
|
||||
getFaucetAddress :: IO Address
|
||||
getFaucetAddress = readCreateProcess cp ""
|
||||
where
|
||||
cp = (proc cardanoCliPath [ "address"
|
||||
, "build"
|
||||
, "--payment-verification-key-file"
|
||||
, "devnet/credentials/faucet.vk"
|
||||
, "--testnet-magic"
|
||||
, "42"
|
||||
]) { env = Just [("CARDANO_NODE_SOCKET_PATH", "devnet/node.socket")] }
|
||||
|
||||
seedAddressFromFaucetAndWait :: (MonadIO m) => Address -> Lovelace -> Bool -> m TxIn
|
||||
seedAddressFromFaucetAndWait addr amount isFuel = do
|
||||
txin <- liftIO $ seedAddressFromFaucet addr amount isFuel
|
||||
waitForTxIn txin
|
||||
pure txin
|
||||
|
||||
-- | Send an amount in lovelace to the named actor
|
||||
seedAddressFromFaucet :: Address -> Lovelace -> Bool -> IO TxIn
|
||||
seedAddressFromFaucet addr amount isFuel = do
|
||||
draftTx <- buildSeedTxForAddress addr amount isFuel
|
||||
signedTx <- signSeedTx' draftTx
|
||||
txin <- txInput 0 <$> seedTxIdFromSignedTx signedTx
|
||||
submitTx signedTx
|
||||
pure txin
|
||||
|
||||
|
||||
buildSeedTxForAddress :: Address -> Lovelace -> Bool -> IO DraftTx
|
||||
buildSeedTxForAddress addr amount isFuel = do
|
||||
filename <- getTempPath'
|
||||
-- when (amount < minTxLovelace) $ error $ "Minmum required UTxO: Lovelace " <> show minTxLovelace
|
||||
let cp faucet hash = (proc cardanoCliPath $ filter (/= "")
|
||||
[ "transaction"
|
||||
, "build"
|
||||
, "--babbage-era"
|
||||
, "--cardano-mode"
|
||||
, "--change-address"
|
||||
, faucet
|
||||
, "--tx-in"
|
||||
, hash
|
||||
, "--tx-out"
|
||||
, addr <> "+" <> show amount
|
||||
]
|
||||
<> bool [] [ "--tx-out-datum-hash", T.unpack fuelMarkerDatumHash ] isFuel
|
||||
<>
|
||||
[ "--out-file"
|
||||
, filename
|
||||
, "--testnet-magic"
|
||||
, "42"
|
||||
])
|
||||
{ env = Just [("CARDANO_NODE_SOCKET_PATH", "devnet/node.socket")] }
|
||||
faucet <- getFaucetAddress
|
||||
hash <- getFirstTxIn faucet
|
||||
_ <- readCreateProcess (cp faucet (T.unpack hash)) ""
|
||||
pure filename
|
||||
|
||||
|
||||
signSeedTx' :: DraftTx -> IO SignedTx
|
||||
signSeedTx' draftFile = do
|
||||
outFile <- getTempPath'
|
||||
let cp = (proc cardanoCliPath [ "transaction"
|
||||
, "sign"
|
||||
, "--tx-body-file"
|
||||
, draftFile
|
||||
, "--signing-key-file"
|
||||
, "devnet/credentials/faucet.sk"
|
||||
, "--out-file"
|
||||
, outFile
|
||||
, "--testnet-magic"
|
||||
, "42"
|
||||
])
|
||||
{ env = Just [("CARDANO_NODE_SOCKET_PATH", "devnet/node.socket")] }
|
||||
_ <- readCreateProcess cp ""
|
||||
pure outFile
|
||||
|
||||
seedTxIdFromSignedTx :: SignedTx -> IO TxId
|
||||
seedTxIdFromSignedTx filename =
|
||||
T.strip . T.pack <$> readCreateProcess cp ""
|
||||
where
|
||||
cp = (proc cardanoCliPath [ "transaction"
|
||||
, "txid"
|
||||
, "--tx-file"
|
||||
, filename
|
||||
]) { env = Just [("CARDANO_NODE_SOCKET_PATH", "devnet/node.socket")] }
|
||||
|
||||
submitTx :: SignedTx -> IO ()
|
||||
submitTx signedFile = do
|
||||
_ <- readCreateProcess cp ""
|
||||
pure ()
|
||||
where
|
||||
cp = (proc cardanoCliPath [ "transaction"
|
||||
, "submit"
|
||||
, "--tx-file"
|
||||
, signedFile
|
||||
, "--testnet-magic"
|
||||
, "42"
|
||||
]) { env = Just [("CARDANO_NODE_SOCKET_PATH", "devnet/node.socket")] }
|
1
src/Hydra/NodeTypes.hs
Normal file
1
src/Hydra/NodeTypes.hs
Normal file
@ -0,0 +1 @@
|
||||
|
54
src/Hydra/ServerOutput.hs
Normal file
54
src/Hydra/ServerOutput.hs
Normal file
@ -0,0 +1,54 @@
|
||||
-- |
|
||||
|
||||
module Hydra.ServerOutput where
|
||||
|
||||
import GHC.Generics
|
||||
import Data.Aeson
|
||||
|
||||
import Data.Time (UTCTime)
|
||||
import Data.Text (Text)
|
||||
import Hydra.Types
|
||||
import Hydra.ClientInput
|
||||
|
||||
-- Copied and adapted from hydra-poc:hydra-node/src/hydra/ServerOutput.hs
|
||||
-- Anything that took effort was replaced by Value
|
||||
|
||||
data ServerOutput tx
|
||||
= PeerConnected {peer :: Host}
|
||||
| PeerDisconnected {peer :: Host}
|
||||
| ReadyToCommit {parties :: Value}
|
||||
| Committed {party :: Party, utxo :: WholeUTXO}
|
||||
| HeadIsOpen {utxo :: WholeUTXO}
|
||||
| HeadIsClosed
|
||||
{ snapshotNumber :: SnapshotNumber
|
||||
, -- | Nominal deadline until which contest can be submitted and after
|
||||
-- which fanout is possible. NOTE: Use this only for informational
|
||||
-- purpose and wait for 'ReadyToFanout' instead before sending 'Fanout'
|
||||
-- as the ledger of our cardano-node might not have progressed
|
||||
-- sufficiently in time yet and we do not re-submit transactions (yet).
|
||||
contestationDeadline :: UTCTime
|
||||
}
|
||||
| HeadIsContested {snapshotNumber :: SnapshotNumber}
|
||||
| ReadyToFanout
|
||||
| HeadIsAborted {utxo :: WholeUTXO}
|
||||
| HeadIsFinalized {utxo :: WholeUTXO}
|
||||
| CommandFailed {clientInput :: ClientInput}
|
||||
| TxSeen {transaction :: tx}
|
||||
| TxValid {transaction :: tx}
|
||||
| TxInvalid {utxo :: WholeUTXO, transaction :: tx, validationError :: ValidationError}
|
||||
| SnapshotConfirmed
|
||||
{ snapshot :: Snapshot tx
|
||||
, signatures :: MultiSignature (Snapshot tx)
|
||||
}
|
||||
| GetUTxOResponse {utxo :: WholeUTXO}
|
||||
| InvalidInput {reason :: String, input :: Text}
|
||||
| -- | A friendly welcome message which tells a client something about the
|
||||
-- node. Currently used for knowing what signing key the server uses (it
|
||||
-- only knows one).
|
||||
Greetings {me :: Party}
|
||||
| PostTxOnChainFailed {postChainTx :: PostChainTx tx, postTxError :: PostTxError tx}
|
||||
| RolledBack
|
||||
deriving (Eq, Show, Generic)
|
||||
|
||||
instance (ToJSON tx) => ToJSON (ServerOutput tx)
|
||||
instance (FromJSON tx) => FromJSON (ServerOutput tx)
|
63
src/Hydra/Types.hs
Normal file
63
src/Hydra/Types.hs
Normal file
@ -0,0 +1,63 @@
|
||||
-- |
|
||||
|
||||
module Hydra.Types where
|
||||
|
||||
import GHC.Generics
|
||||
import Data.Aeson
|
||||
|
||||
import Data.Map (Map)
|
||||
import qualified Data.Text as T
|
||||
import Data.Text (Text)
|
||||
import Numeric.Natural (Natural)
|
||||
|
||||
-- | Cardano address
|
||||
type Address = String
|
||||
|
||||
type Lovelace = Int
|
||||
|
||||
type TxIn = T.Text
|
||||
type WholeUTXO = Map TxIn TxInInfo
|
||||
|
||||
data TxInInfo = TxInInfo
|
||||
{ address :: Address
|
||||
, datumhash :: Maybe T.Text
|
||||
, value :: Map T.Text Int
|
||||
}
|
||||
deriving (Eq, Show, Generic)
|
||||
|
||||
instance FromJSON TxInInfo
|
||||
instance ToJSON TxInInfo
|
||||
|
||||
fuelMarkerDatumHash :: T.Text
|
||||
fuelMarkerDatumHash = "a654fb60d21c1fed48db2c320aa6df9737ec0204c0ba53b9b94a09fb40e757f3"
|
||||
|
||||
|
||||
-- REVIEW(SN): This is also used in hydra-tui
|
||||
|
||||
-- Below various types copied/adapted from hydra-poc code
|
||||
|
||||
data Host = Host
|
||||
{ hostname :: Text
|
||||
, port :: PortNumber
|
||||
}
|
||||
deriving (Ord, Generic, Eq, Show)
|
||||
|
||||
instance ToJSON Host
|
||||
instance FromJSON Host
|
||||
|
||||
|
||||
newtype Party = Party {vkey :: T.Text}
|
||||
deriving (Eq, Show, Read, Generic)
|
||||
|
||||
instance ToJSON Party
|
||||
instance FromJSON Party
|
||||
|
||||
type UTxOType tx = Value
|
||||
type Snapshot tx = Value
|
||||
type MultiSignature x = Value
|
||||
type PostChainTx tx = Value
|
||||
type PostTxError tx = Value
|
||||
type ValidationError = Value
|
||||
type SnapshotNumber = Natural
|
||||
type PortNumber = Natural
|
||||
type ContestationPeriod = Natural
|
650
src/Main.hs
Normal file
650
src/Main.hs
Normal file
@ -0,0 +1,650 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE PartialTypeSignatures #-}
|
||||
{-# OPTIONS_GHC -Wno-unused-do-bind #-}
|
||||
{-# LANGUAGE TupleSections #-}
|
||||
{-# LANGUAGE ConstraintKinds #-}
|
||||
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
|
||||
|
||||
|
||||
module Main
|
||||
|
||||
(main)
|
||||
|
||||
where
|
||||
|
||||
import Prelude hiding (filter)
|
||||
|
||||
import Hydra.Devnet
|
||||
|
||||
import Control.Monad
|
||||
|
||||
import System.Directory
|
||||
import Control.Monad.IO.Class (MonadIO, liftIO)
|
||||
|
||||
import qualified Data.Map as Map
|
||||
import Data.Map (Map, (!))
|
||||
import Data.Witherable
|
||||
import Data.String.Interpolate ( i, iii, __i )
|
||||
import qualified Data.Text as T
|
||||
|
||||
import Control.Concurrent
|
||||
import System.Process
|
||||
|
||||
import Data.Aeson as Aeson
|
||||
( decode, (.:), withObject, Value )
|
||||
|
||||
import Data.Aeson.Text (encodeToTextBuilder)
|
||||
import Data.Text.Lazy (toStrict)
|
||||
import Data.Text.Lazy.Builder (toLazyText)
|
||||
|
||||
import qualified Data.Map.Merge.Lazy as Map
|
||||
import qualified Hydra.Types as HT
|
||||
import Data.Maybe (fromJust, fromMaybe)
|
||||
import Data.Aeson.Types (parseMaybe)
|
||||
import System.IO (IOMode(WriteMode), openFile)
|
||||
import Data.IORef (readIORef, writeIORef, IORef, newIORef)
|
||||
import Hydra.Types
|
||||
import Data.Text (Text)
|
||||
import qualified Data.ByteString.Lazy.Char8 as ByteString.Char8
|
||||
import Data.Time (UTCTime, diffUTCTime)
|
||||
|
||||
import Reflex
|
||||
import Reflex.Dom
|
||||
import Control.Monad.Fix
|
||||
import Hydra.ClientInput
|
||||
import Hydra.ServerOutput
|
||||
import Data.Bool (bool)
|
||||
import Text.Read (readMaybe)
|
||||
import Data.Traversable (for)
|
||||
import Data.Semigroup (First(getFirst, First))
|
||||
import Data.Aeson
|
||||
|
||||
import Control.Monad.Trans (lift)
|
||||
import Language.Javascript.JSaddle.Types ( MonadJSM )
|
||||
|
||||
standupDemoHydraNetwork :: (MonadIO m)
|
||||
=> HydraScriptTxId
|
||||
-> Map Text HydraKeyInfo
|
||||
-> m (Map Text (ProcessHandle, HydraNodeInfo))
|
||||
standupDemoHydraNetwork hstxid actors = do
|
||||
liftIO $ createDirectoryIfMissing True "demo-logs"
|
||||
liftIO $ sequence . flip Map.mapWithKey nodes $ \name node'' -> do
|
||||
logHndl <- openFile [iii|demo-logs/hydra-node-#{name}.log|] WriteMode
|
||||
errHndl <- openFile [iii|demo-logs/phydra-node-#{name}.error.log|] WriteMode
|
||||
let cp = (mkHydraNodeCP sharedInfo node'' (filter ((/= _nodeId node'') . _nodeId) (Map.elems nodes)))
|
||||
{ std_out = UseHandle logHndl
|
||||
, std_err = UseHandle errHndl
|
||||
}
|
||||
(_,_,_,handle) <- createProcess cp
|
||||
pure (handle, node'')
|
||||
where
|
||||
portNum p n = p * 1000 + n
|
||||
node' (n, (name, keys)) =
|
||||
( name
|
||||
, HydraNodeInfo n (portNum 5 n) (portNum 9 n) (portNum 6 n) keys
|
||||
)
|
||||
nodes = Map.fromList . fmap node' $ zip [1 ..] (Map.toList actors)
|
||||
sharedInfo = HydraSharedInfo
|
||||
{ _hydraScriptsTxId = T.unpack hstxid
|
||||
, _ledgerGenesis = "devnet/genesis-shelley.json"
|
||||
, _ledgerProtocolParameters = "devnet/protocol-parameters.json"
|
||||
, _networkId = show devnetMagic
|
||||
, _nodeSocket = "devnet/node.socket"
|
||||
}
|
||||
|
||||
-- | Takes the node participant and the list of peers
|
||||
mkHydraNodeCP :: HydraSharedInfo -> HydraNodeInfo -> [HydraNodeInfo] -> CreateProcess
|
||||
mkHydraNodeCP sharedInfo node peers =
|
||||
(proc hydraNodePath $ sharedArgs sharedInfo <> nodeArgs node <> concatMap peerArgs peers)
|
||||
{ std_out = Inherit
|
||||
}
|
||||
|
||||
data HydraSharedInfo = HydraSharedInfo
|
||||
{ _hydraScriptsTxId :: String
|
||||
, _ledgerGenesis :: FilePath
|
||||
, _ledgerProtocolParameters :: FilePath
|
||||
, _networkId :: String
|
||||
, _nodeSocket :: FilePath
|
||||
}
|
||||
|
||||
data HydraNodeInfo = HydraNodeInfo
|
||||
{ _nodeId :: Int
|
||||
, _port :: Int
|
||||
, _apiPort :: Int
|
||||
, _monitoringPort :: Int
|
||||
, _keys :: HydraKeyInfo
|
||||
}
|
||||
|
||||
sharedArgs :: HydraSharedInfo -> [String]
|
||||
sharedArgs (HydraSharedInfo hydraScriptsTxId ledgerGenesis protocolParams networkId nodeSocket) =
|
||||
[ "--ledger-genesis"
|
||||
, ledgerGenesis
|
||||
, "--ledger-protocol-parameters"
|
||||
, protocolParams
|
||||
, "--network-id"
|
||||
, networkId
|
||||
, "--node-socket"
|
||||
, nodeSocket
|
||||
, "--hydra-scripts-tx-id"
|
||||
, hydraScriptsTxId
|
||||
]
|
||||
|
||||
nodeArgs :: HydraNodeInfo -> [String]
|
||||
nodeArgs (HydraNodeInfo nodeId port' apiPort monitoringPort
|
||||
(HydraKeyInfo
|
||||
(KeyPair cskPath _cvkPath)
|
||||
(KeyPair hskPath _hvkPath))) =
|
||||
[ "--node-id"
|
||||
, show nodeId
|
||||
, "--port"
|
||||
, show port'
|
||||
, "--api-port"
|
||||
, show apiPort
|
||||
, "--monitoring-port"
|
||||
, show monitoringPort
|
||||
, "--hydra-signing-key"
|
||||
, hskPath
|
||||
, "--cardano-signing-key"
|
||||
, cskPath
|
||||
]
|
||||
|
||||
peerArgs :: HydraNodeInfo -> [String]
|
||||
peerArgs ni =
|
||||
[ "--peer"
|
||||
, [i|127.0.0.1:#{_port ni}|]
|
||||
, "--hydra-verification-key"
|
||||
, _verificationKey . _hydraKeys . _keys $ ni
|
||||
, "--cardano-verification-key"
|
||||
, _verificationKey . _cardanoKeys . _keys $ ni
|
||||
]
|
||||
|
||||
cardanoNodeCreateProcess :: CreateProcess
|
||||
cardanoNodeCreateProcess =
|
||||
(proc cardanoNodePath
|
||||
[ "run"
|
||||
, "--config"
|
||||
, "devnet/cardano-node.json"
|
||||
, "--topology"
|
||||
, "devnet/topology.json"
|
||||
, "--database-path"
|
||||
, "devnet/db"
|
||||
, "--socket-path"
|
||||
, "devnet/node.socket"
|
||||
, "--shelley-operational-certificate"
|
||||
, "devnet/opcert.cert"
|
||||
, "--shelley-kes-key"
|
||||
, "devnet/kes.skey"
|
||||
, "--shelley-vrf-key"
|
||||
, "devnet/vrf.skey"
|
||||
]) { std_out = CreatePipe
|
||||
}
|
||||
|
||||
runHydraDemo :: (MonadIO m)
|
||||
=> HydraDemo
|
||||
-> m (Map Text ( ProcessHandle
|
||||
, Address -- Cardano address
|
||||
, HydraNodeInfo
|
||||
))
|
||||
runHydraDemo nodes = do
|
||||
keysAddresses <- forM nodes $ \(actorSeed, fuelSeed) -> do
|
||||
keys@(HydraKeyInfo (KeyPair _ vk) _) <- generateKeys
|
||||
addr <- liftIO $ getCardanoAddress vk
|
||||
void $ seedAddressFromFaucetAndWait addr actorSeed False
|
||||
void $ seedAddressFromFaucetAndWait addr fuelSeed True
|
||||
pure (keys, addr)
|
||||
liftIO . putStrLn $ "Publishing reference scripts"
|
||||
hstxid <- publishReferenceScripts
|
||||
handles <- standupDemoHydraNetwork hstxid (fmap fst keysAddresses)
|
||||
liftIO . putStrLn $ [i|"Hydra Network Running for nodes #{Map.keys nodes}|]
|
||||
pure $ Map.merge Map.dropMissing Map.dropMissing (Map.zipWithMatched (\_ addr (handle, nodeInfo) -> (handle, addr, nodeInfo))) (fmap snd keysAddresses) handles
|
||||
|
||||
|
||||
type State = Map Text ( ProcessHandle
|
||||
, Address -- Cardano address
|
||||
, HydraNodeInfo
|
||||
)
|
||||
|
||||
headElement :: forall t m. ( TriggerEvent t m, DomBuilder t m) =>m ()
|
||||
headElement = do
|
||||
el "title" $ text "Hydra Head Demo"
|
||||
elAttr "script" ("src"=:"https://cdn.tailwindcss.com") blank
|
||||
|
||||
main :: IO ()
|
||||
main = liftIO $ do
|
||||
prepareDevnet
|
||||
withCreateProcess cardanoNodeCreateProcess $ \_ _stdout _ _handle -> do
|
||||
putStrLn "Devnet is running"
|
||||
threadDelay $ seconds 3
|
||||
mainWidgetWithHead headElement app
|
||||
|
||||
makeTx :: () => IORef State -> Text
|
||||
-> Map TxIn TxInInfo -> Lovelace -> Text -> IO Text
|
||||
makeTx hydraProcessHandlesRef fromName utxos lovelace toName = do
|
||||
print (fromName, utxos, toName)
|
||||
let lovelaceUtxos = mapMaybe (Map.lookup "lovelace" . HT.value) utxos
|
||||
actors <- readIORef hydraProcessHandlesRef
|
||||
jsonStr <-
|
||||
buildSignedHydraTx
|
||||
(_signingKey . _cardanoKeys . _keys . (\(_, _, hn) -> hn) $ actors ! fromName)
|
||||
((\(_, addr, _) -> addr) $ actors ! fromName)
|
||||
((\(_, addr, _) -> addr) $ actors ! toName)
|
||||
lovelaceUtxos
|
||||
lovelace
|
||||
let jsonTx :: Aeson.Value = fromMaybe (error "Failed to parse TX") . Aeson.decode . ByteString.Char8.pack $ jsonStr
|
||||
pure . fromJust . parseMaybe (withObject "signed tx" (.: "cborHex")) $ jsonTx
|
||||
|
||||
startDemo :: MonadIO m => IORef State -> HydraDemo -> m RunningNodes
|
||||
startDemo hydraProcessHandlesRef demo = do
|
||||
liftIO (mapM (terminateProcess . (\(hndl, _, _) -> hndl)) =<< readIORef hydraProcessHandlesRef)
|
||||
nodeInfos <- runHydraDemo demo
|
||||
liftIO . writeIORef hydraProcessHandlesRef $ nodeInfos
|
||||
actorList :: RunningNodes <- forM nodeInfos $ \(_, addr, nInfo) -> do
|
||||
pure
|
||||
( addr,
|
||||
[iii|ws://localhost:#{_apiPort nInfo}|]
|
||||
)
|
||||
pure actorList
|
||||
|
||||
-- | Friendly name for a Hydra node.
|
||||
type DemoNodeName = Text
|
||||
|
||||
-- | WebSocket URL
|
||||
type ApiUrl = Text
|
||||
|
||||
type RunningNodes = Map DemoNodeName ( Address -- Cardano address
|
||||
, ApiUrl
|
||||
)
|
||||
|
||||
type HydraDemo = Map
|
||||
DemoNodeName
|
||||
( Lovelace -- Seed for actor
|
||||
, Lovelace -- Seed for fuel
|
||||
)
|
||||
|
||||
|
||||
seconds :: Int -> Int
|
||||
seconds = (* 1000000)
|
||||
|
||||
alicebobcarolDemo :: HydraDemo
|
||||
alicebobcarolDemo = Map.fromList [("Alice", (1000000000, 100000000)), ("Bob", (500000000, 100000000)), ("Carol", (250000000, 100000000))]
|
||||
|
||||
|
||||
filterOutFuel :: WholeUTXO -> WholeUTXO
|
||||
filterOutFuel = Map.filter (not . isFuel)
|
||||
|
||||
isFuel :: TxInInfo -> Bool
|
||||
isFuel txinfo = datumhash txinfo == Just fuelMarkerDatumHash
|
||||
|
||||
-- | Tracks the state of the head based on Hydra Node responses
|
||||
data HeadState
|
||||
= Idle
|
||||
| Initializing
|
||||
| Open
|
||||
| Closed UTCTime
|
||||
| StateReadyToFanout
|
||||
deriving (Eq, Show)
|
||||
|
||||
|
||||
buttonClass :: (PostBuild t m, DomBuilder t m) => Dynamic t T.Text -> m b -> m (Event t ())
|
||||
buttonClass cls content = do
|
||||
(buttonEl, _) <- elDynClass' "button" cls content
|
||||
pure $ domEvent Click buttonEl
|
||||
|
||||
|
||||
utxoPicker :: forall t m. (DomBuilder t m, MonadFix m, MonadHold t m, PostBuild t m) => Bool -> WholeUTXO -> m (Dynamic t (Maybe WholeUTXO))
|
||||
utxoPicker pickable wholeUtxo = mdo
|
||||
elClass "div" "font-semibold text-lg mb-2" $ text "UTxOs"
|
||||
|
||||
currentUtxo <- holdDyn Nothing selectedUtxo
|
||||
selectedUtxo <- fmap (leftmost . Map.elems) $ elClass "div" "flex flex-row flex-wrap gap-2" $ flip Map.traverseWithKey wholeUtxo $ \k v -> mdo
|
||||
let amiSelected = maybe False ((k ==) . fst) <$> currentUtxo
|
||||
let cls = ("text-white font-bold text-xl px-4 py-2 rounded-md flex flex-row cursor-pointer mr-2 " <>)
|
||||
. bool
|
||||
"bg-gray-500 hover:bg-gray-400 active:bg-gray-300"
|
||||
"bg-blue-500 hover:bg-blue-400 active:bg-blue-300"
|
||||
<$> amiSelected
|
||||
(buttonEl, _) <- elDynClass' "button" cls $ do
|
||||
elClass "div" "text-sm text-gray-300 font-semibold flex justify-between" $ do
|
||||
elClass "div" "flex flex-col" $ do
|
||||
elClass "div" "w-full flex flex-row justify-between" $ do
|
||||
elClass "div" "text-gray-400 mr-4" $ text "lovelace"
|
||||
when (isFuel v) $ elClass "div" "px-2 py-0 flex items-center justify-center leading-node bg-green-500 text-xs text-white font-semibold text-sm rounded-full flex" $
|
||||
el "div" $ text "FUEL"
|
||||
elClass "div" "text-lg text-left font-semibold" $ text $ maybe "" (T.pack . show) (Map.lookup "lovelace" $ HT.value v)
|
||||
|
||||
pure $ bool Nothing (Just (k, v)) . (pickable &&) . not <$> current amiSelected <@ domEvent Click buttonEl
|
||||
pure $ fmap (uncurry Map.singleton) <$> currentUtxo
|
||||
|
||||
demoSettings :: (DomBuilder t m, PostBuild t m, MonadHold t m, MonadFix m) => HydraDemo -> m (Dynamic t HydraDemo)
|
||||
demoSettings setngs = elClass "div" "flex flex-col pl-4 pr-4" $ do
|
||||
let initSize = Map.size setngs
|
||||
let initialList = Map.fromList (zip [1 .. ] (Map.toList setngs))
|
||||
rec
|
||||
nextIdentityNumber <- fmap (1 + initSize +) <$> count newNode
|
||||
let updates =
|
||||
((\n -> Map.singleton n (Just ([i|Node #{n}|], (100000000, 100000000)))) <$> current nextIdentityNumber <@ newNode)
|
||||
<> deleteEs
|
||||
(((), deleteEs), demoDyn) <- runDynamicWriterT $ runEventWriterT $ void $ elClass "div" "flex-col space-y-2" $ do
|
||||
elClass "p" "text-white text-2xl my-4" $ text "Configure a Hydra Head by specifying the node names and their initial funds in Lovelace."
|
||||
listHoldWithKey initialList updates $ \k (name, (actorSeed, _hydraSeed)) -> elClass "div" "flex flex-col" $ do
|
||||
name' <- elClass "div" "flex flex-row space-x-2" $ do
|
||||
name' <- fmap _inputElement_value . inputElement $
|
||||
def & inputElementConfig_initialValue .~ name
|
||||
& initialAttributes .~ ("class" =: "text-white bg-gray-800 text-2xl font-bold focus:outline-none p-2" <> "type" =: "text")
|
||||
amount' <- fmap _inputElement_value . inputElement $
|
||||
def & inputElementConfig_initialValue .~ (T.pack . show $ actorSeed)
|
||||
& initialAttributes .~ ("class" =: "text-white bg-gray-800 text-2xl font-bold focus:outline-none p-2" <> "type" =: "number")
|
||||
deleteE <- buttonClass "bg-gray-400 hover:bg-gray-300 active:bg-gray-200 text-white font-bold text-xl px-4 py-2 rounded-md" $
|
||||
text "×"
|
||||
let actorSeed' = (\n a -> (n,) <$> readMaybe (T.unpack a)) <$> name' <*> amount'
|
||||
tellDyn (maybe mempty (Map.singleton k. (\(actor,sd) -> (actor, (sd, 100000000)))) <$> actorSeed')
|
||||
tellEvent (Map.singleton k Nothing <$ deleteE)
|
||||
pure name'
|
||||
let hasDuplicateName = (\n ns -> (> 1) . Map.size . Map.filter (\(n',_) -> n == n') $ ns) <$> name' <*> demoDyn
|
||||
let duplicateNameMsg = elClass "div" "text-red-400 m-2" $ text "Duplicate name"
|
||||
dyn_ (bool blank duplicateNameMsg <$> fromUniqDynamic (uniqDynamic hasDuplicateName))
|
||||
pure ()
|
||||
newNode <- buttonClass "bg-gray-400 hover:bg-gray-300 active:bg-gray-200 text-white font-bold text-xl my-4 px-4 py-2 rounded-md w-32" $
|
||||
text "Add node"
|
||||
let demoDyn' = Map.fromList . Map.elems <$> demoDyn
|
||||
pure demoDyn'
|
||||
|
||||
startStopDemoControls ::
|
||||
( DomBuilder t m,
|
||||
MonadFix m,
|
||||
PostBuild t m,
|
||||
MonadHold t m, MonadIO (Performable m), PerformEvent t m) =>
|
||||
IORef State ->
|
||||
m (Event t RunningNodes)
|
||||
startStopDemoControls hydraProcessHandlesRef = mdo
|
||||
headRunning <- toggle False headStartedOrStoppedE
|
||||
((), demoConfig) <- runDynamicWriterT $ dyn_ (bool (tellDyn =<< demoSettings alicebobcarolDemo) blank <$> headRunning)
|
||||
startStopHeadE <- buttonClass ((\running ->
|
||||
let color :: Text = bool "green" "red" running
|
||||
in [__i|bg-#{color}-500 hover:bg-#{color}-400 active:bg-#{color}-300
|
||||
text-white font-bold text-xl m-4 px-4 py-2 rounded-md|]
|
||||
:: Text)
|
||||
<$> headRunning)
|
||||
$ dynText (bool "Start head" "Stop head" <$> headRunning)
|
||||
let startStopWithConfE = current demoConfig <@ startStopHeadE
|
||||
headStartedOrStoppedE <- performEvent $
|
||||
-- Start with mempty to stop the demo:
|
||||
(\running conf -> startDemo hydraProcessHandlesRef $ bool conf mempty running)
|
||||
<$> current headRunning
|
||||
<@> startStopWithConfE
|
||||
let headStartingDom conf =
|
||||
if Map.null conf
|
||||
then blank
|
||||
else elClass "div" "text-white text-2xl m-4" $ text "Head starting..."
|
||||
void $ runWithReplace blank $ leftmost [ headStartingDom <$> startStopWithConfE
|
||||
, blank <$ headStartedOrStoppedE
|
||||
]
|
||||
pure headStartedOrStoppedE
|
||||
|
||||
|
||||
app ::
|
||||
forall t m.
|
||||
( PostBuild t m,
|
||||
DomBuilder t m,
|
||||
MonadFix m,
|
||||
MonadJSM m, MonadJSM (Performable m),
|
||||
MonadHold t m, PerformEvent t m, TriggerEvent t m) =>
|
||||
m ()
|
||||
app = do
|
||||
hydraProcessHandlesRef :: IORef State <- liftIO (newIORef mempty)
|
||||
elClass "div" "w-screen h-screen bg-gray-900 overflow-y-scroll overflow-x-hidden" $ do
|
||||
elClass "div" "p-4 m-4 text-white text-5xl font-bold" $ text "Hydra Proof Of Concept Demo"
|
||||
mdo
|
||||
headStartedE <- startStopDemoControls hydraProcessHandlesRef
|
||||
void $ runWithReplace blank $ ffor headStartedE $ \actors -> mdo
|
||||
let actorNames = ffor (Map.toList actors) $ \(name, (_,_)) -> name
|
||||
headState <- holdDyn Idle newState
|
||||
let headStateDom = elClass "div" "text-lg" . text . ("Head State: " <>)
|
||||
unless (null actors) $ elClass "div" "ml-4 mt-8 mr-4 mb-2 w-full font-black text-green-500" $ dyn_ $ ffor headState $ \case
|
||||
Idle -> do
|
||||
headStateDom "Idle"
|
||||
elClass "div" "text-green-700 text-sm" $ text "Waiting for participant to init..."
|
||||
Initializing -> do
|
||||
headStateDom "Initializing"
|
||||
elClass "div" "text-green-700 text-sm" $ text $ "Waiting for commits from: " <> T.intercalate ", " actorNames
|
||||
Open -> headStateDom "Open"
|
||||
Closed _ -> headStateDom "Closed/Contestation period"
|
||||
StateReadyToFanout -> headStateDom "Ready to fanout"
|
||||
|
||||
newState <- elClass "div" "ml-4 mr-4 overflow-hidden rounded-lg hover:drop-shadow-xl transition-all drop-shadow bg-gray-800" $ mdo
|
||||
rec
|
||||
currentTab <- holdDyn (head actorNames) changeTab
|
||||
|
||||
changeTab <- fmap leftmost $ elClass "div" "w-full flex flex-row justify-start" $ for actorNames $ \name -> do
|
||||
let
|
||||
isSelected = (== name) <$> currentTab
|
||||
mkClasses selected =
|
||||
T.intercalate " " [ "leading-none p-4 font-bold text-2xl text-gray-100 flex items-center justify-center"
|
||||
, bool "bg-gray-800 text-gray-300 pointer-cursor" "bg-gray-700 text-gray-100" selected
|
||||
]
|
||||
(buttonEl, _) <- elDynClass' "button" (mkClasses <$> isSelected) $ text name
|
||||
pure $ name <$ domEvent Click buttonEl
|
||||
fmap (fmap getFirst . snd) . runEventWriterT $ forM (Map.toList actors) $ \(name, (actorAddress, wsUrl)) -> mdo
|
||||
let wsCfg = (WebSocketConfig @t @ClientInput) action never True []
|
||||
ws <- jsonWebSocket wsUrl wsCfg
|
||||
let isSelected = (== name) <$> currentTab
|
||||
let mkClasses selected =
|
||||
T.intercalate " " [ "p-2 bg-gray-700 text-white flex flex-col items-left"
|
||||
, bool "hidden" "" selected
|
||||
]
|
||||
(_, action) <- elDynClass "div" (mkClasses <$> isSelected) $ runEventWriterT $ runWithReplace (elClass "div" "text-white" $ text "Connecting to node...") . ffor (_webSocket_open ws) $ \() -> do
|
||||
let
|
||||
webSocketMessage :: Event t (ServerOutput Aeson.Value) =
|
||||
fromMaybe (error "Parsing message from Hydra node failed") <$> _webSocket_recv ws
|
||||
processLog = \case
|
||||
ReadyToCommit {} -> Just Initializing
|
||||
HeadIsOpen {} -> Just Open
|
||||
HeadIsClosed _ fanoutTime -> Just (Closed fanoutTime)
|
||||
ReadyToFanout {} -> Just StateReadyToFanout
|
||||
HeadIsAborted {} -> Just Idle
|
||||
HeadIsFinalized {} -> Just Idle
|
||||
_ -> Nothing
|
||||
let stateChange = fmapMaybe processLog webSocketMessage
|
||||
let
|
||||
|
||||
myVKeyB :: Behavior t (Maybe T.Text) <-
|
||||
hold Nothing
|
||||
. fmap Just
|
||||
. mapMaybe (\case
|
||||
Greetings (Party vkey') -> Just vkey'
|
||||
_ -> Nothing)
|
||||
$ webSocketMessage
|
||||
headStateE <- mdo
|
||||
void $ dyn $ ffor headState $ \case
|
||||
Idle -> idleScreen name
|
||||
Initializing -> initializingScreen actorAddress myVKeyB webSocketMessage
|
||||
Open -> openScreen hydraProcessHandlesRef name actorNames actorAddress webSocketMessage
|
||||
Closed fanoutTime -> closedScreen fanoutTime
|
||||
StateReadyToFanout ->
|
||||
tellAction
|
||||
. (Fanout <$)
|
||||
<=< buttonClass "bg-green-400 hover:bg-green-400 active:bg-green-200 text-white font-bold text-xl my-2 px-4 py-2 rounded-md w-32" $ text "Do fanout"
|
||||
elClass "div" "mt-4" $ do
|
||||
elClass "div" "mb-1 font-semibold text-sm" $ text "Hydra Node Log"
|
||||
elClass "div" "p-2 bg-gray-800 rounded-md drop-shadow" $
|
||||
el "ul" $ do
|
||||
comms <- foldDyn (++) [] $
|
||||
((:[]) . ("Rcv: " <>) . toStrict . toLazyText . encodeToTextBuilder . toJSON <$> webSocketMessage)
|
||||
<>
|
||||
fmap (fmap (("Snd: " <>) . toStrict . toLazyText . encodeToTextBuilder . toJSON)) action
|
||||
dyn_ $ mapM (el "li" . text) <$> comms
|
||||
pure stateChange
|
||||
lift $ tellEvent (First <$> headStateE)
|
||||
pure ()
|
||||
pure ()
|
||||
|
||||
filterUtxos :: Address -> WholeUTXO -> WholeUTXO
|
||||
filterUtxos addr = Map.filter ((== addr) . HT.address)
|
||||
|
||||
tellAction :: (EventWriter t [a] m, Reflex t) => Event t a -> m ()
|
||||
tellAction = tellEvent . fmap (:[])
|
||||
|
||||
idleScreen :: (EventWriter t [ClientInput] m, DomBuilder t m) => Text -> m ()
|
||||
idleScreen name =
|
||||
elClass "div" "p-2 flex flex-row" $ do
|
||||
(buttonEl, _) <- elClass' "button" "bg-blue-500 hover:bg-blue-400 active:bg-blue-300 text-white font-bold text-xl px-4 py-2 rounded-md" $ text $ "Initialize head as " <> name
|
||||
tellAction $ Init 10 <$ domEvent Click buttonEl
|
||||
|
||||
initializingScreen ::
|
||||
( EventWriter t [ClientInput] m,
|
||||
DomBuilder t m,
|
||||
MonadFix m,
|
||||
MonadHold t m,
|
||||
PostBuild t m, MonadIO m) =>
|
||||
Address ->
|
||||
Behavior t (Maybe Text) ->
|
||||
Event t (ServerOutput tx) ->
|
||||
m ()
|
||||
initializingScreen actorAddress myVKeyB webSocketMessage = do
|
||||
elClass "div" "p-2 flex flex-col" $ do
|
||||
-- TODO: did not use performEvent here
|
||||
newUTXOs <- liftIO $ queryAddressUTXOs actorAddress -- fmapMaybe eitherToMaybe <$> (undefined . (DemoApi_GetActorUTXO actorAddress <$) =<< getPostBuild)
|
||||
let commitSelection doCommit = do
|
||||
(_, currentSet) <-
|
||||
runDynamicWriterT $ (tellDyn <=< utxoPicker True) newUTXOs
|
||||
-- runWithReplace (elClass "div" "p-4 bg-gray-800 rounded mb-2" $ text $ "Getting " <> name <> "'s UTXOs...") $
|
||||
-- (tellDyn <=< utxoPicker True) <$> newUTXOs
|
||||
tellAction $ fmap (Commit . fromMaybe mempty) $ current currentSet <@ doCommit
|
||||
let hasCommitted =
|
||||
attachWithMaybe
|
||||
( \mvkey -> \case
|
||||
Committed (Party vk) _ -> guard (Just vk == mvkey)
|
||||
_ -> Nothing
|
||||
)
|
||||
myVKeyB
|
||||
webSocketMessage
|
||||
|
||||
mdo
|
||||
void . runWithReplace (commitSelection doCommit) . ffor hasCommitted $ \() ->
|
||||
elClass "div" "text-xl py-4" $ text "Committed, waiting for the others."
|
||||
doCommit <- elClass "div" "flex flex-row mt-4" $ do
|
||||
-- Until the head is committed starting the head can be aborted:
|
||||
tellAction
|
||||
. (Hydra.ClientInput.Abort <$)
|
||||
<=< buttonClass "bg-gray-400 hover:bg-gray-300 active:bg-gray-200 text-white font-bold text-xl px-4 py-2 rounded-md mr-2"
|
||||
$ text "Abort"
|
||||
isDisabled <- holdDyn False (True <$ hasCommitted)
|
||||
let cls =
|
||||
(bool "bg-blue-500 hover:bg-blue-400 active:bg-blue-300" "bg-gray-500 hover:bg-gray-500 active:bg-gray-500 cursor-not-allowed " <$> isDisabled)
|
||||
<> " text-white font-bold text-xl px-4 py-2 rounded-md"
|
||||
buttonClass cls $ text "Commit"
|
||||
pure ()
|
||||
pure ()
|
||||
|
||||
|
||||
openScreen ::
|
||||
( EventWriter t [ClientInput] m,
|
||||
DomBuilder t m,
|
||||
MonadFix m,
|
||||
MonadHold t m,
|
||||
PostBuild t m,
|
||||
MonadIO (Performable m), PerformEvent t m) =>
|
||||
IORef State ->
|
||||
Text ->
|
||||
[Text] ->
|
||||
Address ->
|
||||
Event t (ServerOutput tx) ->
|
||||
m ()
|
||||
openScreen hydraProcessHandlesRef name actorNames actorAddress webSocketMessage = do
|
||||
-- Get your UTxOs on page load and when we observe a transaction
|
||||
tellAction . (GetUTxO <$)
|
||||
. ( ( void $
|
||||
filter
|
||||
( \case
|
||||
TxSeen {} -> True
|
||||
_ -> False
|
||||
)
|
||||
webSocketMessage
|
||||
)
|
||||
<>
|
||||
)
|
||||
=<< getPostBuild
|
||||
let updatedUTXOs =
|
||||
fmap (filterUtxos actorAddress)
|
||||
. mapMaybe
|
||||
( \case
|
||||
GetUTxOResponse utxoz -> Just utxoz
|
||||
_ -> Nothing
|
||||
)
|
||||
$ webSocketMessage
|
||||
currentUTXOs <- holdDyn mempty updatedUTXOs
|
||||
let ifUTXOs yes no = dyn_ (bool yes no <$> fmap Map.null currentUTXOs)
|
||||
ifUTXOsDyn yes no = dyn (bool yes no <$> fmap Map.null currentUTXOs)
|
||||
mdo
|
||||
(_, currentSet) <-
|
||||
runDynamicWriterT
|
||||
. runWithReplace (elClass "div" "text-white text-2xl" $ text "Getting your UTxOs")
|
||||
$ fmap (tellDyn <=< (pure . pure . filterOutFuel)) updatedUTXOs
|
||||
_ <- elClass "div" "mb-4 ml-2" $ dyn_ $ utxoPicker False <$> currentSet
|
||||
elClass "div" "text-xl mb-8 ml-2" $ ifUTXOs (text "Send Ada to a participant:") (text "No UTXOs for this participant")
|
||||
flip ifUTXOs blank $ do
|
||||
(recipientDyn, lovelaceDyn) <- elClass "div" "flex ml-2 mb-2" $
|
||||
elClass "div" "w-auto flex flex-row rounded bg-gray-800 mb-2 overflow-hidden" $ do
|
||||
ie <- elClass "div" "flex flex-col p-2" $ do
|
||||
elClass "div" "text-gray-600 text-sm font-semibold" $ text "LOVELACES"
|
||||
inputElement $
|
||||
def
|
||||
& initialAttributes .~ ("class" =: "bg-gray-800 text-2xl font-bold focus:outline-none p-2" <> "type" =: "number")
|
||||
& inputElementConfig_initialValue .~ "1000000"
|
||||
recipient <- fmap Reflex.Dom.value $
|
||||
elClass "div" "flex flex-col p-2" $ do
|
||||
elClass "div" "text-gray-600 text-sm font-semibold uppercase" $ text "To"
|
||||
-- FIXME: unsafe head, will crash with <= 1 actors
|
||||
dropdown
|
||||
(head $ filter (/= name) actorNames)
|
||||
(pure (Map.filter (/= name) $ Map.fromList (fmap (\n -> (n, n)) actorNames)))
|
||||
$ def & dropdownConfig_attributes .~ pure ("class" =: "bg-gray-800 hover:bg-gray-700 active:bg-gray-900 text-gray-100 font-semibold text-xl px-4 py-2 rounded-md m-2")
|
||||
pure (recipient, readMaybe . T.unpack <$> _inputElement_value ie)
|
||||
elClass "div" "flex" $ do
|
||||
signedTxE <-
|
||||
performEvent . fmap liftIO $
|
||||
makeTx hydraProcessHandlesRef name
|
||||
<$> current currentSet
|
||||
-- NOTE/TODO(skylar): This is just to default to the minimum
|
||||
<*> current (fromMaybe 1000000 <$> lovelaceDyn)
|
||||
<*> current recipientDyn
|
||||
<@ doSend
|
||||
tellAction
|
||||
. fmap NewTx
|
||||
$ signedTxE
|
||||
|
||||
doSend <- elClass "div" "flex flex-row ml-2" $ do
|
||||
sendButtonClick <- flip ifUTXOsDyn (pure never) $ do
|
||||
buttonClass "bg-green-500 hover:bg-green-400 active:bg-green-200 text-white font-bold text-xl mr-2 px-4 py-2 rounded-md" $ text "Send"
|
||||
tellAction
|
||||
. (Close <$)
|
||||
<=< buttonClass "bg-red-500 hover:bg-red-400 active:bg-red-200 text-white font-bold text-xl px-4 py-2 rounded-md"
|
||||
$ text "Close Head"
|
||||
switchHold never sendButtonClick
|
||||
pure ()
|
||||
pure ()
|
||||
|
||||
closedScreen ::
|
||||
( MonadFix m,
|
||||
MonadIO m,
|
||||
MonadIO (Performable m),
|
||||
DomBuilder t m,
|
||||
PostBuild t m,
|
||||
TriggerEvent t m,
|
||||
PerformEvent t m,
|
||||
MonadHold t m
|
||||
) =>
|
||||
UTCTime ->
|
||||
m ()
|
||||
closedScreen fanoutTime = do
|
||||
countDownDyn <- clockLossy 1 fanoutTime
|
||||
elClass "div" "text-white text-2xl my-4 ml-2" $ do
|
||||
text "Fanout time left: "
|
||||
dyn_
|
||||
( text . T.pack . show @Integer
|
||||
. ceiling
|
||||
. diffUTCTime fanoutTime
|
||||
. _tickInfo_lastUTC
|
||||
<$> countDownDyn
|
||||
)
|
||||
text " seconds"
|
14
src/Paths.hs
Normal file
14
src/Paths.hs
Normal file
@ -0,0 +1,14 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
module Paths where
|
||||
|
||||
import System.Which (staticWhich)
|
||||
|
||||
hydraToolsPath :: FilePath
|
||||
hydraToolsPath = $(staticWhich "hydra-tools")
|
||||
|
||||
realpathPath :: FilePath
|
||||
realpathPath = $(staticWhich "realpath")
|
||||
|
||||
dirnamePath :: FilePath
|
||||
dirnamePath = $(staticWhich "dirname")
|
||||
|
Loading…
Reference in New Issue
Block a user