Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

add initial version of genesis conversion tool #195

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions genesis-tool/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
let
genesisSpecDefault = {
activeSlotsCoeff = .05;
protocolParams = {
poolDeposit = 500000000;
protocolVersion = {
minor = 0;
major = 0;
};
minUTxOValue = 0;
decentralisationParam = 1;
maxTxSize = 16384;
minPoolCost = 0;
minFeeA = 44;
maxBlockBodySize = 65536;
minFeeB = 155381;
eMax = 18;
extraEntropy = {
tag = "NeutralNonce";
};
maxBlockHeaderSize = 1100;
keyDeposit = 400000;
nOpt = 50;
rho = 1.78650067e-3;
tau = 0.1;
a0 = 0.1;
};
protocolMagicId = 42;
genDelegs = {};
updateQuorum = 3;
networkId = "Testnet";
initialFunds = {};
maxLovelaceSupply = 45000000000000000;
networkMagic = 42;
epochLength = 21600;
staking = {
pools = {};
stake = {};
};
systemStart = "1970-01-01T00 =00 =00Z";
slotsPerKESPeriod = 3600;
slotLength = 1;
maxKESEvolutions = 120;
securityParam = 108;
};
in { inputParams ? {} }:

let
pkgs = import ../nix { };
inherit (pkgs) lib;

inputConfig = __toFile "input.json" (__toJSON (inputParams.utxoSnapshot));
genesisSpec = __toFile "genesis-spec.json" (__toJSON (genesisSpecDefault // inputParams.genesisOverrides));
in lib.fix (self: {
inherit inputParams inputConfig genesisSpec;
ghc = pkgs.haskellPackages.ghcWithPackages (ps: [ ps.aeson ps.base58-bytestring ps.base16-bytestring ]);
utxo-converter = pkgs.runCommand "utxo-converter" {
buildInputs = [ self.ghc pkgs.haskellPackages.ghcid ];
preferLocalBuild = true;
} ''
cp ${./main.hs} main.hs
mkdir -pv $out/bin/
ghc ./main.hs -o $out/bin/utxo-converter
'';

genesisInitialFunds = let
buildInputs = [ self.utxo-converter pkgs.cardano-cli pkgs.cardano-node ];
in pkgs.runCommand "genesis-initial-funds" { inherit buildInputs; } ''
utxo-converter ${inputConfig}
mkdir -p $out
cp output.json $out/utxo.json
'';
genesisCreator = let
buildInputs = with pkgs; [ jq cardano-cli ];
in pkgs.runCommand "genesis-initial-funds" { inherit buildInputs; } ''
mkdir -p $out
cp ${self.genesisInitialFunds}/utxo.json .
cp ${self.genesisSpec} genesis-spec.json
cardano-cli shelley genesis create --genesis-dir . --gen-genesis-keys 1 --mainnet
jq --argjson initialFunds "$(<utxo.json)" '.initialFunds = $initialFunds' genesis.json > $out/genesis.json

'';

tester = pkgs.writeShellScript "tester" ''
set -e
export PATH=${lib.makeBinPath (with pkgs; [ jq cardano-cli cardano-node ])}:$PATH
rm -f /tmp/testrun/*
mkdir -p /tmp/testrun
cd /tmp/testrun
cp ${self.genesisInitialFunds}/utxo.json ./
# TODO: launch node with genesis
cp ${self.genesisSpec} genesis-spec.json
cardano-cli shelley genesis --genesis-dir . create --genesis-keys 1
'';
})
36 changes: 36 additions & 0 deletions genesis-tool/generate-sample.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# example usage: nix-build generate-incentivized.nix -A tester
let
ada = n: n * 1000000; # lovelace
mada = n: n * 1000000 * 1000000; # million ada in lovelace
stakePoolCount = 0;
stakePoolBalances = [];
readFile = file: (__replaceStrings ["\n"] [""] (__readFile file));
extraBlockchainConfig = {
slots_per_epoch = 43200;
};

inputParams =
let
genesisOverrides = {
protocolParamaters = {
decentralisationParameter = 1;
poolDeposit = 1000000000000000;
nOpt = 1;
rho = 0;
tau = 0;
a0 = 0;
};
maxLovelaceSupply = 45000000000000000;
protocolMagicId = 764824073;
};
initialUtxoSnapshot = (__fromJSON (__readFile ./sample-utxo.json)).fund;
utxoSnapshot = {
fund = initialUtxoSnapshot ++ [
# additional addresses go here
#{ address = ""; value = mada 1; }
];
};
in {
inherit utxoSnapshot genesisOverrides;
};
in import ./. { inherit inputParams; }
72 changes: 72 additions & 0 deletions genesis-tool/main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}

module Main where

import Data.Aeson
import qualified Data.ByteString as BS
import qualified Data.Map as Map
import Data.Map (Map)
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import Data.ByteString (ByteString)
import qualified Data.ByteString.Base58 as B58
import qualified Data.ByteString.Base16 as B16
import Data.Maybe
import Data.Text.Encoding
import GHC.Generics
import System.Environment
import Data.Hashable
import Data.Text (Text)

data Input = Input
{ inputFunds :: [InputFund]
} deriving (Show, Generic)

instance FromJSON Input where
parseJSON = withObject "Input" $ \v -> Input <$> v .: "fund"

data InputFund = InputFund
{ inputFundAddress :: Base58Address
, inputFundValue :: Integer
} deriving (Show, Generic)

instance FromJSON InputFund where
parseJSON = withObject "InputFund" $ \v -> InputFund <$> v .: "address" <*> v .: "value"

newtype Base58Address = Base58Address ByteString deriving (Show, Generic)
newtype HexAddress = HexAddress ByteString deriving (Show, Ord, Eq)

instance Hashable HexAddress where
hashWithSalt a (HexAddress bs) = hashWithSalt a bs

instance FromJSON Base58Address where
parseJSON = withText "Base58Address" $ \s -> (Base58Address . fromJust . (B58.decodeBase58 B58.bitcoinAlphabet) . encodeUtf8) <$> (pure s)

data Output = Output
{ initialFunds :: HashMap HexAddress Integer
} deriving Show

encodeKey :: (HexAddress, Integer) -> (Text, Value)
encodeKey (HexAddress key, value) = (decodeUtf8 $ B16.encode key, toJSON value)

instance ToJSON Output where
toJSON (Output funds) = Object $ HashMap.fromList $ map encodeKey $ HashMap.toList funds

main :: IO ()
main = do
args <- getArgs
let
go :: [String] -> IO (Either String Input)
go [path] = eitherDecodeFileStrict path
convertFund :: InputFund -> (HexAddress, Integer)
convertFund (InputFund (Base58Address addr) value) = (HexAddress $ B16.encode addr, value)
go2 (Left err) = do
print err
go2 (Right (Input funds)) = do
let
output = Output $ HashMap.fromList $ map convertFund funds
encodeFile "output.json" output
print "done"
result1 <- go args
go2 result1
1 change: 1 addition & 0 deletions genesis-tool/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"3832643831383538356138333538316332316365313832366566656533636266353735393630303939353035323834303835623633643163353031666232623634646533623631396131303135383336353833343230323032303230306130613230346236353635373032303735373032303734363836353230363736663666363432303737366637323662323034393631366237353230343236663736363936333638323132303636373236663664323034383464323030613061303031616236633636373562":1000000000000}
8 changes: 8 additions & 0 deletions genesis-tool/sample-utxo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"fund": [
{
"address": "65wSXtwuTM3MatmQoKPfMzwitRdxBFxbnVzrVPXyhQK7P1hCitxiWTvkZE5LXVj2B5uTrLwUdCWU65s7UXeote3g3TeAwJTF3RXgq8R5sz4Ga6d9c2m2DvdC9kGgxt7jf8qxBtZQn",
"value": 1000000000000
}
]
}