diff --git a/dockerfiles/stages/3-builder b/dockerfiles/stages/3-builder index 5229281ba86..cd7cff22f6c 100644 --- a/dockerfiles/stages/3-builder +++ b/dockerfiles/stages/3-builder @@ -55,7 +55,6 @@ RUN eval $(opam config env) \ src/app/generate_keypair/generate_keypair.exe \ src/app/validate_keypair/validate_keypair.exe \ src/app/rosetta/ocaml-signer/signer.exe \ - src/app/rosetta/test-agent/agent.exe \ && cp _build/default/src/app/archive_blocks/archive_blocks.exe $HOME/app/mina-archive-blocks \ && cp _build/default/src/app/extract_blocks/extract_blocks.exe $HOME/app/mina-extract-blocks \ && cp _build/default/src/app/missing_blocks_auditor/missing_blocks_auditor.exe $HOME/app/mina-missing-blocks-auditor \ @@ -68,7 +67,6 @@ RUN eval $(opam config env) \ && mv _build/default/src/app/generate_keypair/generate_keypair.exe $HOME/app/mina-generate-keypair \ && mv _build/default/src/app/validate_keypair/validate_keypair.exe $HOME/app/mina-validate-keypair \ && mv _build/default/src/app/rosetta/ocaml-signer/signer.exe $HOME/app/mina-ocaml-signer \ - && mv _build/default/src/app/rosetta/test-agent/agent.exe $HOME/app/mina-rosetta-test-agent \ && rm -rf _build # Clear go module caches diff --git a/dockerfiles/stages/4-deb-builder b/dockerfiles/stages/4-deb-builder index a0087d777c4..bef01139591 100644 --- a/dockerfiles/stages/4-deb-builder +++ b/dockerfiles/stages/4-deb-builder @@ -44,7 +44,6 @@ RUN echo "--- Build all major tagets required for packaging" \ src/app/rosetta/rosetta.exe \ src/app/rosetta/rosetta_mainnet_signatures.exe \ src/app/rosetta/rosetta_testnet_signatures.exe \ - src/app/rosetta/test-agent/agent.exe \ src/app/rosetta/ocaml-signer/signer.exe # --- MAKE DEB diff --git a/graphql_schema.json b/graphql_schema.json index cb8e1ce9315..deaff03aada 100644 --- a/graphql_schema.json +++ b/graphql_schema.json @@ -614,152 +614,6 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "INPUT_OBJECT", - "name": "SetStakingInput", - "description": null, - "fields": [ - { - "name": "publicKeys", - "description": - "Public keys of accounts you wish to stake with - these must be accounts that are in trackedAccounts", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "PublicKey", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": [ - { - "name": "publicKeys", - "description": - "Public keys of accounts you wish to stake with - these must be accounts that are in trackedAccounts", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "PublicKey", - "ofType": null - } - } - } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SetStakingPayload", - "description": null, - "fields": [ - { - "name": "lastStaking", - "description": - "Returns the public keys that were staking funds previously", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "PublicKey", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lockedPublicKeys", - "description": - "List of public keys that could not be used to stake because they were locked", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "PublicKey", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "currentStakingKeys", - "description": - "Returns the public keys that are now staking their funds", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "PublicKey", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, { "kind": "OBJECT", "name": "TarFile", @@ -2735,38 +2589,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "setStaking", - "description": "Set keys you wish to stake with", - "args": [ - { - "name": "input", - "description": null, - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "SetStakingInput", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "SetStakingPayload", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": - "Restart the daemon with the flag --block-producer-key instead" - }, { "name": "setCoinbaseReceiver", "description": "Set the key to receive coinbases", diff --git a/scripts/build-and-test-rosetta-from-git.sh b/scripts/build-and-test-rosetta-from-git.sh deleted file mode 100755 index aec03dd1c21..00000000000 --- a/scripts/build-and-test-rosetta-from-git.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -GITBRANCH=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD) -TAG=$(echo ${GITBRANCH} | sed 's!/!-!; s!_!-!g') - -docker pull gcr.io/o1labs-192920/mina-rosetta-opam-deps:${TAG} - -cat dockerfiles/Dockerfile-rosetta | docker build \ - --target production \ - --force-rm \ - --cache-from gcr.io/o1labs-192920/mina-rosetta-opam-deps:${TAG} \ - -t gcr.io/o1labs-192920/mina-rosetta:${TAG} \ - --build-arg "DUNE_PROFILE=dev" \ - --build-arg "OPAM_BRANCH=${GITBRANCH}" \ - --build-arg "MINA_BRANCH=${GITBRANCH}" - - - -docker run -it --entrypoint=./docker-test-start.sh gcr.io/o1labs-192920/mina-rosetta:${TAG} - -[[ $? -eq 0 ]] && docker push gcr.io/o1labs-192920/mina-rosetta:${TAG} || echo "Tests failed, not pushing" diff --git a/src/app/cli/src/cli_entrypoint/mina_cli_entrypoint.ml b/src/app/cli/src/cli_entrypoint/mina_cli_entrypoint.ml index da4bc6d0c8d..81b377e9d16 100644 --- a/src/app/cli/src/cli_entrypoint/mina_cli_entrypoint.ml +++ b/src/app/cli/src/cli_entrypoint/mina_cli_entrypoint.ml @@ -978,8 +978,11 @@ let setup_daemon logger = Precomputed_values.genesis_ledger precomputed_values |> Lazy.force |> Ledger.merkle_root in - let initial_block_production_keypairs = - block_production_keypair |> Option.to_list |> Keypair.Set.of_list + let block_production_keypairs = + block_production_keypair + |> Option.map ~f:(fun kp -> + (kp, Public_key.compress kp.Keypair.public_key)) + |> Option.to_list |> Keypair.And_compressed_pk.Set.of_list in let epoch_ledger_location = conf_dir ^/ "epoch_ledger" in let consensus_local_state = @@ -1202,7 +1205,7 @@ Pass one of -peer, -peer-list-file, -seed, -peer-list-url.|} ; ~persistent_root_location:(conf_dir ^/ "root") ~persistent_frontier_location:(conf_dir ^/ "frontier") ~epoch_ledger_location ~snark_work_fee:snark_work_fee_flag - ~time_controller ~initial_block_production_keypairs ~monitor + ~time_controller ~block_production_keypairs ~monitor ~consensus_local_state ~is_archive_rocksdb ~work_reassignment_wait ~archive_process_location ~log_block_creation ~precomputed_values ~start_time ?precomputed_blocks_path ~log_precomputed_blocks diff --git a/src/app/cli/src/init/client.ml b/src/app/cli/src/init/client.ml index 78342a765e3..776e193f220 100644 --- a/src/app/cli/src/init/client.ml +++ b/src/app/cli/src/init/client.ml @@ -1241,43 +1241,6 @@ let stop_tracing = | Error e -> Daemon_rpcs.Client.print_rpc_error e)) -let set_staking_graphql = - let open Command.Param in - let open Cli_lib.Arg_type in - let open Graphql_lib in - let pk_flag = - flag "--public-key" ~aliases:[ "public-key" ] - ~doc:"PUBLICKEY Public key of account with which to produce blocks" - (required public_key_compressed) - in - Command.async - ~summary: - "The set-staking command is deprecated and no longer has any effect.To \ - enable block production, instead restart the daemon with the flag \ - --block-producer-key" - (Cli_lib.Background_daemon.graphql_init pk_flag - ~f:(fun graphql_endpoint public_key -> - let print_message msg arr = - if not (Array.is_empty arr) then - printf "%s: %s\n" msg - (String.concat_array ~sep:", " - (Array.map ~f:Public_key.Compressed.to_base58_check arr)) - in - let%map result = - Graphql_client.query_exn - (Graphql_queries.Set_staking.make - ~public_key:(Encoders.public_key public_key) - ()) - graphql_endpoint - in - print_message "Stopped staking with" result#setStaking#lastStaking ; - print_message - "❌ Failed to start staking with keys (try `mina accounts unlock` \ - first)" - result#setStaking#lockedPublicKeys ; - print_message "Started staking with" - result#setStaking#currentStakingKeys)) - let set_coinbase_receiver_graphql = let open Command.Param in let open Cli_lib.Arg_type in @@ -2415,7 +2378,6 @@ let client = ; ("create-token-account", create_new_account_graphql) ; ("mint-tokens", mint_tokens_graphql) ; ("cancel-transaction", cancel_transaction_graphql) - ; ("set-staking", set_staking_graphql) ; ("set-snark-worker", set_snark_worker) ; ("set-snark-work-fee", set_snark_work_fee) ; ("export-logs", Export_logs.export_via_graphql) diff --git a/src/app/cli/src/init/coda_run.ml b/src/app/cli/src/init/coda_run.ml index 7df616daa99..f6336b10582 100644 --- a/src/app/cli/src/init/coda_run.ml +++ b/src/app/cli/src/init/coda_run.ml @@ -1,6 +1,5 @@ open Core open Async -open Signature_lib open O1trace module Graphql_cohttp_async = Graphql_internal.Make (Graphql_async.Schema) (Cohttp_async.Io) @@ -382,15 +381,6 @@ let setup_local_server ?(client_trustlist = []) ?rest_server_port return (Mina_lib.visualize_frontier ~filename coda)) ; implement Daemon_rpcs.Visualization.Registered_masks.rpc (fun () filename -> return (Mina_base.Ledger.Debug.visualize ~filename)) - ; implement Daemon_rpcs.Set_staking.rpc (fun () keypairs -> - let keypair_and_compressed_key = - List.map keypairs - ~f:(fun ({ Keypair.Stable.Latest.public_key; _ } as keypair) -> - (keypair, Public_key.compress public_key)) - in - Mina_lib.replace_block_production_keypairs coda - (Keypair.And_compressed_pk.Set.of_list keypair_and_compressed_key) ; - Deferred.unit) ; implement Daemon_rpcs.Add_trustlist.rpc (fun () cidr -> return (let cidr_str = Unix.Cidr.to_string cidr in diff --git a/src/app/cli/src/init/graphql_queries.ml b/src/app/cli/src/init/graphql_queries.ml index f47fc89e020..265bfea867c 100644 --- a/src/app/cli/src/init/graphql_queries.ml +++ b/src/app/cli/src/init/graphql_queries.ml @@ -116,18 +116,6 @@ query pendingSnarkWork { } |}] -module Set_staking = -[%graphql -{| -mutation ($public_key: PublicKey) { - setStaking(input : {publicKeys: [$public_key]}) { - lastStaking @bsDecoder(fn: "Decoders.public_key_array") - lockedPublicKeys @bsDecoder(fn: "Decoders.public_key_array") - currentStakingKeys @bsDecoder(fn: "Decoders.public_key_array") - } - } -|}] - module Set_coinbase_receiver = [%graphql {| diff --git a/src/app/cli/src/tests/coda_worker.ml b/src/app/cli/src/tests/coda_worker.ml index a86ecb16cd6..d819426a8ae 100644 --- a/src/app/cli/src/tests/coda_worker.ml +++ b/src/app/cli/src/tests/coda_worker.ml @@ -389,19 +389,19 @@ module T = struct List.nth_exn (Lazy.force Genesis_ledger.accounts) i |> Genesis_ledger.keypair_of_account_record_exn) in - let initial_block_production_keypairs = - Keypair.Set.of_list (block_production_keypair |> Option.to_list) + let block_production_keypairs = + block_production_keypair + |> Option.map ~f:(fun kp -> + (kp, Public_key.compress kp.Keypair.public_key)) + |> Option.to_list |> Keypair.And_compressed_pk.Set.of_list in - let initial_block_production_keys = - Public_key.Compressed.Set.of_list - ( Option.map block_production_keypair ~f:(fun keypair -> - let open Keypair in - Public_key.compress keypair.public_key) - |> Option.to_list ) + let block_production_pubkeys = + block_production_keypairs |> Keypair.And_compressed_pk.Set.to_list + |> List.map ~f:snd |> Public_key.Compressed.Set.of_list in let epoch_ledger_location = conf_dir ^/ "epoch_ledger" in let consensus_local_state = - Consensus.Data.Local_state.create initial_block_production_keys + Consensus.Data.Local_state.create block_production_pubkeys ~genesis_ledger:Genesis_ledger.t ~genesis_epoch_data:precomputed_values.genesis_epoch_data ~epoch_ledger_location @@ -482,10 +482,9 @@ module T = struct ~epoch_ledger_location ~wallets_disk_location:(conf_dir ^/ "wallets") ~time_controller ~snark_work_fee:(Currency.Fee.of_int 0) - ~initial_block_production_keypairs ~monitor - ~consensus_local_state ~is_archive_rocksdb - ~work_reassignment_wait:420000 ~precomputed_values ~start_time - ~upload_blocks_to_gcloud:false + ~block_production_keypairs ~monitor ~consensus_local_state + ~is_archive_rocksdb ~work_reassignment_wait:420000 + ~precomputed_values ~start_time ~upload_blocks_to_gcloud:false ~archive_process_location: (Option.map archive_process_location ~f:(fun host_and_port -> Cli_lib.Flag.Types. diff --git a/src/app/cli/src/tests/full_test.ml b/src/app/cli/src/tests/full_test.ml index 7f8e08e693f..e5bca189469 100644 --- a/src/app/cli/src/tests/full_test.ml +++ b/src/app/cli/src/tests/full_test.ml @@ -196,7 +196,9 @@ let run_test () : unit Deferred.t = ~proposed_protocol_version_opt:None ~super_catchup:true ~work_selection_method: (module Work_selector.Selection_methods.Sequence) - ~initial_block_production_keypairs:(Keypair.Set.singleton keypair) + ~block_production_keypairs: + (Keypair.And_compressed_pk.Set.singleton + (keypair, Public_key.compress keypair.public_key)) ~snark_worker_config: Mina_lib.Config.Snark_worker_config. { initial_snark_worker_key = diff --git a/src/app/rosetta/README.md b/src/app/rosetta/README.md index c3c7d5c5fff..86593d7724e 100644 --- a/src/app/rosetta/README.md +++ b/src/app/rosetta/README.md @@ -4,6 +4,13 @@ Implementation of the [Rosetta API](https://www.rosetta-api.org/) for Mina. ## Changelog +2022/02/03: + +- Removed the current test-agent, in part because it relies + on the ability to enable and disable staking via GrapQL. + That feature of the daemon had been deprecated, and has been + removed. A new test-agent may appear in the future. + 2022/01/18: - /network/list uses `MINA_ROSETTA_NETWORK` @@ -171,7 +178,6 @@ This creates an image (mina-rosetta:vX) based on the most up-to-date changes tha The container includes 4 scripts in /rosetta which run a different set of services connected to a particular network - `docker-standalone-start.sh` is the most straightforward, it starts only the mina-rosetta API endpoint and any flags passed into the script go to mina-rosetta. Use this for the "offline" part of the Construction API. - `docker-demo-start.sh` launches a mina node with a very simple 1-address genesis ledger as a sandbox for developing and playing around in. This script starts the full suite of tools (a mina node, mina-archive, a postgresql DB, and mina-rosetta), but for a demo network with all operations occuring inside this container and no external network activity. -- `docker-test-start.sh` launches the same demo network as in demo-start.sh but also launches the mina-rosetta-test-agent to run a suite of tests against the rosetta API. - The default, `docker-start.sh`, which connects the mina node to our [Mainnet](https://docs.minaprotocol.com/en/using-mina/connecting) network and initializes the archive database from publicly-availible nightly O(1) Labs backups. As with `docker-demo-start.sh`, this script runs a mina node, mina-archive, a postgresql DB, and mina-rosetta. The script also periodically checks for blocks that may be missing between the nightly backup and the tip of the chain and will fill in those gaps by walking back the linked list of blocks in the canonical chain and importing them one at a time. Take a look at the [source](https://github.com/MinaProtocol/mina/blob/rosetta-v16/src/app/rosetta/docker-start.sh) for more information about what you can configure and how. - Finally, the previous default, `docker-devnet-start.sh`, which connects the mina node to our [Devnet](https://docs.minaprotocol.com/en/advanced/connecting-devnet) network with the archive database initalized in a similar way to docker-start.sh. As with `docker-demo-start.sh`, this script runs a mina node, mina-archive, a postgresql DB, and mina-rosetta. `docker-devnet-start.sh` is now just a special case of `docker-start.sh` so inspect the source there for more detailed configuration. @@ -227,7 +233,7 @@ Accounts in Mina are not uniquely identified by an address alone, you must also ### Operations for Supported Transactions via Construction -The following supported transactions on devnet and mainnet for the Construction API are the `payment` and `delegation` ones within the ["living" documentation](https://github.com/MinaProtocol/mina/blob/477bbdcdeeeafbcbaff74b9b1a83feacf104e5c9/src/app/rosetta/test-agent/poke.ml#L89) in our integration testing code. The other transaction types are disabled on the live networks. +The following supported transactions on devnet and mainnet for the Construction API are `payment` and `delegation`. The other transaction types are disabled on the live networks. ## Future Work and Known Issues @@ -270,23 +276,15 @@ The signer library used by the test agent can be used as a reference for further ### Rosetta CLI Validation -The Data API is fully validated using the official `rosetta-cli` against private networks that issue every different type of transaction (running the test-agent suite while `check:data` is run). There are no reconcilliation errors. We are in the middle of verifying reconcilliation errors against devnet. +The Data API is fully validated using the official `rosetta-cli` against private networks that issue every different type of transaction. There are no reconcilliation errors. We are in the middle of verifying reconcilliation errors against devnet. -The Construction API is _not_ validated using `rosetta-cli` as this would require an implementation of the signer in the rosetta-go-sdk. The test-agent does a thorough job of testing the construction API, however, see the integration-test-agent section above. +The Construction API is _not_ validated using `rosetta-cli` as this would require an implementation of the signer in the rosetta-go-sdk. ### Reproduce agent and rosetta-cli validation `minaprotocol/mina-rosetta:v16` and `rosetta-cli @ v0.5.12` using this [`rosetta.conf`](https://github.com/MinaProtocol/mina/blob/2b43c8cccfb9eb480122d207c5a3e6e58c4bbba3/src/app/rosetta/rosetta.conf) and the [`bootstrap_balances.json`](https://github.com/MinaProtocol/mina/blob/2b43c8cccfb9eb480122d207c5a3e6e58c4bbba3/src/app/rosetta/bootstrap_balances.json) next to it. -**Create one of each transaction type using the test-agent and exit** - -``` -$ docker run --rm --publish 3087:3087 --publish 3086:3086 --publish 3085:3085 --name mina-rosetta-test --entrypoint ./docker-test-start.sh -d minaprotocol/mina-rosetta:v16 - -$ docker logs --follow mina-rosetta-test -``` - **Run a fast sandbox network forever and test with rosetta-cli** ``` diff --git a/src/app/rosetta/docker-test-start.sh b/src/app/rosetta/docker-test-start.sh deleted file mode 100755 index 94cf8d3befe..00000000000 --- a/src/app/rosetta/docker-test-start.sh +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/bash - -set -eou pipefail - -POSTGRES_VERSION=$(psql -V | cut -d " " -f 3 | sed 's/.[[:digit:]]*$//g') - -function cleanup -{ - CODE=${1:-0} - echo "========================= TEST COMPLETE: exited with code $CODE =========================" - echo "========================= CLEANING UP ===========================" - echo "Killing archive node" - pkill 'mina-archive' || true - echo "Killing mina daemon" - pkill 'mina' || true - echo "Killing rosetta api" - pkill 'mina-rosetta' || true - echo "Killing rosetta test agent" - pkill 'mina-rosetta-test-agent' || true - echo "Stopping postgres cluster" - pg_ctlcluster ${POSTGRES_VERSION} main stop - exit $CODE -} - -trap cleanup TERM -trap cleanup INT -trap cleanup EXIT - - -# Allows configuring the port that each service runs on. -# This script does not connect to a network, so MINA_DAEMON_PORT can be kept private. -# To interact with rosetta, use MINA_ROSETTA_PORT. -MINA_DAEMON_PORT=${MINA_DAEMON_PORT:=8301} -MINA_ROSETTA_PORT=${MINA_ROSETTA_PORT:=3087} -MINA_ARCHIVE_PORT=${MINA_ARCHIVE_PORT:=3086} -MINA_GRAPHQL_PORT=${MINA_GRAPHQL_PORT:=3085} -LOG_LEVEL=${LOG_LEVEL:=Debug} -PG_CONN=postgres://pguser:pguser@localhost:5432/archive - - -# ====== Set up demo environment ======== -export MINA_PRIVKEY_PASS=${MINA_PRIVKEY_PASS:-""} -export MINA_TIME_OFFSET=0 - - -# Demo keys and config file -echo "Running Mina demo..." -MINA_CONFIG_DIR=${MINA_CONFIG_DIR:-/root/.mina-config} -MINA_CONFIG_FILE="${MINA_CONFIG_DIR}/daemon.json}" - -export PK=${PK:-"B62qiZfzW27eavtPrnF6DeDSAKEjXuGFdkouC3T5STRa6rrYLiDUP2p"} -SNARK_PK=${SNARK_PK:-"B62qjnkjj3zDxhEfxbn1qZhUawVeLsUr2GCzEz8m1MDztiBouNsiMUL"} - -CONFIG_TEMPLATE=${CONFIG_TEMPLATE:-/genesis_ledgers/daemon.json.template} - -set +u -if [ -z "$GENESIS_STATE_TIMESTAMP" ]; then - export GENESIS_STATE_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") -fi -set -u -echo "Genesis State Timestamp for this run is: ${GENESIS_STATE_TIMESTAMP}" - -echo "Rewriting config file from template ${CONFIG_TEMPLATE} to ${MINA_CONFIG_FILE}" -envsubst < ${CONFIG_TEMPLATE} > ${MINA_CONFIG_FILE} - -# Start postgres -echo "========================= STARTING POSTGRESQL ===========================" -pg_ctlcluster ${POSTGRES_VERSION} main start - -# wait for it to settle -sleep 3 - -# rosetta -echo "========================= STARTING ROSETTA API on PORT ${MINA_ROSETTA_PORT} ===========================" -mina-rosetta \ - --archive-uri $PG_CONN \ - --graphql-uri "http://127.0.0.1:${MINA_GRAPHQL_PORT}/graphql" \ - --log-level "${LOG_LEVEL}" \ - --port "${MINA_ROSETTA_PORT}" & - -# wait for it to settle -sleep 3 - -# archive -echo "========================= STARTING ARCHIVE PROCESS ===========================" -mina-archive run \ - --postgres-uri $PG_CONN \ - --server-port "${MINA_ARCHIVE_PORT}" \ - --log-level "${LOG_LEVEL}" \ - --log-json & - -# wait for it to settle -sleep 6 - -# MINA_CONFIG_DIR is exposed by the dockerfile and contains demo mode essentials -echo "========================= STARTING DAEMON ===========================" -echo "Contents of config file ${MINA_CONFIG_FILE}:" -cat "${MINA_CONFIG_FILE}" -export MINA_LIBP2P_HELPER_PATH=/usr/local/bin/libp2p_helper -mina daemon \ - --block-producer-pubkey "${PK}" \ - --run-snark-worker "${SNARK_PK}" \ - --config-dir "${MINA_CONFIG_DIR}" \ - --config-file "${MINA_CONFIG_FILE}" \ - --seed \ - --demo-mode \ - --proof-level none \ - --disable-node-status \ - --background \ - --external-ip 127.0.0.1 \ - --external-port "${MINA_DAEMON_PORT}" \ - --archive-address "127.0.0.1:${MINA_ARCHIVE_PORT}" \ - --rest-port "${MINA_GRAPHQL_PORT}" \ - --insecure-rest-server \ - --log-level "${LOG_LEVEL}" \ - --log-json \ - $@ - -# wait for it to settle -sleep 6 - -# test agent -mina-rosetta-test-agent \ - -graphql-uri "http://127.0.0.1:${MINA_GRAPHQL_PORT}/graphql" \ - -rosetta-uri "http://127.0.0.1:${MINA_ROSETTA_PORT}/" \ - -log-level Trace \ - -log-json & - -# wait for test agent to exit (asynchronously) -AGENT_PID=$! -while $(kill -0 $AGENT_PID 2> /dev/null); do - sleep 2 -done -set +e -wait $AGENT_PID -AGENT_STATUS=$? -set -e -echo "Test finished with code $AGENT_STATUS" - -# then cleanup and forward the status -cleanup $AGENT_STATUS - diff --git a/src/app/rosetta/start.sh b/src/app/rosetta/start.sh deleted file mode 100755 index 3c32ae72c35..00000000000 --- a/src/app/rosetta/start.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash - -set -eou pipefail - -function cleanup -{ - CODE=${1:-0} - echo "Killing archive.exe" - kill $(ps aux | egrep '_build/default/src/app/.*archive.exe' | grep -v grep | awk '{ print $2 }') || true - echo "Killing mina.exe" - kill $(ps aux | egrep '_build/default/src/app/.*mina.exe' | grep -v grep | awk '{ print $2 }') || true - echo "Killing agent.exe" - kill $(ps aux | egrep '_build/default/src/app/rosetta/test-agent/agent.exe' | grep -v grep | awk '{ print $2 }') || true - echo "Killing rosetta.exe" - kill $(ps aux | egrep '_build/default/src/app/rosetta' | grep -v grep | awk '{ print $2 }') || true - exit $CODE -} - -trap cleanup TERM -trap cleanup INT - -PG_CONN=postgres://$USER:$USER@localhost:5432/archiver - -# rebuild -pushd ../../../ -PATH=/usr/local/bin:$PATH dune b src/app/runtime_genesis_ledger/runtime_genesis_ledger.exe src/app/cli/src/mina.exe src/app/archive/archive.exe src/app/rosetta/rosetta.exe src/app/rosetta/test-agent/agent.exe src/app/rosetta/ocaml-signer/signer.exe -popd - -# make genesis (synchronously) -./make-runtime-genesis.sh - -# drop tables and recreate -psql -d archiver < drop_tables.sql -psql -d archiver < create_schema.sql - -# archive -../../../_build/default/src/app/archive/archive.exe run \ - -postgres-uri $PG_CONN \ - -log-json \ - -config-file /tmp/config.json \ - -server-port 3086 & - -# wait for it to settle -sleep 3 - -# demo node -./run-demo.sh \ - -external-ip 127.0.0.1 \ - -archive-address 3086 \ - -log-json \ - -log-level debug & - -# wait for it to settle -sleep 60 - -# rosetta -../../../_build/default/src/app/rosetta/rosetta.exe \ - -archive-uri $PG_CONN \ - -graphql-uri http://localhost:3085/graphql \ - -log-level debug \ - -log-json \ - -port 3087 & - -# wait for it to settle -sleep 3 - -ARG=${1:-NONE} -if [[ "$ARG" == "CURL" ]]; then - echo "Running for curl mode, no agent present" - sleep infinity -else - if [[ "$ARG" == "FOREVER" ]]; then - echo "Running forever, not exiting agent afterwards" - EXTRA_FLAGS=" -dont-exit" - else - EXTRA_FLAGS="" - fi - - # test agent - ../../../_build/default/src/app/rosetta/test-agent/agent.exe \ - -graphql-uri http://localhost:3085/graphql \ - -rosetta-uri http://localhost:3087/ \ - -log-level Trace \ - -log-json $EXTRA_FLAGS & - - # wait for test agent to exit (asynchronously) - AGENT_PID=$! - while $(kill -0 $AGENT_PID 2> /dev/null); do - sleep 2 - done - set +e - wait $AGENT_PID - AGENT_STATUS=$? - set -e - echo "Test finished with code $AGENT_STATUS" - - # then cleanup and forward the status - cleanup $AGENT_STATUS -fi diff --git a/src/app/rosetta/test-agent/agent.ml b/src/app/rosetta/test-agent/agent.ml deleted file mode 100644 index 57d45e938f1..00000000000 --- a/src/app/rosetta/test-agent/agent.ml +++ /dev/null @@ -1,818 +0,0 @@ -(** An agent that pokes at Coda and peeks at Rosetta to see if things look alright *) - -open Core_kernel -open Async -open Rosetta_lib -open Lib - -(* Rosetta_models.Currency shadows our Currency so we "save" it as MinaCurrency first *) -module MinaCurrency = Currency -open Rosetta_models - -module Error = struct - include Error - - let equal e1 e2 = Yojson.Safe.equal (Error.to_yojson e1) (Error.to_yojson e2) -end - -let other_pk = "B62qoDWfBZUxKpaoQCoFqr12wkaY84FrhxXNXzgBkMUi2Tz4K8kBDiv" - -let snark_pk = "B62qjnkjj3zDxhEfxbn1qZhUawVeLsUr2GCzEz8m1MDztiBouNsiMUL" - -let timelocked_pk = "B62qpJDprqj1zjNLf4wSpFC6dqmLzyokMy6KtMLSvkU8wfdL1midEb4" - -let wait span = Async.after span |> Deferred.map ~f:Result.return - -(* Keep trying to run `step` `retry_count` many times initially waiting for `initial_delay` and each time waiting `each_delay` *) -let keep_trying ~step ~retry_count ~initial_delay ~each_delay ~failure_reason = - let open Deferred.Result.Let_syntax in - let rec go = function - | 0 -> - Deferred.Result.fail - (Errors.create ~context:failure_reason `Invariant_violation) - | i -> ( - match%bind step () with - | `Succeeded a -> - return a - | `Failed -> - let%bind () = wait each_delay in - go (i - 1) ) - in - let%bind () = wait initial_delay in - go retry_count - -let get_last_block_index ~rosetta_uri ~network_response ~logger = - let open Core.Time in - let open Deferred.Result.Let_syntax in - keep_trying - ~step:(fun () -> - let%map block_r = - Peek.Block.newest_block ~rosetta_uri ~network_response ~logger - in - match - Result.map block_r ~f:(fun block -> - (Option.value_exn block.Block_response.block).block_identifier - .index ) - with - | Error _ -> - `Failed - | Ok index -> - `Succeeded index ) - ~retry_count:20 ~initial_delay:(Span.of_sec 1.0) - ~each_delay:(Span.of_sec 1.0) - ~failure_reason:"Took too long for the last block to be fetched" - -let verify_in_mempool_and_block ~logger ~rosetta_uri ~graphql_uri - ~network_response ~txn_hash ~operation_expectations = - let open Core.Time in - let open Deferred.Result.Let_syntax in - let%bind () = wait (Span.of_sec 1.0) in - (* Grab the mempool and find the user command inside *) - let%bind () = - keep_trying - ~step:(fun () -> - let%map mempool_r = - Peek.Mempool.mempool ~rosetta_uri ~network_response ~logger - in - match - Result.map mempool_r ~f:(fun mempool -> - List.find mempool.Mempool_response.transaction_identifiers - ~f:(fun ident -> - String.equal ident.Transaction_identifier.hash txn_hash ) ) - with - | Error _ -> - `Failed - | Ok None -> - `Failed - | Ok (Some _) -> - `Succeeded () ) - ~retry_count:5 ~initial_delay:(Span.of_ms 100.0) - ~each_delay:(Span.of_sec 3.0) - ~failure_reason:"Took too long to appear in mempool" - in - (* Pull specific account out of mempool *) - let%bind mempool_res = - Peek.Mempool.transaction ~rosetta_uri ~network_response ~logger - ~hash:txn_hash - in - [%log debug] - ~metadata: - [ ( "operations" - , mempool_res.transaction.operations |> [%to_yojson: Operation.t list] - ) ] - "Mempool operations: $operations" ; - let%bind () = - Operation_expectation.assert_similar_operations ~logger - ~expected: - ( operation_expectations - |> List.filter ~f:(fun op -> - not - (String.equal op.Operation_expectation._type - "fee_receiver_inc") ) ) - ~actual:mempool_res.transaction.operations ~situation:"mempool" - in - [%log info] "Verified mempool operations" ; - let%bind last_block_index = - get_last_block_index ~rosetta_uri ~network_response ~logger - in - [%log debug] - ~metadata:[("index", `Intlit (Int64.to_string last_block_index))] - "Found block index $index" ; - (* Start staking so we get blocks *) - let%bind _res = Poke.Staking.enable ~graphql_uri in - (* Wait until the newest block has index > last_block_index and has at least one user command *) - let%bind block = - keep_trying - ~step:(fun () -> - let%map block_r = - Peek.Block.newest_block ~rosetta_uri ~network_response ~logger - in - match - Result.map block_r ~f:(fun block -> - let newer_block : bool = - Int64.( - (Option.value_exn block.Block_response.block) - .block_identifier - .index > last_block_index) - in - let has_user_command : bool = - (* HACK: First transaction is always an internal command and second, if present, is always a user - * command, so we can just check that length > 1 *) - Int.( - List.length - (Option.value_exn block.Block_response.block).transactions - > 1) - in - if newer_block && has_user_command then Some block else None ) - with - | Error _ -> - `Failed - | Ok None -> - `Failed - | Ok (Some block) -> - `Succeeded block ) - ~retry_count:20 ~initial_delay:(Span.of_sec 1.0) - ~each_delay:(Span.of_sec 2.0) - ~failure_reason:"Took too long for a block to be created" - in - [%log debug] - ~metadata: - [ ( "index" - , `Intlit - (Int64.to_string - (Option.value_exn block.Block_response.block).block_identifier - .index) ) ] - "Waited for the next block index $index" ; - (* Stop noisy block production *) - let%bind _res = Poke.Staking.disable ~graphql_uri in - let successful (x : Operation_expectation.t) = {x with status= "Success"} in - [%log debug] - ~metadata: - [ ( "transactions" - , [%to_yojson: Rosetta_models.Transaction.t list] - (Option.value_exn block.block).transactions ) ] - "Asserting that operations are similar in block. Transactions $transactions" ; - Operation_expectation.assert_similar_operations ~logger - ~expected: - ( List.map ~f:successful operation_expectations - @ Operation_expectation. - [ { amount= Some 40_000_000_000 - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Success" - ; _type= "coinbase_inc" - ; target= `Check None } ] ) - ~actual: - ( List.map (Option.value_exn block.block).transactions ~f:(fun txn -> - txn.operations ) - |> List.join ) - ~situation:"block" - -let direct_graphql_payment_through_block ~logger ~rosetta_uri ~graphql_uri - ~network_response = - let open Deferred.Result.Let_syntax in - (* Unlock the account *) - let%bind _ = Poke.Account.unlock ~graphql_uri in - (* Send a payment *) - let%bind hash = - Poke.SendTransaction.payment ~fee:(`Int 2_000_000_000) - ~amount:(`Int 5_000_000_000) ~to_:(`String other_pk) ~graphql_uri () - in - verify_in_mempool_and_block ~logger ~rosetta_uri ~graphql_uri ~txn_hash:hash - ~network_response - ~operation_expectations: - Operation_expectation. - [ { amount= Some (-5_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "payment_source_dec" - ; target= `Check None } - ; { amount= Some 5_000_000_000 - ; account= - Some {Account.pk= other_pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "payment_receiver_inc" - ; target= `Check None } - ; { amount= Some (-2_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "fee_payer_dec" - ; target= `Check None } - ; { amount= Some 2_000_000_000 - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "fee_receiver_inc" - ; target= `Check None } ] - -let direct_graphql_no_account_fee_through_block ~logger ~rosetta_uri - ~graphql_uri ~network_response = - let open Deferred.Result.Let_syntax in - (* Unlock the account *) - let%bind _ = Poke.Account.unlock ~graphql_uri in - let fresh_pk = "B62qokqG3ueJmkj7zXaycV31tnG6Bbg3E8tDS5vkukiFic57rgstTbb" in - (* Send a payment *) - let%bind hash = - Poke.SendTransaction.payment ~fee:(`Int 7_000_000_000) ~amount:(`Int 1_000) - ~to_:(`String fresh_pk) ~graphql_uri () - in - verify_in_mempool_and_block ~logger ~rosetta_uri ~graphql_uri ~txn_hash:hash - ~network_response - ~operation_expectations: - Operation_expectation. - [ { amount= Some (-7_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "fee_payment" - ; target= `Ignore } ] - -let direct_graphql_delegation_through_block ~logger ~rosetta_uri ~graphql_uri - ~network_response = - let open Deferred.Result.Let_syntax in - (* Unlock the account *) - let%bind _ = Poke.Account.unlock ~graphql_uri in - (* Delegate stake *) - let%bind hash = - Poke.SendTransaction.delegation ~fee:(`Int 2_000_000_000) - ~to_:(`String other_pk) ~graphql_uri () - in - verify_in_mempool_and_block ~logger ~rosetta_uri ~graphql_uri ~txn_hash:hash - ~network_response - ~operation_expectations: - Operation_expectation. - [ { amount= None - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "delegate_change" - ; target= `Check (Some other_pk) } - ; { amount= Some (-2_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "fee_payment" - ; target= `Check None } ] - -(* token creation disabled in daemon for now *) -(* -let direct_graphql_create_token_through_block ~logger ~rosetta_uri ~graphql_uri - ~network_response = - let open Deferred.Result.Let_syntax in - (* Unlock the sender account *) - let%bind _ = Poke.Account.unlock ~graphql_uri in - (* create token *) - let%bind hash = - Poke.SendTransaction.create_token ~fee:(`Int 2_000_000_000) - ~receiver:(`String other_pk) ~graphql_uri () - in - verify_in_mempool_and_block ~logger ~rosetta_uri ~graphql_uri ~txn_hash:hash - ~network_response - ~operation_expectations: - Operation_expectation. - [ { amount= Some (-2_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "fee_payment" - ; target= `Check None } - ; { amount= None - ; account= None - ; status= "Pending" - ; _type= "create_token" - ; target= `Check None } ] - -let direct_graphql_create_token_account_through_block ~logger ~rosetta_uri - ~graphql_uri ~network_response = - let open Deferred.Result.Let_syntax in - (* Unlock the account *) - let%bind _ = Poke.Account.unlock ~graphql_uri in - (* Create token account *) - let%bind hash = - Poke.SendTransaction.create_token_account ~fee:(`Int 2_000_000_000) - ~receiver:other_pk ~token:(`String "2") ~graphql_uri () - in - verify_in_mempool_and_block ~logger ~rosetta_uri ~graphql_uri ~txn_hash:hash - ~network_response - ~operation_expectations: - Operation_expectation. - [ { amount= Some (-2_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "fee_payment" - ; target= `Check None } ] -*) - -let construction_api_transaction_through_mempool ~logger ~rosetta_uri - ~graphql_uri ~network_response ~operation_expectations ~operations = - let open Deferred.Result.Let_syntax in - let keys = - Signer.Keys.of_private_key_box - {| {"box_primitive":"xsalsa20poly1305","pw_primitive":"argon2i","nonce":"8jGuTAxw3zxtWasVqcD1H6rEojHLS1yJmG3aHHd","pwsalt":"AiUCrMJ6243h3TBmZ2rqt3Voim1Y","pwdiff":[134217728,6],"ciphertext":"DbAy736GqEKWe9NQWT4yaejiZUo9dJ6rsK7cpS43APuEf5AH1Qw6xb1s35z8D2akyLJBrUr6m"} |} - in - let%bind derive_res = - Offline.Derive.req ~logger ~rosetta_uri ~network_response - ~public_key_hex_bytes:keys.public_key_hex_bytes - in - let operations = - operations (Option.value_exn derive_res.account_identifier) - in - let%bind preprocess_res = - Offline.Preprocess.req ~logger ~rosetta_uri ~network_response - ~max_fee:(Unsigned.UInt64.of_int 100_000_000_000) - ~operations - in - let%bind metadata_res = - Peek.Construction.metadata ~rosetta_uri ~network_response ~logger - ~options:preprocess_res.options - in - [%log debug] - ~metadata:[("res", Construction_metadata_response.to_yojson metadata_res)] - "Construction_metadata result $res" ; - let%bind payloads_res = - Offline.Payloads.req ~logger ~rosetta_uri ~network_response ~operations - ~metadata:metadata_res.metadata - in - let%bind payloads_parse_res = - Offline.Parse.req ~logger ~rosetta_uri ~network_response - ~transaction: - (`Unsigned - payloads_res.Construction_payloads_response.unsigned_transaction) - in - if not ([%equal: Operation.t list] operations payloads_parse_res.operations) - then ( - [%log debug] - ~metadata: - [ ("expected", [%to_yojson: Operation.t list] operations) - ; ( "actual" - , [%to_yojson: Operation.t list] payloads_parse_res.operations ) ] - "Construction_parse : Expected $expected, after payloads+parse $actual" ; - failwith "Operations are not equal before and after payloads+parse" ) ; - let%bind signature = - Signer.sign ~keys - ~unsigned_transaction_string:payloads_res.unsigned_transaction - |> Deferred.return - in - let%bind combine_res = - Offline.Combine.req ~logger ~rosetta_uri ~network_response ~signature - ~unsigned_transaction:payloads_res.unsigned_transaction - ~public_key_hex_bytes:keys.public_key_hex_bytes - ~account_id:(Option.value_exn derive_res.account_identifier) - in - let%bind combine_parse_res = - Offline.Parse.req ~logger ~rosetta_uri ~network_response - ~transaction: - (`Signed combine_res.Construction_combine_response.signed_transaction) - in - if not ([%equal: Operation.t list] operations combine_parse_res.operations) - then ( - [%log debug] - ~metadata: - [ ("expected", [%to_yojson: Operation.t list] operations) - ; ( "actual" - , [%to_yojson: Operation.t list] combine_parse_res.operations ) ] - "Construction_combine : Expected $expected, after combine+parse $actual" ; - failwith "Operations are not equal before and after combine+parse" ) ; - let%bind hash_res = - Offline.Hash.req ~logger ~rosetta_uri ~network_response - ~signed_transaction:combine_res.signed_transaction - in - let%bind verified_bool = - Signer.verify ~public_key_hex_bytes:keys.public_key_hex_bytes - ~signed_transaction_string:combine_res.signed_transaction - |> Deferred.return - in - let%bind () = - if verified_bool then return () - else - Deferred.Result.fail - (Errors.create ~context:"Bad signature created during construction" - `Invariant_violation) - in - let%bind submit_res = - Peek.Construction.submit ~logger ~rosetta_uri ~network_response - ~signed_transaction:combine_res.signed_transaction - in - assert ( - Transaction_identifier.equal hash_res.Transaction_identifier_response.transaction_identifier - submit_res.transaction_identifier ) ; - [%log debug] "Construction_submit is finalized" ; - verify_in_mempool_and_block ~logger ~rosetta_uri ~graphql_uri - ~txn_hash:hash_res.transaction_identifier.hash ~network_response - ~operation_expectations - -let construction_api_payment_through_mempool = - construction_api_transaction_through_mempool - ~operations:(fun account_id -> - Poke.SendTransaction.payment_operations ~from:account_id.address - ~fee:(Unsigned.UInt64.of_int 3_000_000_000) - ~amount:(Unsigned.UInt64.of_int 10_000_000_000) - ~to_:other_pk ) - ~operation_expectations: - Operation_expectation. - [ { amount= Some (-10_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "payment_source_dec" - ; target= `Check None } - ; { amount= Some 10_000_000_000 - ; account= - Some {Account.pk= other_pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "payment_receiver_inc" - ; target= `Check None } - ; { amount= Some (-3_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "fee_payment" - ; target= `Check None } ] - -let construction_api_delegation_through_mempool = - construction_api_transaction_through_mempool - ~operations:(fun account_id -> - Poke.SendTransaction.delegation_operations ~from:account_id.address - ~fee:(Unsigned.UInt64.of_int 5_000_000_000) - ~to_:other_pk ) - ~operation_expectations: - Operation_expectation. - [ { amount= None - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "delegate_change" - ; target= `Check (Some other_pk) } - ; { amount= Some (-5_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "fee_payment" - ; target= `Check None } ] - -(* token creation disabled in daemon for now *) -(* -let construction_api_create_token_through_mempool = - construction_api_transaction_through_mempool - ~operations:(fun account_id -> - Poke.SendTransaction.create_token_operations ~sender:account_id.address - ~fee:(Unsigned.UInt64.of_int 5_000_000_000) ) - ~operation_expectations: - Operation_expectation. - [ { amount= Some (-5_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "fee_payment" - ; target= `Check None } - ; { amount= None - ; account= None - ; status= "Pending" - ; _type= "create_token" - ; target= `Check None } ] - -let construction_api_create_token_account_through_mempool = - construction_api_transaction_through_mempool - ~operations:(fun account_id -> - Poke.SendTransaction.create_token_operations ~sender:account_id.address - ~fee:(Unsigned.UInt64.of_int 5_000_000_000) ) - ~operation_expectations: - Operation_expectation. - [ { amount= Some (-5_000_000_000) - ; account= - Some {Account.pk= Poke.pk; token_id= Unsigned.UInt64.of_int 1} - ; status= "Pending" - ; _type= "fee_payment" - ; target= `Check None } ] -*) - -let get_consensus_constants ~logger : - Consensus.Constants.t Or_error.t Deferred.t = - let open Deferred.Or_error.Let_syntax in - let conf_dir = "/tmp" in - let genesis_dir = - let home = Core.Sys.home_directory () in - Filename.concat home ".coda-config" - in - let config_file = - let mina_config_file = "MINA_CONFIG_FILE" in - let coda_config_file = "CODA_CONFIG_FILE" in - match Sys.getenv mina_config_file,Sys.getenv coda_config_file with - | Some config_file,_ -> - config_file - | None,Some config_file -> - [%log warn] "Using deprecated environment variable %s, please use %s instead" - coda_config_file mina_config_file; - config_file - | None,None -> - Filename.concat conf_dir "config.json" - in - let%bind config = - let%map config_json = Genesis_ledger_helper.load_config_json config_file in - match Runtime_config.of_yojson config_json with - | Ok config -> - config - | Error err -> - failwithf "Could not parse configuration: %s" err () - in - let%map proof, _ = - Genesis_ledger_helper.init_from_config_file ~genesis_dir ~logger - ~proof_level:None config - in - Precomputed_values.consensus_constants proof - -let historical_balance_check ~logger ~rosetta_uri ~network_response = - let open Core.Time in - let open Deferred.Result.Let_syntax in - let%bind consensus_constants = - Deferred.Result.map_error (get_consensus_constants ~logger) ~f:(fun _ -> - Errors.create ~context:"Failed to get consensus constants" - `Invariant_violation ) - in - let%bind last_block_index = - get_last_block_index ~rosetta_uri ~network_response ~logger - in - (* TODO(omerzach): We need to test for more complex accounts that involve - * internal and user commands too *) - let account_identifier = Account_identifier.create timelocked_pk in - let index_to_slot (index : int64) = - keep_trying - ~step:(fun () -> - let%map block_r = - Peek.Block.block_at_index ~index ~rosetta_uri ~network_response - ~logger - in - let block_r : (Block_response.t, Rosetta_models.Error.t) result = - block_r - in - match - Result.map block_r ~f:(fun block -> - let block = Option.value_exn block.Block_response.block in - let block_time : Block_time.t = - Block_time.of_int64 block.timestamp - in - let consensus_time : Consensus.Data.Consensus_time.t = - Consensus.Data.Consensus_time.of_time_exn - ~constants:consensus_constants block_time - in - Consensus.Data.Consensus_time.to_global_slot consensus_time ) - with - | Error _ -> - `Failed - | Ok slot -> - `Succeeded slot ) - ~retry_count:10 ~initial_delay:(Span.of_ms 0.0) - ~each_delay:(Span.of_ms 250.0) - ~failure_reason: - (sprintf "Took too long for block %s to be fetched" - (Int64.to_string index)) - in - let expected_balance_at_slot (slot : int64) = - let open Unsigned in - let global_slot = UInt32.of_int (Int.of_int64_exn slot) in - let cliff_time = UInt32.of_int 20 in - let cliff_amount = MinaCurrency.Amount.of_int 2_000_000_000_000 in - let vesting_period = Unsigned.UInt32.of_int 5 in - let vesting_increment = MinaCurrency.Amount.of_int 10_000_000_000 in - let initial_minimum_balance = - MinaCurrency.Balance.of_int 5_000_000_000_000 - in - let total_balance = 10_000_000_000_000 in - let min_balance_at_slot = - Mina_base.Account.min_balance_at_slot ~global_slot ~cliff_time - ~cliff_amount ~vesting_period ~vesting_increment - ~initial_minimum_balance - |> MinaCurrency.Balance.to_int - in - total_balance - min_balance_at_slot - in - let check_balance_at_index (index : int64) ~logger = - let open Deferred.Result.Let_syntax in - let%bind slot = index_to_slot index in - let slot = slot |> Unsigned.UInt32.to_int64 |> Int64.of_int64 in - let expected_balance = expected_balance_at_slot slot in - let%bind actual_balance = - keep_trying - ~step:(fun () -> - let%map balance_r = - Peek.Account_balance.balance_at_index ~account_identifier ~index - ~rosetta_uri ~network_response ~logger - in - match balance_r with - | Ok {balances= [{value; _}]; _} -> - `Succeeded - ( value |> MinaCurrency.Balance.of_string - |> MinaCurrency.Balance.to_int ) - | _ -> - `Failed ) - ~retry_count:5 ~initial_delay:(Span.of_ms 100.0) - ~each_delay:(Span.of_sec 3.0) - ~failure_reason: - (sprintf "Took too long to look up balance for index %s" - (Int64.to_string index)) - in - assert (Int.(expected_balance = actual_balance)) ; - Deferred.Result.return () - in - let rec check_balances_until ~(until_index : int64) - ~(last_index_checked : int64) = - if Int64.(last_index_checked >= until_index) then Deferred.Result.return () - else - let next_index = Int64.(last_index_checked + of_int 1) in - let%bind () = check_balance_at_index next_index ~logger in - let%bind () = - check_balances_until ~until_index ~last_index_checked:next_index - in - Deferred.Result.return () - in - check_balances_until ~until_index:last_block_index - ~last_index_checked:(Int64.of_int 0) - -(* for each possible user command, run the command via GraphQL, check that - the command is in the transaction pool -*) -let check_new_account_user_commands ~logger ~rosetta_uri ~graphql_uri = - let open Core.Time in - let open Deferred.Result.Let_syntax in - (* Stop staking so we can rely on things being in the mempool *) - let%bind _res = Poke.Staking.disable ~graphql_uri in - (* Figure out our network identifier *) - let%bind network_response = Peek.Network.list ~rosetta_uri ~logger in - (* Wait until we are "synced" -- on debug nets this is when block production begins *) - let%bind () = - keep_trying - ~step:(fun () -> - let status_r_dr = - Peek.Network.status ~rosetta_uri ~network_response ~logger - in - let%map status_r = status_r_dr in - if - [%equal: (string option, Error.t) Result.t] - (Result.map status_r ~f:(fun status -> - Option.bind status.Network_status_response.sync_status - ~f:(fun sync_status -> sync_status.stage) )) - (Ok (Some "Synced")) - then `Succeeded () - else `Failed ) - ~retry_count:15 ~initial_delay:(Span.of_sec 0.5) - ~each_delay:(Span.of_sec 1.0) ~failure_reason:"Took too long to sync" - in - (* Directly create a payment in graphql and make sure it's in the mempool - * properly, and then in a block properly *) - [%log info] "Starting payment check" ; - let%bind () = - direct_graphql_payment_through_block ~logger ~rosetta_uri ~graphql_uri - ~network_response - in - [%log info] "Created payment and waited" ; - (* Stop staking so we can rely on things being in the mempool again *) - let%bind _res = Poke.Staking.disable ~graphql_uri in - [%log info] "Starting payment (no account fee) check" ; - let%bind () = - direct_graphql_no_account_fee_through_block ~logger ~rosetta_uri - ~graphql_uri ~network_response - in - [%log info] "Created payment (no account fee) and waited" ; - (* Stop staking so we can rely on things being in the mempool again *) - let%bind _res = Poke.Staking.disable ~graphql_uri in - (* Follow the full construction API flow and make sure the submitted - * transaction appears in the mempool *) - [%log info] "Starting construction payment check" ; - let%bind () = - construction_api_payment_through_mempool ~logger ~rosetta_uri ~graphql_uri - ~network_response - in - [%log info] "Created construction payment and waited" ; - (* Stop staking *) - [%log info] "Starting delegation check" ; - let%bind _res = Poke.Staking.disable ~graphql_uri in - let%bind () = - direct_graphql_delegation_through_block ~logger ~rosetta_uri ~graphql_uri - ~network_response - in - [%log info] "Created graphql delegation and waited" ; - (* Stop staking *) - [%log info] "Starting construction delegation check" ; - let%bind _res = Poke.Staking.disable ~graphql_uri in - let%bind () = - construction_api_delegation_through_mempool ~logger ~rosetta_uri - ~graphql_uri ~network_response - in - [%log info] "Created construction delegation and waited" ; - (* token creation is disabled in daemon for now *) - (* - [%log info] "Starting create token check" ; - (* Stop staking *) - let%bind _res = Poke.Staking.disable ~graphql_uri in - let%bind () = - direct_graphql_create_token_through_block ~logger ~rosetta_uri ~graphql_uri - ~network_response - in - [%log info] "Created token via graphql and waited" ; - [%log info] "Starting create token construction check" ; - let%bind () = - construction_api_create_token_through_mempool ~logger ~rosetta_uri - ~graphql_uri ~network_response - in - [%log info] "Created token using construction and waited" ; - (* Stop staking *) - [%log info] "Starting create token account check" ; - let%bind _res = Poke.Staking.disable ~graphql_uri in - let%bind () = - direct_graphql_create_token_account_through_block ~logger ~rosetta_uri - ~graphql_uri ~network_response - in - [%log info] "Created token account and waited" ; - [%log info] "Starting construction create token account check" ; - let%bind () = - construction_api_create_token_account_through_mempool ~logger ~rosetta_uri - ~graphql_uri ~network_response - in - [%log info] "Created token account using construction and waited" ; - [%log info] "Starting historical balance check" ; - let%bind _ = - historical_balance_check ~logger ~rosetta_uri ~network_response - in - *) - [%log info] "Finished historical balance check" ; - (* Success *) - return () - -let run ~logger ~rosetta_uri ~graphql_uri ~don't_exit = - let open Core.Time in - let open Deferred.Result.Let_syntax in - let%bind () = - check_new_account_user_commands ~logger ~rosetta_uri ~graphql_uri - in - [%log info] "Finished running test-agent" ; - if don't_exit then ( - let%bind _res = Poke.Staking.enable ~graphql_uri in - [%log info] "Running forever with more blocks" ; - let rec go () = - let%bind () = wait (Span.of_sec 1.0) in - go () - in - go () ) - else ( - [%log info] "Exiting" ; - return () ) - -let command = - let open Command.Let_syntax in - let%map_open rosetta_uri = - flag "--rosetta-uri" ~aliases:["rosetta-uri"] - ~doc:"URI of Rosetta endpoint to connect to" Cli.required_uri - and graphql_uri = - flag "--graphql-uri" ~aliases:["graphql-uri"] - ~doc:"URI of Mina GraphQL endpoint to connect to" Cli.required_uri - and log_json = - flag "--log-json" ~aliases:["log-json"] - ~doc:"Print log output as JSON (default: plain text)" no_arg - and log_level = - flag "--log-level" ~aliases:["log-level"] - ~doc:"Set log level (default: Info)" Cli.log_level - and don't_exit = - flag "--dont-exit" ~aliases:["dont-exit"] - ~doc:"Don't exit after tests finish (default: do exit)" no_arg - in - let open Deferred.Let_syntax in - fun () -> - let logger = Logger.create () in - Cli.logger_setup log_json log_level ; - [%log info] "Rosetta test-agent starting" ; - match%bind run ~logger ~rosetta_uri ~graphql_uri ~don't_exit with - | Ok () -> - [%log info] "Rosetta test-agent stopping successfully" ; - return () - | Error e -> - [%log error] "Rosetta test-agent stopping with a failure: %s" - (Errors.show e) ; - exit 1 - -let () = - Command.run - (Command.async ~summary:"Run agent to poke at Coda and peek at Rosetta" - command) diff --git a/src/app/rosetta/test-agent/dune b/src/app/rosetta/test-agent/dune deleted file mode 100644 index 0b709f5f58d..00000000000 --- a/src/app/rosetta/test-agent/dune +++ /dev/null @@ -1,32 +0,0 @@ -(executable - (package agent) - (name agent) - (public_name agent) - (modes native) - (libraries - async - async_ssl - caqti - caqti-async - caqti-driver-postgresql - cohttp - ctypes - cohttp-async - core_kernel - logger - rosetta_models - lib - ppx_deriving_yojson.runtime - yojson - ) - (instrumentation (backend bisect_ppx)) - (preprocess (pps - graphql_ppx - ppx_coda - ppx_deriving.show - ppx_deriving_yojson - ppx_jane - ppx_version - ppx_compare - )) -) diff --git a/src/app/rosetta/test-agent/offline.ml b/src/app/rosetta/test-agent/offline.ml deleted file mode 100644 index 0da5fd89820..00000000000 --- a/src/app/rosetta/test-agent/offline.ml +++ /dev/null @@ -1,126 +0,0 @@ -open Async -open Rosetta_models -open Rosetta_lib -module Lift = Peek.Lift - -let post = Peek.post - -let net_id = Peek.net_id - -open Deferred.Result.Let_syntax - -module Derive = struct - let req ~rosetta_uri ~logger ~public_key_hex_bytes ~network_response = - let%bind r = - post ~rosetta_uri ~logger - ~body: - Construction_derive_request.( - { network_identifier= net_id network_response - ; public_key= - { Public_key.hex_bytes= public_key_hex_bytes - ; curve_type= "pallas" } - ; metadata= Some Amount_of.Token_id.(encode default) } - |> to_yojson) - ~path:"construction/derive" - in - Lift.res r ~logger ~of_yojson:Construction_derive_response.of_yojson - |> Lift.successfully -end - -module Preprocess = struct - let req ~rosetta_uri ~logger ~max_fee ~operations ~network_response = - let%bind r = - post ~rosetta_uri ~logger - ~body: - Construction_preprocess_request.( - { network_identifier= net_id network_response - ; max_fee= [Amount_of.mina max_fee] - ; operations - ; suggested_fee_multiplier= None - ; metadata= None } - |> to_yojson) - ~path:"construction/preprocess" - in - Lift.res r ~logger ~of_yojson:Construction_preprocess_response.of_yojson - |> Lift.successfully -end - -module Payloads = struct - let req ~rosetta_uri ~logger ~operations ~metadata ~network_response = - let%bind r = - post ~rosetta_uri ~logger - ~body: - Construction_payloads_request.( - { network_identifier= net_id network_response - ; operations - ; metadata= Some metadata - ; public_keys= [] } - |> to_yojson) - ~path:"construction/payloads" - in - Lift.res r ~logger ~of_yojson:Construction_payloads_response.of_yojson - |> Lift.successfully -end - -module Parse = struct - let req ~rosetta_uri ~logger ~transaction ~network_response = - let signed, transaction = - match transaction with - | `Unsigned txn -> - (false, txn) - | `Signed txn -> - (true, txn) - in - let%bind r = - post ~rosetta_uri ~logger - ~body: - Construction_parse_request.( - {network_identifier= net_id network_response; transaction; signed} - |> to_yojson) - ~path:"construction/parse" - in - Lift.res r ~logger ~of_yojson:Construction_parse_response.of_yojson - |> Lift.successfully -end - -module Combine = struct - let req ~rosetta_uri ~logger ~unsigned_transaction ~signature ~account_id - ~public_key_hex_bytes ~network_response = - let%bind r = - post ~rosetta_uri ~logger - ~body: - Construction_combine_request.( - { network_identifier= net_id network_response - ; unsigned_transaction - ; signatures= - [ (* TODO: How important is it to fill in all these details properly? *) - { Signature.signing_payload= - { Signing_payload.account_identifier= Some account_id - ; address= None - ; hex_bytes= "TODO" - ; signature_type= None } - ; public_key= - { Public_key.hex_bytes= public_key_hex_bytes - ; curve_type= "pallas" } - ; signature_type= "schnorr_poseidon" - ; hex_bytes= signature } ] } - |> to_yojson) - ~path:"construction/combine" - in - Lift.res r ~logger ~of_yojson:Construction_combine_response.of_yojson - |> Lift.successfully -end - -module Hash = struct - let req ~rosetta_uri ~logger ~signed_transaction ~network_response = - let%bind r = - post ~rosetta_uri ~logger - ~body: - Construction_hash_request.( - {network_identifier= net_id network_response; signed_transaction} - |> to_yojson) - ~path:"construction/hash" - in - Lift.res r ~logger ~of_yojson:Transaction_identifier_response.of_yojson - |> Lift.successfully -end diff --git a/src/app/rosetta/test-agent/operation_expectation.ml b/src/app/rosetta/test-agent/operation_expectation.ml deleted file mode 100644 index 3fb237ca76d..00000000000 --- a/src/app/rosetta/test-agent/operation_expectation.ml +++ /dev/null @@ -1,113 +0,0 @@ -open Core_kernel -open Rosetta_models -open Rosetta_lib -open Async - -module Reason = struct - type t = - | Amount - | Account - | Account_pk - | Account_token_id - | Status - | Target - | Type - [@@deriving equal, sexp, show] -end - -module Account = struct - type t = {pk: string; token_id: Unsigned.UInt64.t} [@@deriving show] -end - -type t = - { amount: int option - ; account: Account.t option - ; status: string - ; _type: string - ; target: [`Ignore | `Check of string option] } -[@@deriving show] - -(** Returns a validation of the reasons it is not similar or unit if it is *) -let similar ~logger:_ t (op : Operation.t) = - let open Validation in - let open Validation.Let_syntax in - let open Reason in - let opt_eq ~f a b ~err = - match (a, b) with - | Some x, Some y -> - f x y - | None, None -> - return () - | _ -> - fail err - in - let test b err = if b then return () else fail err in - let%map () = - opt_eq t.amount op.amount ~err:Amount ~f:(fun x y -> - test String.(equal (string_of_int x) y.Amount.value) Amount ) - and () = - opt_eq t.account op.account ~err:Account ~f:(fun x y -> - let%map _ = - test - String.(equal x.Account.pk y.Account_identifier.address) - Account_pk - and _ = - match y.metadata with - | Some (`Assoc [("token_id", `String y)]) -> - test - String.(equal (Unsigned.UInt64.to_string x.token_id) y) - Account_token_id - | _ -> - fail Account_token_id - in - () ) - and () = test (Option.equal String.equal (Some t.status) op.status) Status - and () = - match t.target with - | `Ignore -> - return () - | `Check target -> - opt_eq target op.metadata ~err:Target ~f:(fun target metadata -> - match metadata with - | `Assoc [("delegate_change_target", `String y)] - | `Assoc [("token_owner_pk", `String y)] -> - test String.(equal y target) Target - | _ -> - fail Target ) - and () = test String.(equal t._type op._type) Type in - () - -(** Result of the first expected operation that is wrong. Shows the "closest" - * match by selecting the one with minimal error reasons *) -let assert_similar_operations ~logger ~situation ~expected ~actual = - let rec choose_similar t least_bad_err rest = function - | [] -> - (* TODO: This may raise if we are expecting more ops than we get *) - Error (fst (Option.value_exn least_bad_err)) - | op :: ops -> ( - match similar ~logger t op with - | Ok _ -> - (* Return the operations with this one removed *) - Ok (rest @ ops) - | Error es -> - let l = List.length es in - let least_bad_err = - match least_bad_err with - | Some (_, l') when l' <= l -> - least_bad_err - | _ -> - Some ((op, es), l) - in - choose_similar t least_bad_err (op :: rest) ops ) - in - List.fold_result expected ~init:actual ~f:(fun actual t -> - choose_similar t None [] actual ) - |> Result.map_error ~f:(fun (op, es) -> - Errors.create - ~context: - (sprintf - !"Unexpected operations in %s reasons: %{sexp: Reason.t \ - list}, raw: %s" - situation es (Operation.show op)) - `Invariant_violation ) - |> Result.ignore_m |> Deferred.return diff --git a/src/app/rosetta/test-agent/peek.ml b/src/app/rosetta/test-agent/peek.ml deleted file mode 100644 index 2d303fe9718..00000000000 --- a/src/app/rosetta/test-agent/peek.ml +++ /dev/null @@ -1,199 +0,0 @@ -(** Observing the state of the network through the lens of Rosetta *) - -open Async -open Core_kernel -open Rosetta_models -open Rosetta_lib - -module Lift = struct - let json res = - res - |> Result.map_error ~f:(fun str -> Errors.create (`Json_parse (Some str))) - - let res res ~logger:_ ~of_yojson = - Result.bind res ~f:(fun r -> - of_yojson r - |> Result.map_error ~f:(fun str -> - Errors.erase @@ Errors.create (`Json_parse (Some str)) ) ) - - let successfully r = - match r with - | Ok x -> - Deferred.Result.return x - | Error e -> - Deferred.Result.fail - (Errors.create - ~context:(Rosetta_models.Error.show e) - `Invariant_violation) - - let req ~logger:_ req : - ( (Yojson.Safe.t, Rosetta_models.Error.t) result - , Errors.t ) - Deferred.Result.t = - let open Deferred.Let_syntax in - let%bind response, body = req in - let%bind str = Cohttp_async.Body.to_string body in - match Cohttp_async.Response.status response with - | `OK -> ( - match Yojson.Safe.from_string str with - | body -> - Deferred.Result.return (Ok body) - | exception Yojson.Json_error err -> - Deferred.Result.fail - (Errors.create ~context:"Parsing rosetta body" - (`Json_parse (Some err))) ) - | _ -> ( - match Yojson.Safe.from_string str with - | body -> ( - match Rosetta_models.Error.of_yojson body |> json with - | Ok err -> - Deferred.Result.return (Error err) - | Error e -> - Deferred.Result.fail e ) - | exception Yojson.Json_error err -> - Deferred.Result.fail - (Errors.create ~context:"Parsing Rosetta error" - (`Json_parse (Some err))) ) -end - -let net_id network_response = - List.hd_exn network_response.Network_list_response.network_identifiers - -let post ~logger ~rosetta_uri ~body ~path = - Cohttp_async.Client.post - ~headers: - Cohttp.Header.(init () |> fun t -> add t "Accept" "application/json") - ~body:(body |> Yojson.Safe.to_string |> Cohttp_async.Body.of_string) - (Uri.with_path rosetta_uri path) - |> Lift.req ~logger - -module Network = struct - open Deferred.Result.Let_syntax - - let list ~rosetta_uri ~logger = - let%bind res = - post ~rosetta_uri ~logger - ~body:Metadata_request.(create () |> to_yojson) - ~path:"network/list" - in - Lift.res res ~logger ~of_yojson:Network_list_response.of_yojson - |> Lift.successfully - - let status ~rosetta_uri ~network_response ~logger = - let%map res = - post ~rosetta_uri ~logger - ~body:Network_request.(create (net_id network_response) |> to_yojson) - ~path:"network/status" - in - Lift.res ~logger res ~of_yojson:Network_status_response.of_yojson -end - -module Mempool = struct - open Deferred.Result.Let_syntax - - let mempool ~rosetta_uri ~network_response ~logger = - let%map res = - post ~rosetta_uri ~logger - ~body:Network_request.(create (net_id network_response) |> to_yojson) - ~path:"mempool/" - in - Lift.res ~logger res ~of_yojson:Mempool_response.of_yojson - - let transaction ~rosetta_uri ~network_response ~logger ~hash = - let%bind res = - post ~rosetta_uri ~logger - ~body: - Mempool_transaction_request.( - { network_identifier= net_id network_response - ; transaction_identifier= {Transaction_identifier.hash} } - |> to_yojson) - ~path:"mempool/transaction" - in - Lift.res res ~logger ~of_yojson:Mempool_transaction_response.of_yojson - |> Lift.successfully -end - -module Block = struct - open Deferred.Result.Let_syntax - - let request_block ~block_identifier ~rosetta_uri ~network_response ~logger = - let%map res = - post ~rosetta_uri ~logger - ~body: - Block_request.( - create (net_id network_response) block_identifier |> to_yojson) - ~path:"block/" - in - Lift.res ~logger res ~of_yojson:Block_response.of_yojson - - let newest_block ~rosetta_uri ~network_response ~logger = - request_block - ~block_identifier:(Partial_block_identifier.create ()) - ~rosetta_uri ~network_response ~logger - - let block_at_index ~index ~rosetta_uri ~network_response ~logger = - request_block - ~block_identifier:{index= Some index; hash= None} - ~rosetta_uri ~network_response ~logger -end - -module Construction = struct - open Deferred.Result.Let_syntax - - let metadata ~rosetta_uri ~network_response ~logger ~options = - let%bind res = - post ~rosetta_uri ~logger - ~body: - Construction_metadata_request.( - { network_identifier= net_id network_response - ; options - ; public_keys= [] } - |> to_yojson) - ~path:"construction/metadata" - in - Lift.res ~logger res ~of_yojson:Construction_metadata_response.of_yojson - |> Lift.successfully - - (* This is really a poke, but collocating it here because it goes through rosetta *) - let submit ~rosetta_uri ~network_response ~logger ~signed_transaction = - let%bind res = - post ~rosetta_uri ~logger - ~body: - Construction_submit_request.( - {network_identifier= net_id network_response; signed_transaction} - |> to_yojson) - ~path:"construction/submit" - in - Lift.res ~logger res ~of_yojson:Transaction_identifier_response.of_yojson - |> Lift.successfully -end - -module Account_balance = struct - open Deferred.Result.Let_syntax - - let request_balance ~account_identifier ~block_identifier ~rosetta_uri - ~network_response ~logger = - let request : Account_balance_request.t = - { network_identifier= net_id network_response - ; account_identifier - ; block_identifier - ; currencies= [] } - in - let%map res = - post ~rosetta_uri ~logger - ~body:(request |> Account_balance_request.to_yojson) - ~path:"account/balance" - in - Lift.res ~logger res ~of_yojson:Account_balance_response.of_yojson - - let current_balance ~account_identifier ~rosetta_uri ~network_response - ~logger = - request_balance ~account_identifier ~block_identifier:None ~rosetta_uri - ~network_response ~logger - - let balance_at_index ~account_identifier ~(index : int64) ~rosetta_uri - ~network_response ~logger = - request_balance ~account_identifier - ~block_identifier:(Some {index= Some index; hash= None}) - ~rosetta_uri ~network_response ~logger -end diff --git a/src/app/rosetta/test-agent/poke.ml b/src/app/rosetta/test-agent/poke.ml deleted file mode 100644 index 9d328be3f2e..00000000000 --- a/src/app/rosetta/test-agent/poke.ml +++ /dev/null @@ -1,220 +0,0 @@ -(** Poking the underlying Mina daemon in order to manipulate the sate of - * the network *) - -open Core_kernel -open Lib -open Async - -(* TODO: Parameterize this against prod/test networks *) -(* this is the same as PK in Rosetta dockerfile *) -let pk = "B62qmnkbvNpNvxJ9FkSkBy5W6VkquHbgN2MDHh1P8mRVX3FQ1eWtcxV" - -module Staking = struct - module Disable = - [%graphql - {| - mutation disableStaking { - setStaking(input: {publicKeys: []}) { - lastStaking - } - } - |}] - - let disable ~graphql_uri = - let open Deferred.Result.Let_syntax in - let%map res = Graphql.query (Disable.make ()) graphql_uri in - (res#setStaking)#lastStaking - - module Enable = - [%graphql - {| - mutation enableStaking($publicKey: PublicKey!) { - setStaking(input: {publicKeys: [$publicKey]}) { - lastStaking - } - } -|}] - - let enable ~graphql_uri = - let open Deferred.Result.Let_syntax in - let%map res = - Graphql.query (Enable.make ~publicKey:(`String pk) ()) graphql_uri - in - (res#setStaking)#lastStaking -end - -module Account = struct - module Unlock = - [%graphql - {| - mutation ($password: String!, $public_key: PublicKey!) { - unlockAccount(input: {password: $password, publicKey: $public_key }) { - publicKey - } - } - |}] - - let unlock ~graphql_uri = - let open Deferred.Result.Let_syntax in - let%map res = - Graphql.query - (Unlock.make ~password:"" ~public_key:(`String pk) ()) - graphql_uri - in - (res#unlockAccount)#publicKey -end - -module SendTransaction = struct - module Payment = - [%graphql - {| - mutation sendPayment($fee: UInt64!, $amount: UInt64!, $token: TokenId, $to_: PublicKey!, $from: PublicKey!) { - sendPayment(input: {fee: $fee, amount: $amount, token: $token, to: $to_, from: $from}, signature: null) { - payment { - hash - } - } - } - |}] - - let payment ~fee ~amount ?token ~to_ ~graphql_uri () = - let open Deferred.Result.Let_syntax in - let%map res = - Graphql.query - (Payment.make ~fee ~amount ?token ~to_ ~from:(`String pk) ()) - graphql_uri - in - let (`UserCommand x) = (res#sendPayment)#payment in - x#hash - - (* Note: These operations below are intentionally constructed from a templated - * string rather - * than using a structured User_command_info to serve as living, tested, - * documentation for a valid operation list for a payment *) - - let payment_operations ~from ~fee ~amount ~to_ = - assert (String.equal from pk) ; - let amount_str = Unsigned.UInt64.to_string amount in - let operations = - sprintf - {| [{"operation_identifier":{"index":0},"related_operations":[],"type":"fee_payer_dec","status":"Pending","account":{"address":"%s","metadata":{"token_id":"1"}},"amount":{"value":"-%s","currency":{"symbol":"MINA","decimals":9}}},{"operation_identifier":{"index":1},"related_operations":[],"type":"payment_source_dec","status":"Pending","account":{"address":"%s","metadata":{"token_id":"1"}},"amount":{"value":"-%s","currency":{"symbol":"MINA","decimals":9}}},{"operation_identifier":{"index":2},"related_operations":[{"index":1}],"type":"payment_receiver_inc","status":"Pending","account":{"address":"%s","metadata":{"token_id":"1"}},"amount":{"value":"%s","currency":{"symbol":"MINA","decimals":9}}}] |} - from - (Unsigned.UInt64.to_string fee) - from amount_str to_ amount_str - in - let json = Yojson.Safe.from_string operations in - [%of_yojson: Rosetta_models.Operation.t list] json - |> Result.ok |> Option.value_exn - - module Delegation = - [%graphql - {| - - mutation sendDelegation($fee : UInt64!, $to_: PublicKey!, $from: PublicKey!) { - sendDelegation(input: {fee: $fee, to: $to_, from: $from}, signature: null) { - delegation { - hash - } - } - } - |}] - - let delegation ~fee ~to_ ~graphql_uri () = - let open Deferred.Result.Let_syntax in - let%map res = - Graphql.query - (Delegation.make ~fee ~to_ ~from:(`String pk) ()) - graphql_uri - in - let (`UserCommand cmd) = (res#sendDelegation)#delegation in - cmd#hash - - let delegation_operations ~from ~fee ~to_ = - assert (String.equal from pk) ; - let operations = - sprintf - {| [{"operation_identifier":{"index":0},"related_operations":[],"type":"fee_payer_dec","status":"Pending","account":{"address":"%s","metadata":{"token_id":"1"}},"amount":{"value":"-%s","currency":{"symbol":"MINA","decimals":9}}},{"operation_identifier":{"index":1},"related_operations":[],"type":"delegate_change","status":"Pending","account":{"address":"%s","metadata":{"token_id":"1"}},"amount":null, "metadata": { "delegate_change_target": "%s"} }] |} - from - (Unsigned.UInt64.to_string fee) - from to_ - in - let json = Yojson.Safe.from_string operations in - [%of_yojson: Rosetta_models.Operation.t list] json - |> Result.ok |> Option.value_exn - - module Create_token = - [%graphql - {| - mutation ($sender: PublicKey!, - $receiver: PublicKey!, - $fee: UInt64!) { - createToken(input: {feePayer: $sender, tokenOwner: $receiver, fee: $fee}, signature: null) { - createNewToken { - hash - } - } - } - |}] - - let create_token ~fee ~receiver:_ ~graphql_uri () = - let open Deferred.Result.Let_syntax in - let%map res = - Graphql.query - (Create_token.make ~fee ~sender:(`String pk) ~receiver:(`String pk) ()) - graphql_uri - in - let cmd = (res#createToken)#createNewToken in - cmd#hash - - let create_token_operations ~fee ~sender = - assert (String.equal sender pk) ; - let operations = - sprintf - {| [{"operation_identifier":{"index":0},"related_operations":[],"type":"fee_payer_dec","status":"Pending","account":{"address":"%s","metadata":{"token_id":"1"}},"amount":{"value":"-%s","currency":{"symbol":"MINA","decimals":9}}},{"operation_identifier":{"index":1},"related_operations":[],"type":"create_token","status":"Pending"}] |} - sender - (Unsigned.UInt64.to_string fee) - in - let json = Yojson.Safe.from_string operations in - [%of_yojson: Rosetta_models.Operation.t list] json - |> Result.ok |> Option.value_exn - - module Create_token_account = - [%graphql - {| - mutation ($sender: PublicKey, - $tokenOwner: PublicKey!, - $receiver: PublicKey!, - $token: TokenId!, - $fee: UInt64!) { - createTokenAccount(input: - {feePayer: $sender, tokenOwner: $tokenOwner, receiver: $receiver, token: $token, fee: $fee}, signature: null) { - createNewTokenAccount { - hash - } - } - } - |}] - - let create_token_account ~fee ~receiver ~token ~graphql_uri () = - let open Deferred.Result.Let_syntax in - let%map res = - Graphql.query - (Create_token_account.make ~sender:(`String pk) - ~receiver:(`String receiver) ~tokenOwner:(`String pk) ~token ~fee ()) - graphql_uri - in - let cmd = (res#createTokenAccount)#createNewTokenAccount in - cmd#hash - - let create_token_account_operations ~fee ~sender = - assert (String.equal sender pk) ; - let operations = - sprintf - {| [{"operation_identifier":{"index":0},"related_operations":[],"type":"fee_payer_dec","status":"Pending","account":{"address":"%s","metadata":{"token_id":"1"}},"amount":{"value":"-%s","currency":{"symbol":"MINA","decimals":9}}} |} - sender - (Unsigned.UInt64.to_string fee) - in - let json = Yojson.Safe.from_string operations in - [%of_yojson: Rosetta_models.Operation.t list] json - |> Result.ok |> Option.value_exn -end diff --git a/src/lib/block_producer/block_producer.ml b/src/lib/block_producer/block_producer.ml index 9201ca1a9ff..ac5f19b4ca5 100644 --- a/src/lib/block_producer/block_producer.ml +++ b/src/lib/block_producer/block_producer.ml @@ -4,9 +4,7 @@ open Pipe_lib open Mina_base open Mina_state open Mina_transition -open Signature_lib open O1trace -open Otp_lib module Time = Block_time type Structured_log_events.t += Block_produced @@ -535,7 +533,7 @@ module Vrf_evaluation_state = struct end let run ~logger ~vrf_evaluator ~prover ~verifier ~trust_system - ~get_completed_work ~transaction_resource_pool ~time_controller ~keypairs + ~get_completed_work ~transaction_resource_pool ~time_controller ~consensus_local_state ~coinbase_receiver ~frontier_reader ~transition_writer ~set_next_producer_timing ~log_block_creation ~(precomputed_values : Precomputed_values.t) ~block_reward_threshold @@ -875,22 +873,6 @@ let run ~logger ~vrf_evaluator ~prover ~verifier ~trust_system let vrf_evaluation_state = Vrf_evaluation_state.create () in let rec check_next_block_timing slot i () = trace_recurring "check next block timing" (fun () -> - (* See if we want to change keypairs *) - let _keypairs = - match Agent.get keypairs with - | keypairs, `Different -> - (* Perform block production key swap since we have new - keypairs *) - Consensus.Data.Local_state.block_production_keys_swap - ~constants:consensus_constants consensus_local_state - ( Keypair.And_compressed_pk.Set.to_list keypairs - |> List.map ~f:snd |> Public_key.Compressed.Set.of_list ) - (Time.now time_controller) ; - (*TODO: propagate updated delegatee table to the VRF evaluator*) - keypairs - | keypairs, `Same -> - keypairs - in (* Begin checking for the ability to produce a block *) match Broadcast_pipe.Reader.peek frontier_reader with | None -> @@ -1122,19 +1104,6 @@ let run ~logger ~vrf_evaluator ~prover ~verifier ~trust_system Deferred.return () ))) in let start () = - (* Schedule to wake up immediately on the next tick of the producer loop - * instead of immediately mutating local_state here as there could be a - * race. - * - * Given that rescheduling takes the min of the two timeouts, we won't - * erase this timeout even if the last run of the producer wants to wait - * for a long while. - * *) - Agent.on_update keypairs ~f:(fun _new_keypairs -> - Singleton_scheduler.schedule scheduler (Time.now time_controller) - ~f: - (check_next_block_timing Mina_numbers.Global_slot.zero - Mina_numbers.Length.zero)) ; check_next_block_timing Mina_numbers.Global_slot.zero Mina_numbers.Length.zero () in diff --git a/src/lib/daemon_rpcs/daemon_rpcs.ml b/src/lib/daemon_rpcs/daemon_rpcs.ml index be9bf2d4b9c..150e6a9e89f 100644 --- a/src/lib/daemon_rpcs/daemon_rpcs.ml +++ b/src/lib/daemon_rpcs/daemon_rpcs.ml @@ -1,7 +1,6 @@ open Core_kernel open Async open Mina_base -open Signature_lib module Types = Types module Client = Client @@ -241,15 +240,6 @@ module Stop_tracing = struct Rpc.Rpc.create ~name:"Stop_tracing" ~version:0 ~bin_query ~bin_response end -module Set_staking = struct - type query = Keypair.Stable.Latest.t list [@@deriving bin_io_unversioned] - - type response = unit [@@deriving bin_io_unversioned] - - let rpc : (query, response) Rpc.Rpc.t = - Rpc.Rpc.create ~name:"Set_staking" ~version:0 ~bin_query ~bin_response -end - module Visualization = struct module Frontier = struct type query = string [@@deriving bin_io_unversioned] diff --git a/src/lib/mina_commands/mina_commands.ml b/src/lib/mina_commands/mina_commands.ml index 4a0fd8d8c56..7bc4f3b73de 100644 --- a/src/lib/mina_commands/mina_commands.ml +++ b/src/lib/mina_commands/mina_commands.ml @@ -61,19 +61,6 @@ let reset_trust_status t (ip_address : Unix.Inet_addr.Blocking_sexp.t) = let trust_system = config.trust_system in Trust_system.reset_ip trust_system ip_address -let replace_block_production_keys keys pks = - let kps = - List.filter_map pks ~f:(fun pk -> - let open Option.Let_syntax in - let%map kps = - Mina_lib.wallets keys |> Secrets.Wallets.find_unlocked ~needle:pk - in - (kps, pk)) - in - Mina_lib.replace_block_production_keypairs keys - (Keypair.And_compressed_pk.Set.of_list kps) ; - kps |> List.map ~f:snd - let setup_and_submit_user_command t (user_command_input : User_command_input.t) = let open Participating_state.Let_syntax in diff --git a/src/lib/mina_graphql/mina_graphql.ml b/src/lib/mina_graphql/mina_graphql.ml index 6f1d4c00b01..c24cea5bfa6 100644 --- a/src/lib/mina_graphql/mina_graphql.ml +++ b/src/lib/mina_graphql/mina_graphql.ml @@ -1831,27 +1831,6 @@ module Types = struct ~resolve:(fun _ -> Fn.id) ]) - let set_staking = - obj "SetStakingPayload" ~fields:(fun _ -> - [ field "lastStaking" - ~doc:"Returns the public keys that were staking funds previously" - ~typ:(non_null (list (non_null public_key))) - ~args:Arg.[] - ~resolve:(fun _ (lastStaking, _, _) -> lastStaking) - ; field "lockedPublicKeys" - ~doc: - "List of public keys that could not be used to stake because \ - they were locked" - ~typ:(non_null (list (non_null public_key))) - ~args:Arg.[] - ~resolve:(fun _ (_, locked, _) -> locked) - ; field "currentStakingKeys" - ~doc:"Returns the public keys that are now staking their funds" - ~typ:(non_null (list (non_null public_key))) - ~args:Arg.[] - ~resolve:(fun _ (_, _, currentStaking) -> currentStaking) - ]) - let set_coinbase_receiver = obj "SetCoinbaseReceiverPayload" ~fields:(fun _ -> [ field "lastCoinbaseReceiver" @@ -2334,16 +2313,6 @@ module Types = struct ~typ:(non_null public_key_arg) ] - let set_staking = - obj "SetStakingInput" ~coerce:Fn.id - ~fields: - [ arg "publicKeys" - ~typ:(non_null (list (non_null public_key_arg))) - ~doc: - "Public keys of accounts you wish to stake with - these must \ - be accounts that are in trackedAccounts" - ] - let set_coinbase_receiver = obj "SetCoinbaseReceiverInput" ~coerce:Fn.id ~fields: @@ -3083,19 +3052,6 @@ module Mutations = struct Result.map_error result ~f:(Fn.compose Yojson.Safe.to_string Error_json.error_to_yojson)) - let set_staking = - result_field "setStaking" ~doc:"Set keys you wish to stake with" - ~args:Arg.[ arg "input" ~typ:(non_null Types.Input.set_staking) ] - ~typ:(non_null Types.Payload.set_staking) - ~deprecated: - (Deprecated - (Some "Restart the daemon with the flag --block-producer-key instead")) - ~resolve:(fun { ctx = _coda; _ } () _pks -> - Error - "The setStaking command is deprecated and no longer has any effect. \ - To enable block production, instead restart the daemon with the \ - flag --block-producer-key.") - let set_coinbase_receiver = field "setCoinbaseReceiver" ~doc:"Set the key to receive coinbases" ~args: @@ -3281,7 +3237,6 @@ module Mutations = struct ; create_token_account ; mint_tokens ; export_logs - ; set_staking ; set_coinbase_receiver ; set_snark_worker ; set_snark_work_fee diff --git a/src/lib/mina_lib/config.ml b/src/lib/mina_lib/config.ml index 53fda89c917..4bdf35b6045 100644 --- a/src/lib/mina_lib/config.ml +++ b/src/lib/mina_lib/config.ml @@ -23,7 +23,7 @@ type t = ; is_seed : bool ; disable_node_status : bool ; super_catchup : bool - ; initial_block_production_keypairs : Keypair.Set.t + ; block_production_keypairs : Keypair.And_compressed_pk.Set.t ; coinbase_receiver : Consensus.Coinbase_receiver.t ; work_selection_method : (module Work_selector.Selection_method_intf) ; snark_worker_config : Snark_worker_config.t diff --git a/src/lib/mina_lib/mina_lib.ml b/src/lib/mina_lib/mina_lib.ml index 17b6b5ce8da..94f92b56c7c 100644 --- a/src/lib/mina_lib/mina_lib.ml +++ b/src/lib/mina_lib/mina_lib.ml @@ -7,7 +7,6 @@ open Pipe_lib open Strict_pipe open Signature_lib open O1trace -open Otp_lib open Network_peer module Archive_client = Archive_client module Config = Config @@ -123,8 +122,6 @@ type t = ; pipes : pipes ; wallets : Secrets.Wallets.t ; coinbase_receiver : Consensus.Coinbase_receiver.t ref - ; block_production_keypairs : - (Agent.read_write Agent.flag, Keypair.And_compressed_pk.Set.t) Agent.t ; snark_job_state : Work_selector.State.t ; mutable next_producer_timing : Daemon_rpcs.Types.Status.Next_producer_timing.t option @@ -156,9 +153,8 @@ let client_port t = (* Get the most recently set public keys *) let block_production_pubkeys t : Public_key.Compressed.Set.t = - let keypair_and_compressed_pks, _ = Agent.get t.block_production_keypairs in - Public_key.Compressed.Set.map keypair_and_compressed_pks - ~f:(fun (_keypair, pk_compressed) -> pk_compressed) + t.config.block_production_keypairs |> Keypair.And_compressed_pk.Set.to_list + |> List.map ~f:snd |> Public_key.Compressed.Set.of_list let coinbase_receiver t = !(t.coinbase_receiver) @@ -173,9 +169,6 @@ let replace_coinbase_receiver t coinbase_receiver = ] ; t.coinbase_receiver := coinbase_receiver -let replace_block_production_keypairs t kps = - Agent.update t.block_production_keypairs kps - let log_snark_worker_warning t = if Option.is_some t.config.snark_coordinator_key then [%log' warn t.config.logger] @@ -1177,25 +1170,29 @@ let start t = t.block_production_status := block_production_status ; t.next_producer_timing <- Some next_producer_timing in - Block_producer.run ~logger:t.config.logger - ~vrf_evaluator:t.processes.vrf_evaluator ~verifier:t.processes.verifier - ~set_next_producer_timing ~prover:t.processes.prover - ~trust_system:t.config.trust_system - ~transaction_resource_pool: - (Network_pool.Transaction_pool.resource_pool - t.components.transaction_pool) - ~get_completed_work: - (Network_pool.Snark_pool.get_completed_work t.components.snark_pool) - ~time_controller:t.config.time_controller - ~keypairs:(Agent.read_only t.block_production_keypairs) - ~coinbase_receiver:t.coinbase_receiver - ~consensus_local_state:t.config.consensus_local_state - ~frontier_reader:t.components.transition_frontier - ~transition_writer:t.pipes.producer_transition_writer - ~log_block_creation:t.config.log_block_creation - ~precomputed_values:t.config.precomputed_values - ~block_reward_threshold:t.config.block_reward_threshold - ~block_produced_bvar:t.components.block_produced_bvar ; + if + not + (Keypair.And_compressed_pk.Set.is_empty + t.config.block_production_keypairs) + then + Block_producer.run ~logger:t.config.logger + ~vrf_evaluator:t.processes.vrf_evaluator ~verifier:t.processes.verifier + ~set_next_producer_timing ~prover:t.processes.prover + ~trust_system:t.config.trust_system + ~transaction_resource_pool: + (Network_pool.Transaction_pool.resource_pool + t.components.transaction_pool) + ~get_completed_work: + (Network_pool.Snark_pool.get_completed_work t.components.snark_pool) + ~time_controller:t.config.time_controller + ~coinbase_receiver:t.coinbase_receiver + ~consensus_local_state:t.config.consensus_local_state + ~frontier_reader:t.components.transition_frontier + ~transition_writer:t.pipes.producer_transition_writer + ~log_block_creation:t.config.log_block_creation + ~precomputed_values:t.config.precomputed_values + ~block_reward_threshold:t.config.block_reward_threshold + ~block_produced_bvar:t.components.block_produced_bvar ; perform_compaction t ; let () = match t.config.node_status_url with @@ -1279,15 +1276,6 @@ let create ?wallets (config : Config.t) = let monitor = Option.value ~default:(Monitor.create ()) config.monitor in Async.Scheduler.within' ~monitor (fun () -> trace "mina_lib" (fun () -> - let block_production_keypairs = - Agent.create - ~f:(fun kps -> - Keypair.Set.to_list kps - |> List.map ~f:(fun kp -> - (kp, Public_key.compress kp.Keypair.public_key)) - |> Keypair.And_compressed_pk.Set.of_list) - config.initial_block_production_keypairs - in let%bind prover = Monitor.try_with ~here:[%here] ~rest: @@ -1339,7 +1327,7 @@ let create ?wallets (config : Config.t) = Vrf_evaluator.create ~constraint_constants ~pids:config.pids ~logger:config.logger ~conf_dir:config.conf_dir ~consensus_constants - ~keypairs:(Agent.get block_production_keypairs |> fst))) + ~keypairs:config.block_production_keypairs)) >>| Result.ok_exn in let snark_worker = @@ -1524,10 +1512,8 @@ let create ?wallets (config : Config.t) = (Mina_incremental.Status.Observer.value status) in let block_producers = - let public_keys, _ = - Agent.get block_production_keypairs - in - Public_key.Compressed.Set.map public_keys ~f:snd + config.block_production_keypairs + |> Public_key.Compressed.Set.map ~f:snd |> Set.to_list in let ban_statuses = @@ -2058,7 +2044,6 @@ let create ?wallets (config : Config.t) = ; local_snark_work_writer } ; wallets - ; block_production_keypairs ; coinbase_receiver = ref config.coinbase_receiver ; snark_job_state = snark_jobs_state ; subscriptions diff --git a/src/lib/mina_lib/mina_lib.mli b/src/lib/mina_lib/mina_lib.mli index 16ecf7e5941..37b11f30969 100644 --- a/src/lib/mina_lib/mina_lib.mli +++ b/src/lib/mina_lib/mina_lib.mli @@ -36,9 +36,6 @@ val daemon_start_time : Time_ns.t (** Derived from local state (aka they may not reflect the latest public keys to which you've attempted to change *) val block_production_pubkeys : t -> Public_key.Compressed.Set.t -val replace_block_production_keypairs : - t -> Keypair.And_compressed_pk.Set.t -> unit - val coinbase_receiver : t -> Consensus.Coinbase_receiver.t val replace_coinbase_receiver : t -> Consensus.Coinbase_receiver.t -> unit