├── .dockerignore ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── ci.yml │ ├── publish.yml │ └── release.yml ├── .gitignore ├── .rustfmt.nightly.toml ├── Cargo.toml ├── LICENSE ├── README.md ├── avalanchego-conformance-sdk ├── Cargo.toml ├── LICENSE ├── build.rs ├── examples │ └── ping_service.rs ├── scripts │ └── build.release.sh └── src │ └── lib.rs ├── avalanchego-conformance ├── .gitignore ├── LICENSE ├── README.md ├── buf.gen.yaml ├── buf.lock ├── buf.yaml ├── client │ └── client.go ├── cmd │ └── avalanchego-conformance │ │ ├── main.go │ │ └── server │ │ └── server.go ├── go.mod ├── go.sum ├── pkg │ ├── color │ │ └── color.go │ └── logutil │ │ └── zap.go ├── rpcpb │ ├── key.pb.go │ ├── key.proto │ ├── key_grpc.pb.go │ ├── message.pb.go │ ├── message.proto │ ├── message_grpc.pb.go │ ├── packer.pb.go │ ├── packer.proto │ ├── packer_grpc.pb.go │ ├── ping.pb.go │ ├── ping.proto │ └── ping_grpc.pb.go ├── scripts │ ├── genproto.sh │ └── updatedep.sh └── server │ ├── key.go │ ├── message.go │ ├── packer.go │ └── server.go ├── core ├── cert-manager │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── x509.rs ├── network │ ├── Cargo.toml │ ├── LICENSE │ ├── README.md │ ├── examples │ │ └── peer_outbound_ping.rs │ └── src │ │ ├── lib.rs │ │ └── peer │ │ ├── inbound.rs │ │ ├── mod.rs │ │ └── outbound.rs └── server │ ├── .gitignore │ ├── Cargo.toml │ ├── LICENSE │ ├── README.md │ └── src │ ├── handler.rs │ └── lib.rs ├── crates ├── avalanche-consensus │ ├── Cargo.toml │ ├── LICENSE │ ├── README.md │ ├── src │ │ ├── context.rs │ │ ├── lib.rs │ │ └── snowman │ │ │ ├── block │ │ │ ├── mod.rs │ │ │ └── test_block.rs │ │ │ ├── mod.rs │ │ │ ├── snowball │ │ │ ├── binary │ │ │ │ ├── mod.rs │ │ │ │ └── node.rs │ │ │ ├── mod.rs │ │ │ ├── tree.rs │ │ │ └── unary │ │ │ │ ├── mod.rs │ │ │ │ └── node.rs │ │ │ └── topological.rs │ └── tests.unit.sh └── avalanche-types │ ├── .gitignore │ ├── Cargo.toml │ ├── LICENSE │ ├── README.md │ ├── artifacts │ ├── sample.genesis.json │ ├── staker1.insecure.crt │ ├── staker1.insecure.key │ ├── staker2.insecure.crt │ ├── staker2.insecure.key │ ├── staker3.insecure.crt │ ├── staker3.insecure.key │ ├── staker4.insecure.crt │ ├── staker4.insecure.key │ ├── staker5.insecure.crt │ ├── staker5.insecure.key │ ├── test.insecure.crt │ ├── test.insecure.key │ └── test.insecure.secp256k1.key.infos.json │ ├── examples │ ├── evm_contract_abi_calldata.rs │ ├── evm_contract_counter_get_last.rs │ ├── evm_contract_counter_increment.rs │ ├── evm_contract_counter_increment_append_calldata.rs │ ├── evm_contract_counter_increment_forwarder_execute.rs │ ├── evm_contract_counter_increment_forwarder_proxy_call.rs │ ├── evm_contract_counter_increment_forwarder_relay_eip712.rs │ ├── evm_contract_erc20_simple_token_increase_allowance_forwarder_relay_eip712.rs │ ├── evm_contract_erc20_simple_token_transfer_from_forwarder_relay_eip712.rs │ ├── evm_contract_erc721_my_token_approve_forwarder_relay_eip712.rs │ ├── evm_contract_erc721_my_token_mint_forwarder_relay_eip712.rs │ ├── evm_contract_erc721_my_token_transfer_from_forwarder_relay_eip712.rs │ ├── evm_contract_forwarder_get_nonce.rs │ ├── evm_contract_simple_registry_register.rs │ ├── evm_contract_simple_registry_register_forwarder_execute.rs │ ├── evm_contract_simple_registry_register_forwarder_relay_eip712.rs │ ├── evm_contract_voter_vote_a_forwarder_relay_eip712.rs │ ├── evm_eip712_gsn_domain_separator.rs │ ├── evm_eip712_gsn_request_type_hash.rs │ ├── evm_send_raw_transaction_eip1559_hot_key.rs │ ├── evm_send_raw_transaction_eip1559_kms_aws.rs │ ├── jsonrpc_client_evm.rs │ ├── jsonrpc_client_info.rs │ ├── jsonrpc_client_p.rs │ ├── jsonrpc_client_x.rs │ ├── key_cert.rs │ ├── key_secp256k1_info_gen.rs │ ├── key_secp256k1_info_load_avax.rs │ ├── key_secp256k1_info_load_eth.rs │ ├── key_secp256k1_kms_aws.rs │ ├── key_secp256k1_mnemonic_derive_load.rs │ ├── proto_client.rs │ ├── proto_server.rs │ └── wallet_evm_send_transaction_hot_key.rs │ ├── fuzz │ ├── .gitignore │ ├── Cargo.toml │ └── fuzz_targets │ │ └── ids.rs │ ├── scripts │ ├── examples.sh │ └── protobuf_codegen.sh │ ├── src │ ├── avalanchego │ │ ├── aliases.rs │ │ ├── config.rs │ │ ├── genesis.rs │ │ └── mod.rs │ ├── avm │ │ ├── mod.rs │ │ └── txs │ │ │ ├── export.rs │ │ │ ├── fx.rs │ │ │ ├── import.rs │ │ │ ├── mod.rs │ │ │ └── vertex.rs │ ├── choices │ │ ├── decidable.rs │ │ ├── mod.rs │ │ ├── status.rs │ │ └── test_decidable.rs │ ├── codec │ │ ├── mod.rs │ │ └── serde │ │ │ ├── base64_bytes.rs │ │ │ ├── hex_0x_big_int.rs │ │ │ ├── hex_0x_bytes.rs │ │ │ ├── hex_0x_primitive_types_h160.rs │ │ │ ├── hex_0x_primitive_types_h256.rs │ │ │ ├── hex_0x_primitive_types_u256.rs │ │ │ ├── hex_0x_u64.rs │ │ │ ├── hex_0x_utxo.rs │ │ │ ├── ip_port.rs │ │ │ ├── mod.rs │ │ │ └── rfc_3339.rs │ ├── constants.rs │ ├── coreth │ │ ├── chain_config.rs │ │ ├── genesis.rs │ │ └── mod.rs │ ├── errors.rs │ ├── evm │ │ ├── abi │ │ │ └── mod.rs │ │ ├── eip1559 │ │ │ └── mod.rs │ │ ├── eip712 │ │ │ ├── gsn │ │ │ │ ├── mod.rs │ │ │ │ └── relay.rs │ │ │ └── mod.rs │ │ ├── foundry │ │ │ ├── forge.rs │ │ │ └── mod.rs │ │ └── mod.rs │ ├── formatting │ │ └── mod.rs │ ├── hash │ │ └── mod.rs │ ├── ids │ │ ├── bag.rs │ │ ├── bits.rs │ │ ├── mod.rs │ │ ├── node.rs │ │ └── short.rs │ ├── jsonrpc │ │ ├── admin.rs │ │ ├── avm.rs │ │ ├── client │ │ │ ├── admin.rs │ │ │ ├── evm.rs │ │ │ ├── health.rs │ │ │ ├── info.rs │ │ │ ├── mod.rs │ │ │ ├── p.rs │ │ │ ├── url.rs │ │ │ └── x.rs │ │ ├── common.rs │ │ ├── evm.rs │ │ ├── health.rs │ │ ├── info.rs │ │ ├── mod.rs │ │ └── platformvm.rs │ ├── key │ │ ├── bls │ │ │ ├── mod.rs │ │ │ ├── private_key.rs │ │ │ ├── public_key.rs │ │ │ └── signature.rs │ │ ├── mod.rs │ │ └── secp256k1 │ │ │ ├── address.rs │ │ │ ├── keychain.rs │ │ │ ├── kms │ │ │ ├── aws │ │ │ │ ├── eth_signer.rs │ │ │ │ └── mod.rs │ │ │ └── mod.rs │ │ │ ├── libsecp256k1.rs │ │ │ ├── mnemonic.rs │ │ │ ├── mod.rs │ │ │ ├── private_key.rs │ │ │ ├── public_key.rs │ │ │ ├── signature.rs │ │ │ └── txs │ │ │ ├── mod.rs │ │ │ └── transfer.rs │ ├── lib.rs │ ├── message │ │ ├── accepted.rs │ │ ├── accepted_frontier.rs │ │ ├── accepted_state_summary.rs │ │ ├── ancestors.rs │ │ ├── app_gossip.rs │ │ ├── app_request.rs │ │ ├── app_response.rs │ │ ├── chits.rs │ │ ├── compress.rs │ │ ├── get.rs │ │ ├── get_accepted.rs │ │ ├── get_accepted_frontier.rs │ │ ├── get_accepted_state_summary.rs │ │ ├── get_ancestors.rs │ │ ├── get_state_summary_frontier.rs │ │ ├── mod.rs │ │ ├── peerlist.rs │ │ ├── ping.rs │ │ ├── pong.rs │ │ ├── pull_query.rs │ │ ├── push_query.rs │ │ ├── put.rs │ │ └── state_summary_frontier.rs │ ├── node.rs │ ├── packer │ │ ├── ip.rs │ │ └── mod.rs │ ├── platformvm │ │ ├── mod.rs │ │ └── txs │ │ │ ├── add_permissionless_validator.rs │ │ │ ├── add_subnet_validator.rs │ │ │ ├── add_validator.rs │ │ │ ├── create_chain.rs │ │ │ ├── create_subnet.rs │ │ │ ├── export.rs │ │ │ ├── import.rs │ │ │ ├── mod.rs │ │ │ └── status.rs │ ├── proto │ │ ├── README.md │ │ ├── buf.gen.yaml │ │ ├── buf.lock │ │ ├── buf.work.yaml │ │ ├── buf.yaml │ │ ├── mod.rs │ │ ├── pb │ │ │ ├── aliasreader.rs │ │ │ ├── aliasreader.tonic.rs │ │ │ ├── appsender.rs │ │ │ ├── appsender.tonic.rs │ │ │ ├── google.protobuf.rs │ │ │ ├── helloworld.rs │ │ │ ├── helloworld.tonic.rs │ │ │ ├── http.responsewriter.rs │ │ │ ├── http.responsewriter.tonic.rs │ │ │ ├── http.rs │ │ │ ├── http.tonic.rs │ │ │ ├── io.prometheus.client.rs │ │ │ ├── io.reader.rs │ │ │ ├── io.reader.tonic.rs │ │ │ ├── io.writer.rs │ │ │ ├── io.writer.tonic.rs │ │ │ ├── keystore.rs │ │ │ ├── keystore.tonic.rs │ │ │ ├── message.rs │ │ │ ├── messenger.rs │ │ │ ├── messenger.tonic.rs │ │ │ ├── mod.rs │ │ │ ├── net.conn.rs │ │ │ ├── net.conn.tonic.rs │ │ │ ├── p2p.rs │ │ │ ├── rpcdb.rs │ │ │ ├── rpcdb.tonic.rs │ │ │ ├── sdk.rs │ │ │ ├── sharedmemory.rs │ │ │ ├── sharedmemory.tonic.rs │ │ │ ├── subnetlookup.rs │ │ │ ├── subnetlookup.tonic.rs │ │ │ ├── sync.rs │ │ │ ├── sync.tonic.rs │ │ │ ├── validatorstate.rs │ │ │ ├── validatorstate.tonic.rs │ │ │ ├── vm.rs │ │ │ ├── vm.runtime.rs │ │ │ ├── vm.runtime.tonic.rs │ │ │ ├── vm.tonic.rs │ │ │ ├── warp.rs │ │ │ └── warp.tonic.rs │ │ └── protos │ │ │ ├── avalanche │ │ │ ├── aliasreader │ │ │ │ └── aliasreader.proto │ │ │ ├── appsender │ │ │ │ └── appsender.proto │ │ │ ├── http │ │ │ │ ├── http.proto │ │ │ │ └── responsewriter │ │ │ │ │ └── responsewriter.proto │ │ │ ├── io │ │ │ │ ├── prometheus │ │ │ │ │ └── client │ │ │ │ │ │ └── metrics.proto │ │ │ │ ├── reader │ │ │ │ │ └── reader.proto │ │ │ │ └── writer │ │ │ │ │ └── writer.proto │ │ │ ├── keystore │ │ │ │ └── keystore.proto │ │ │ ├── message │ │ │ │ └── tx.proto │ │ │ ├── messenger │ │ │ │ └── messenger.proto │ │ │ ├── net │ │ │ │ └── conn │ │ │ │ │ └── conn.proto │ │ │ ├── p2p │ │ │ │ └── p2p.proto │ │ │ ├── rpcdb │ │ │ │ └── rpcdb.proto │ │ │ ├── sdk │ │ │ │ └── sdk.proto │ │ │ ├── sharedmemory │ │ │ │ └── sharedmemory.proto │ │ │ ├── sync │ │ │ │ └── sync.proto │ │ │ ├── validatorstate │ │ │ │ └── validator_state.proto │ │ │ ├── vm │ │ │ │ ├── runtime │ │ │ │ │ └── runtime.proto │ │ │ │ └── vm.proto │ │ │ └── warp │ │ │ │ └── message.proto │ │ │ └── static │ │ │ ├── google │ │ │ └── protobuf │ │ │ │ ├── descriptor.proto │ │ │ │ ├── empty.proto │ │ │ │ └── timestamp.proto │ │ │ └── helloworld │ │ │ └── helloworld.proto │ ├── subnet │ │ ├── README.md │ │ ├── config │ │ │ ├── consensus.rs │ │ │ ├── gossip.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ └── rpc │ │ │ ├── consensus │ │ │ ├── mod.rs │ │ │ └── snowman.rs │ │ │ ├── context.rs │ │ │ ├── database │ │ │ ├── batch.rs │ │ │ ├── corruptabledb │ │ │ │ └── mod.rs │ │ │ ├── iterator.rs │ │ │ ├── manager │ │ │ │ ├── mod.rs │ │ │ │ └── versioned_database.rs │ │ │ ├── memdb │ │ │ │ ├── batch.rs │ │ │ │ ├── iterator.rs │ │ │ │ └── mod.rs │ │ │ ├── mod.rs │ │ │ ├── nodb.rs │ │ │ ├── rpcdb │ │ │ │ ├── client │ │ │ │ │ ├── batch.rs │ │ │ │ │ ├── iterator.rs │ │ │ │ │ └── mod.rs │ │ │ │ ├── mod.rs │ │ │ │ └── server │ │ │ │ │ └── mod.rs │ │ │ └── versiondb │ │ │ │ ├── batch.rs │ │ │ │ ├── iterator.rs │ │ │ │ └── mod.rs │ │ │ ├── errors.rs │ │ │ ├── health.rs │ │ │ ├── http │ │ │ ├── client.rs │ │ │ ├── handle │ │ │ │ └── mod.rs │ │ │ ├── mod.rs │ │ │ └── server.rs │ │ │ ├── metrics.rs │ │ │ ├── mod.rs │ │ │ ├── plugin.rs │ │ │ ├── runtime │ │ │ ├── client.rs │ │ │ └── mod.rs │ │ │ ├── snow │ │ │ ├── engine │ │ │ │ ├── common │ │ │ │ │ ├── appsender │ │ │ │ │ │ ├── client.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ └── server.rs │ │ │ │ │ ├── engine.rs │ │ │ │ │ ├── http_handler.rs │ │ │ │ │ ├── message.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── vm.rs │ │ │ │ └── mod.rs │ │ │ ├── mod.rs │ │ │ └── validators │ │ │ │ ├── client.rs │ │ │ │ └── mod.rs │ │ │ ├── snowman │ │ │ ├── block.rs │ │ │ └── mod.rs │ │ │ ├── utils │ │ │ ├── grpc.rs │ │ │ └── mod.rs │ │ │ └── vm │ │ │ ├── mod.rs │ │ │ └── server.rs │ ├── subnet_evm │ │ ├── chain_config.rs │ │ ├── genesis.rs │ │ └── mod.rs │ ├── txs │ │ ├── mod.rs │ │ ├── raw.rs │ │ ├── transferable.rs │ │ └── utxo.rs │ ├── units.rs │ ├── utils │ │ ├── mod.rs │ │ ├── urls.rs │ │ └── version.rs │ ├── verify.rs │ ├── wallet │ │ ├── evm │ │ │ ├── eip1559.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── p │ │ │ ├── add_permissionless_validator.rs │ │ │ ├── add_subnet_validator.rs │ │ │ ├── add_validator.rs │ │ │ ├── create_chain.rs │ │ │ ├── create_subnet.rs │ │ │ ├── export.rs │ │ │ ├── import.rs │ │ │ └── mod.rs │ │ └── x │ │ │ ├── export.rs │ │ │ ├── import.rs │ │ │ ├── mod.rs │ │ │ └── transfer.rs │ └── xsvm │ │ ├── genesis.rs │ │ └── mod.rs │ ├── tests.unit.sh │ └── tests │ ├── integration_tests.rs │ └── rpc │ ├── database │ ├── batch.rs │ ├── concurrency.rs │ ├── iterator.rs │ └── mod.rs │ ├── mod.rs │ └── shutdown.rs ├── scripts ├── build.release.sh ├── check_crate_version.sh ├── tests.avalanchego-byzantine.sh ├── tests.avalanchego-conformance.sh ├── tests.avalanchego-e2e.sh ├── tests.fuzz.sh ├── tests.lint.sh ├── tests.unit.sh └── tests.unused.sh └── tests ├── avalanche-e2e ├── Cargo.toml ├── LICENSE ├── README.md └── src │ ├── c │ ├── mod.rs │ └── simple_transfers.rs │ ├── command.rs │ ├── common │ └── mod.rs │ ├── default_spec.rs │ ├── flags.rs │ ├── logs.rs │ ├── main.rs │ ├── p │ ├── mod.rs │ └── transfer.rs │ ├── spec.rs │ └── x │ ├── byzantine │ ├── conflicting_parallel_transfers.rs │ ├── conflicting_transfers.rs │ └── mod.rs │ ├── exports.rs │ ├── mod.rs │ └── simple_transfers.rs ├── avalanchego-byzantine ├── Cargo.toml ├── LICENSE └── src │ ├── lib.rs │ └── tests │ └── mod.rs └── avalanchego-conformance ├── Cargo.toml ├── LICENSE └── src ├── lib.rs └── tests ├── key ├── bls.rs ├── certificates.rs ├── mod.rs └── secp256k1.rs ├── message ├── accepted.rs ├── accepted_frontier.rs ├── accepted_state_summary.rs ├── ancestors.rs ├── app.rs ├── chits.rs ├── get_put.rs ├── mod.rs ├── peerlist.rs ├── ping_pong.rs ├── pull_query.rs ├── push_query.rs ├── state_summary_frontier.rs └── version.rs ├── mod.rs └── packer ├── build_vertex.rs └── mod.rs /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .cache 3 | target 4 | *.md -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners 2 | 3 | * @exdx @gyuho @hexfusion @richardpringle 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "05:00" 8 | timezone: America/Los_Angeles 9 | open-pull-requests-limit: 10 10 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: publish 2 | 3 | on: 4 | workflow_dispatch: 5 | release: 6 | types: [published] 7 | 8 | jobs: 9 | publish-avalanche-types-crate: 10 | name: publish-avalanche-types 11 | runs-on: ubuntu-latest 12 | if: "startsWith(github.event.release.tag_name, 'avalanche-types-v')" 13 | steps: 14 | - uses: actions/checkout@v1 15 | - uses: dtolnay/rust-toolchain@stable 16 | - name: publish avalanche-types crate 17 | shell: bash 18 | run: | 19 | cargo login ${{ secrets.CARGO_TOKEN }} 20 | cargo publish -p avalanche-types 21 | publish-avalanche-consensus-crate: 22 | name: publish-avalanche-consensus 23 | runs-on: ubuntu-latest 24 | if: "startsWith(github.event.release.tag_name, 'avalanche-consensus-v')" 25 | steps: 26 | - uses: actions/checkout@v1 27 | - uses: dtolnay/rust-toolchain@stable 28 | - name: publish avalanche-consensus crate 29 | shell: bash 30 | run: | 31 | cargo login ${{ secrets.CARGO_TOKEN }} 32 | cargo publish -p avalanche-consensus 33 | 34 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "avalanche-types-v*.*.*" 7 | - "avalanche-consensus-v*.*.*" 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | - name: Release 16 | uses: softprops/action-gh-release@v1 17 | with: 18 | draft: true 19 | generate_release_notes: true 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # created by docker-desktop 2 | compose-dev.yaml 3 | 4 | # Generated by Cargo 5 | # will have compiled files and executables 6 | target/ 7 | 8 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 9 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 10 | Cargo.lock 11 | 12 | # These are backup files generated by rustfmt 13 | **/*.rs.bk 14 | 15 | # for "cross build" outputs 16 | /release 17 | 18 | .DS_Store 19 | .vscode 20 | .idea 21 | -------------------------------------------------------------------------------- /.rustfmt.nightly.toml: -------------------------------------------------------------------------------- 1 | # ref. https://github.com/rust-lang/rustfmt/blob/master/Configurations.md 2 | binop_separator = "Back" 3 | blank_lines_lower_bound = 0 4 | blank_lines_upper_bound = 1 5 | brace_style = "SameLineWhere" 6 | color = "Auto" 7 | combine_control_expr = true 8 | comment_width = 80 9 | condense_wildcard_suffixes = true 10 | control_brace_style = "AlwaysSameLine" 11 | edition = "2021" 12 | empty_item_single_line = true 13 | enum_discrim_align_threshold = 20 14 | error_on_line_overflow = true 15 | error_on_unformatted = false 16 | fn_args_layout = "Tall" 17 | fn_call_width = 60 18 | fn_single_line = false 19 | force_explicit_abi = true 20 | force_multiline_blocks = false 21 | format_code_in_doc_comments = true 22 | format_generated_files = true 23 | format_macro_bodies = true 24 | format_macro_matchers = true 25 | format_strings = true 26 | hard_tabs = false 27 | imports_granularity = "Crate" 28 | imports_indent = "Block" 29 | imports_layout = "Mixed" 30 | indent_style = "Block" 31 | max_width = 100 32 | normalize_doc_attributes = true 33 | reorder_imports = true 34 | trailing_comma = "Vertical" 35 | trailing_semicolon = true 36 | unstable_features = true 37 | use_field_init_shorthand = true 38 | use_small_heuristics = "Off" 39 | use_try_shorthand = true 40 | where_single_line = false 41 | wrap_comments = true -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "avalanchego-conformance-sdk", 4 | "core/cert-manager", 5 | "core/network", 6 | "core/server", 7 | "crates/avalanche-consensus", 8 | "crates/avalanche-types", 9 | "tests/avalanche-e2e", 10 | "tests/avalanchego-byzantine", 11 | "tests/avalanchego-conformance", 12 | ] 13 | # by default, only document and build key library crates 14 | default-members = ["crates/avalanche-types", "crates/avalanche-consensus"] 15 | resolver = "2" 16 | 17 | [workspace.lints.clippy] 18 | # suspicious = "deny" 19 | # style = "deny" 20 | # complexity = "deny" 21 | # perf = "deny" 22 | # pedantic = "deny" 23 | # restriction = "deny" 24 | # nursery = "deny" 25 | # cargo = "deny" 26 | 27 | [workspace.package] 28 | version = "0.1.1" 29 | authors = ["gyuho", "hexfusion", "exdx", "richardpringle"] 30 | description = "A collection of Avalanche-specific Rust crates" 31 | license-file = "LICENSE" 32 | readme = "README.md" 33 | homepage = "https://www.avax.network/" 34 | -------------------------------------------------------------------------------- /avalanchego-conformance-sdk/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "avalanchego-conformance-sdk" 3 | version = "0.0.0" 4 | edition = "2021" 5 | rust-version = "1.70" # use "rustup override set stable" to overwrite current toolchain 6 | publish = false 7 | description = "avalanchego-conformance-sdk in Rust" 8 | license-file = "LICENSE" 9 | homepage = "https://avax.network" 10 | repository = "https://github.com/ava-labs/avalanchego-conformance-sdk" 11 | 12 | [dependencies] 13 | log = "0.4.20" 14 | prost = "0.12.1" 15 | tokio = { version = "1.33.0", features = ["fs", "rt-multi-thread", "macros"] } 16 | tokio-stream = { version = "0.1.14", features = ["net"] } 17 | tonic = "0.11.0" 18 | 19 | [build-dependencies] 20 | # ref. https://github.com/hyperium/tonic/tags 21 | # ref. https://github.com/hyperium/tonic/tree/master/tonic-build 22 | tonic-build = "0.11.0" 23 | 24 | [dev-dependencies] 25 | env_logger = "0.11.1" 26 | -------------------------------------------------------------------------------- /avalanchego-conformance-sdk/build.rs: -------------------------------------------------------------------------------- 1 | /// ref. 2 | fn main() { 3 | tonic_build::configure() 4 | .build_server(false) 5 | .build_client(true) 6 | .compile( 7 | &[ 8 | "../avalanchego-conformance/rpcpb/key.proto", 9 | "../avalanchego-conformance/rpcpb/message.proto", 10 | "../avalanchego-conformance/rpcpb/packer.proto", 11 | "../avalanchego-conformance/rpcpb/ping.proto", 12 | ], 13 | &["../avalanchego-conformance/rpcpb"], 14 | ) 15 | .unwrap(); 16 | } 17 | -------------------------------------------------------------------------------- /avalanchego-conformance-sdk/examples/ping_service.rs: -------------------------------------------------------------------------------- 1 | use std::env::args; 2 | 3 | use avalanchego_conformance_sdk::Client; 4 | use tokio::runtime::Runtime; 5 | 6 | /// cargo run --example ping_service -- [HTTP RPC ENDPOINT] 7 | /// cargo run --example ping_service -- http://127.0.0.1:22342 8 | fn main() { 9 | // ref. 10 | env_logger::init_from_env( 11 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 12 | ); 13 | 14 | let url = args().nth(1).expect("no url given"); 15 | let rt = Runtime::new().unwrap(); 16 | 17 | log::info!("creating client"); 18 | let cli = rt.block_on(Client::new(&url)); 19 | 20 | let resp = rt 21 | .block_on(cli.ping_service()) 22 | .expect("failed ping_service"); 23 | log::info!("ping_service response: {:?}", resp); 24 | } 25 | -------------------------------------------------------------------------------- /avalanchego-conformance-sdk/scripts/build.release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xue 3 | 4 | if ! [[ "$0" =~ scripts/build.release.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | cargo build --release 10 | -------------------------------------------------------------------------------- /avalanchego-conformance/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /avalanchego-conformance/README.md: -------------------------------------------------------------------------------- 1 | # avalanche-conformance 2 | 3 | avalanche-conformance is a tool used to ensure code is compatible with avalanchego. The tool performs byte level 4 | checking for the avalanchego codec as well as key generations. The code is run against a live avalanchego node. 5 | 6 | avalanche-conformance is a gRPC server that accepts client connections on a configurable port. A client library is also 7 | provided. 8 | 9 | ## Usage 10 | 11 | ```bash 12 | go install -v ./cmd/avalanchego-conformance 13 | avalanchego-conformance server \ 14 | --port 9090 \ 15 | --grpc-gateway-port 9091 16 | ``` 17 | 18 | The following gRPC messages are implemented by the gRPC server: 19 | 20 | Keys 21 | * CertificateToNodeId 22 | * Secp256K1RecoverHashPublicKey 23 | * Secp256K1Info 24 | * BlsSignature 25 | 26 | Node Messages 27 | * AcceptedFrontier 28 | * AcceptedStateSummary 29 | * Accepted 30 | * Ancestors 31 | * AppGossip 32 | * AppRequest 33 | * AppResponse 34 | * Chits 35 | * GetAcceptedFrontier 36 | * GetAcceptedStateSummary 37 | * GetAccepted 38 | * GetAncestors 39 | * GetStateSummaryFrontier 40 | * Get 41 | * Peerlist 42 | * Ping 43 | * Pong 44 | * PullQuery 45 | * PushQuery 46 | * Put 47 | * StateSummaryFrontier 48 | * Version 49 | 50 | Vertex Messages 51 | * BuildVertex 52 | 53 | Server Messages 54 | * PingService -------------------------------------------------------------------------------- /avalanchego-conformance/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: go 4 | out: . 5 | opt: paths=source_relative 6 | - name: go-grpc 7 | out: . 8 | opt: paths=source_relative 9 | -------------------------------------------------------------------------------- /avalanchego-conformance/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: googleapis 6 | repository: googleapis 7 | commit: 28151c0d0a1641bf938a7672c500e01d 8 | digest: shake256:49215edf8ef57f7863004539deff8834cfb2195113f0b890dd1f67815d9353e28e668019165b9d872395871eeafcbab3ccfdb2b5f11734d3cca95be9e8d139de 9 | -------------------------------------------------------------------------------- /avalanchego-conformance/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | deps: 3 | - buf.build/googleapis/googleapis 4 | breaking: 5 | use: 6 | - FILE 7 | lint: 8 | use: 9 | - DEFAULT 10 | except: 11 | - PACKAGE_VERSION_SUFFIX 12 | -------------------------------------------------------------------------------- /avalanchego-conformance/client/client.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved. 2 | // See the file LICENSE for licensing terms. 3 | 4 | // Package client implements client. 5 | package client 6 | 7 | import ( 8 | "context" 9 | "sync" 10 | "time" 11 | 12 | "github.com/ava-labs/avalanche-rs/avalanchego-conformance/pkg/color" 13 | "github.com/ava-labs/avalanche-rs/avalanchego-conformance/pkg/logutil" 14 | "github.com/ava-labs/avalanche-rs/avalanchego-conformance/rpcpb" 15 | "go.uber.org/zap" 16 | "google.golang.org/grpc" 17 | "google.golang.org/grpc/credentials/insecure" 18 | ) 19 | 20 | type Config struct { 21 | LogLevel string 22 | Endpoint string 23 | DialTimeout time.Duration 24 | } 25 | 26 | type Client interface { 27 | PingService(ctx context.Context) (*rpcpb.PingServiceResponse, error) 28 | Close() error 29 | } 30 | 31 | type client struct { 32 | cfg Config 33 | 34 | conn *grpc.ClientConn 35 | 36 | pingc rpcpb.PingServiceClient 37 | 38 | closed chan struct{} 39 | closeOnce sync.Once 40 | } 41 | 42 | func New(cfg Config) (Client, error) { 43 | lcfg := logutil.GetDefaultZapLoggerConfig() 44 | lcfg.Level = zap.NewAtomicLevelAt(logutil.ConvertToZapLevel(cfg.LogLevel)) 45 | logger, err := lcfg.Build() 46 | if err != nil { 47 | return nil, err 48 | } 49 | _ = zap.ReplaceGlobals(logger) 50 | 51 | color.Outf("{{blue}}dialing endpoint %q{{/}}\n", cfg.Endpoint) 52 | ctx, cancel := context.WithTimeout(context.Background(), cfg.DialTimeout) 53 | conn, err := grpc.DialContext( 54 | ctx, 55 | cfg.Endpoint, 56 | grpc.WithBlock(), 57 | grpc.WithTransportCredentials(insecure.NewCredentials()), 58 | ) 59 | cancel() 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | return &client{ 65 | cfg: cfg, 66 | conn: conn, 67 | pingc: rpcpb.NewPingServiceClient(conn), 68 | closed: make(chan struct{}), 69 | }, nil 70 | } 71 | 72 | func (c *client) PingService(ctx context.Context) (*rpcpb.PingServiceResponse, error) { 73 | zap.L().Info("ping service") 74 | 75 | // ref. https://grpc-ecosystem.github.io/grpc-gateway/docs/tutorials/adding_annotations/ 76 | // curl -X POST -k http://localhost:8081/v1/ping-service -d '' 77 | return c.pingc.PingService(ctx, &rpcpb.PingServiceRequest{}) 78 | } 79 | 80 | func (c *client) Close() error { 81 | c.closeOnce.Do(func() { 82 | close(c.closed) 83 | }) 84 | return c.conn.Close() 85 | } 86 | -------------------------------------------------------------------------------- /avalanchego-conformance/cmd/avalanchego-conformance/main.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved. 2 | // See the file LICENSE for licensing terms. 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "os" 9 | 10 | "github.com/ava-labs/avalanche-rs/avalanchego-conformance/cmd/avalanchego-conformance/server" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | var rootCmd = &cobra.Command{ 15 | Use: "avalanchego-conformance", 16 | Short: "avalanchego-conformance commands", 17 | SuggestFor: []string{"avalanche-conformance"}, 18 | } 19 | 20 | func init() { 21 | cobra.EnablePrefixMatching = true 22 | } 23 | 24 | func init() { 25 | rootCmd.AddCommand( 26 | server.NewCommand(), 27 | ) 28 | } 29 | 30 | func main() { 31 | if err := rootCmd.Execute(); err != nil { 32 | fmt.Fprintf(os.Stderr, "avalanchego-conformance failed %v\n", err) 33 | os.Exit(1) 34 | } 35 | os.Exit(0) 36 | } 37 | -------------------------------------------------------------------------------- /avalanchego-conformance/cmd/avalanchego-conformance/server/server.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved. 2 | // See the file LICENSE for licensing terms. 3 | 4 | package server 5 | 6 | import ( 7 | "context" 8 | "log" 9 | "os" 10 | "os/signal" 11 | "syscall" 12 | "time" 13 | 14 | "github.com/ava-labs/avalanche-rs/avalanchego-conformance/pkg/logutil" 15 | "github.com/ava-labs/avalanche-rs/avalanchego-conformance/server" 16 | "github.com/spf13/cobra" 17 | "go.uber.org/zap" 18 | ) 19 | 20 | func init() { 21 | cobra.EnablePrefixMatching = true 22 | } 23 | 24 | var ( 25 | logLevel string 26 | port uint16 27 | gwPort uint16 28 | dialTimeout time.Duration 29 | ) 30 | 31 | func NewCommand() *cobra.Command { 32 | cmd := &cobra.Command{ 33 | Use: "server [options]", 34 | Short: "Start a network runner server.", 35 | RunE: serverFunc, 36 | } 37 | 38 | cmd.PersistentFlags().StringVar(&logLevel, "log-level", logutil.DefaultLogLevel, "log level") 39 | cmd.PersistentFlags().Uint16Var(&port, "port", 9090, "server port") 40 | cmd.PersistentFlags().Uint16Var(&gwPort, "grpc-gateway-port", 9091, "grpc-gateway server port") 41 | cmd.PersistentFlags().DurationVar(&dialTimeout, "dial-timeout", 10*time.Second, "server dial timeout") 42 | 43 | return cmd 44 | } 45 | 46 | func serverFunc(cmd *cobra.Command, args []string) (err error) { 47 | lcfg := logutil.GetDefaultZapLoggerConfig() 48 | lcfg.Level = zap.NewAtomicLevelAt(logutil.ConvertToZapLevel(logLevel)) 49 | logger, err := lcfg.Build() 50 | if err != nil { 51 | log.Fatalf("failed to build global logger, %v", err) 52 | } 53 | _ = zap.ReplaceGlobals(logger) 54 | 55 | s, err := server.New(server.Config{ 56 | Port: port, 57 | GwPort: gwPort, 58 | DialTimeout: dialTimeout, 59 | }) 60 | if err != nil { 61 | return err 62 | } 63 | 64 | rootCtx, rootCancel := context.WithCancel(context.Background()) 65 | errc := make(chan error) 66 | go func() { 67 | errc <- s.Run(rootCtx) 68 | }() 69 | 70 | sigc := make(chan os.Signal, 1) 71 | signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM) 72 | select { 73 | case sig := <-sigc: 74 | zap.L().Warn("signal received; closing server", zap.String("signal", sig.String())) 75 | rootCancel() 76 | zap.L().Warn("closed server", zap.Error(<-errc)) 77 | case err = <-errc: 78 | zap.L().Warn("server closed", zap.Error(err)) 79 | rootCancel() 80 | } 81 | return err 82 | } 83 | -------------------------------------------------------------------------------- /avalanchego-conformance/pkg/color/color.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved. 2 | // See the file LICENSE for licensing terms. 3 | 4 | package color 5 | 6 | import ( 7 | "fmt" 8 | 9 | formatter "github.com/onsi/ginkgo/v2/formatter" 10 | ) 11 | 12 | // Outputs to stdout. 13 | // 14 | // e.g., 15 | // Out("{{green}}{{bold}}hi there %q{{/}}", "aa") 16 | // Out("{{magenta}}{{bold}}hi therea{{/}} {{cyan}}{{underline}}b{{/}}") 17 | // 18 | // ref. 19 | // https://github.com/onsi/ginkgo/blob/v2.0.0/formatter/formatter.go#L52-L73 20 | // 21 | func Outf(format string, args ...interface{}) { 22 | s := formatter.F(format, args...) 23 | fmt.Fprint(formatter.ColorableStdOut, s) 24 | } 25 | 26 | // Outputs to stderr. 27 | func Errf(format string, args ...interface{}) { 28 | s := formatter.F(format, args...) 29 | fmt.Fprint(formatter.ColorableStdErr, s) 30 | } 31 | 32 | func Greenf(format string, args ...interface{}) { 33 | f := fmt.Sprintf("{{green}}%s{{/}}", format) 34 | Outf(f, args...) 35 | } 36 | 37 | func Redf(format string, args ...interface{}) { 38 | f := fmt.Sprintf("{{red}}%s{{/}}", format) 39 | Outf(f, args...) 40 | } 41 | 42 | func Bluef(format string, args ...interface{}) { 43 | f := fmt.Sprintf("{{blue}}%s{{/}}", format) 44 | Outf(f, args...) 45 | } 46 | -------------------------------------------------------------------------------- /avalanchego-conformance/pkg/logutil/zap.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved. 2 | // See the file LICENSE for licensing terms. 3 | 4 | // Package logutil implements various log utilities. 5 | package logutil 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | 11 | "go.uber.org/zap" 12 | "go.uber.org/zap/zapcore" 13 | ) 14 | 15 | func init() { 16 | logger, err := GetDefaultZapLogger() 17 | if err != nil { 18 | log.Fatalf("Failed to initialize global logger, %v", err) 19 | } 20 | _ = zap.ReplaceGlobals(logger) 21 | } 22 | 23 | // GetDefaultZapLoggerConfig returns a new default zap logger configuration. 24 | func GetDefaultZapLoggerConfig() zap.Config { 25 | return zap.Config{ 26 | Level: zap.NewAtomicLevelAt(ConvertToZapLevel(DefaultLogLevel)), 27 | 28 | Development: false, 29 | Sampling: &zap.SamplingConfig{ 30 | Initial: 100, 31 | Thereafter: 100, 32 | }, 33 | 34 | Encoding: "json", 35 | 36 | // copied from "zap.NewProductionEncoderConfig" with some updates 37 | EncoderConfig: zapcore.EncoderConfig{ 38 | TimeKey: "ts", 39 | LevelKey: "level", 40 | NameKey: "logger", 41 | CallerKey: "caller", 42 | MessageKey: "msg", 43 | StacktraceKey: "stacktrace", 44 | LineEnding: zapcore.DefaultLineEnding, 45 | EncodeLevel: zapcore.LowercaseLevelEncoder, 46 | EncodeTime: zapcore.ISO8601TimeEncoder, 47 | EncodeDuration: zapcore.StringDurationEncoder, 48 | EncodeCaller: zapcore.ShortCallerEncoder, 49 | }, 50 | 51 | // Use "/dev/null" to discard all 52 | OutputPaths: []string{"stderr"}, 53 | ErrorOutputPaths: []string{"stderr"}, 54 | } 55 | } 56 | 57 | // GetDefaultZapLogger returns a new default logger. 58 | func GetDefaultZapLogger() (*zap.Logger, error) { 59 | lcfg := GetDefaultZapLoggerConfig() 60 | return lcfg.Build() 61 | } 62 | 63 | // DefaultLogLevel is the default log level. 64 | var DefaultLogLevel = "info" 65 | 66 | // ConvertToZapLevel converts log level string to zapcore.Level. 67 | func ConvertToZapLevel(lvl string) zapcore.Level { 68 | switch lvl { 69 | case "debug": 70 | return zap.DebugLevel 71 | case "info": 72 | return zap.InfoLevel 73 | case "warn": 74 | return zap.WarnLevel 75 | case "error": 76 | return zap.ErrorLevel 77 | case "dpanic": 78 | return zap.DPanicLevel 79 | case "panic": 80 | return zap.PanicLevel 81 | case "fatal": 82 | return zap.FatalLevel 83 | default: 84 | panic(fmt.Sprintf("unknown level %q", lvl)) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /avalanchego-conformance/rpcpb/key.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/ava-labs/avalanche-rs/avalanchego-conformance;rpcpb"; 4 | 5 | package rpcpb; 6 | 7 | service KeyService { 8 | rpc CertificateToNodeId(CertificateToNodeIdRequest) returns (CertificateToNodeIdResponse) { 9 | } 10 | 11 | rpc Secp256k1RecoverHashPublicKey(Secp256k1RecoverHashPublicKeyRequest) returns (Secp256k1RecoverHashPublicKeyResponse) { 12 | } 13 | 14 | rpc Secp256k1Info(Secp256k1InfoRequest) returns (Secp256k1InfoResponse) { 15 | } 16 | 17 | rpc BlsSignature(BlsSignatureRequest) returns (BlsSignatureResponse) { 18 | } 19 | } 20 | 21 | message CertificateToNodeIdRequest { 22 | bytes certificate = 1; 23 | bytes node_id = 2; 24 | } 25 | 26 | message CertificateToNodeIdResponse { 27 | bytes expected_node_id = 1; 28 | string message = 2; 29 | bool success = 3; 30 | } 31 | 32 | message Secp256k1RecoverHashPublicKeyRequest { 33 | bytes message = 1; 34 | bytes signature = 2; 35 | string public_key_short_id_cb58 = 3; 36 | } 37 | 38 | message Secp256k1RecoverHashPublicKeyResponse { 39 | string expected_public_key_short_id_cb58 = 1; 40 | string message = 2; 41 | bool success = 3; 42 | } 43 | 44 | message Secp256k1InfoRequest { 45 | Secp256k1Info secp256k1_info = 1; 46 | } 47 | 48 | message Secp256k1InfoResponse { 49 | Secp256k1Info expected_secp256k1_info = 1; 50 | string message = 2; 51 | bool success = 3; 52 | } 53 | 54 | message Secp256k1Info { 55 | string key_type = 1; 56 | 57 | string private_key_cb58 = 2; 58 | string private_key_hex = 3; 59 | 60 | // Map from network ID to its chain addresses. 61 | map chain_addresses = 4; 62 | 63 | string short_address = 5; 64 | string eth_address = 6; 65 | } 66 | 67 | message ChainAddresses { 68 | string x = 1; 69 | string p = 2; 70 | } 71 | 72 | message BlsSignatureRequest { 73 | bytes private_key = 1; 74 | bytes public_key = 2; 75 | bytes message = 3; 76 | bytes signature = 4; 77 | bytes signature_proof_of_possession = 5; 78 | } 79 | 80 | message BlsSignatureResponse { 81 | string message = 1; 82 | bool success = 2; 83 | } 84 | -------------------------------------------------------------------------------- /avalanchego-conformance/rpcpb/packer.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/ava-labs/avalanche-rs/avalanchego-conformance;rpcpb"; 4 | 5 | package rpcpb; 6 | 7 | service PackerService { 8 | rpc BuildVertex(BuildVertexRequest) returns (BuildVertexResponse) { 9 | } 10 | } 11 | 12 | message BuildVertexRequest { 13 | uint32 codec_version = 1; 14 | bytes chain_id = 2; 15 | uint64 height = 3; 16 | uint32 epoch = 4; 17 | repeated bytes parent_ids = 5; 18 | repeated bytes txs = 6; 19 | 20 | bytes vtx_bytes = 7; 21 | } 22 | 23 | message BuildVertexResponse { 24 | bytes expected_bytes = 1; 25 | string message = 2; 26 | bool success = 3; 27 | } 28 | -------------------------------------------------------------------------------- /avalanchego-conformance/rpcpb/ping.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/ava-labs/avalanche-rs/avalanchego-conformance;rpcpb"; 4 | 5 | package rpcpb; 6 | 7 | service PingService { 8 | rpc PingService(PingServiceRequest) returns (PingServiceResponse) { 9 | } 10 | } 11 | 12 | message PingServiceRequest {} 13 | 14 | message PingServiceResponse { 15 | int32 pid = 1; 16 | } 17 | -------------------------------------------------------------------------------- /avalanchego-conformance/scripts/genproto.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | if ! [[ "$0" =~ scripts/genproto.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | go install -v google.golang.org/protobuf/cmd/protoc-gen-go@latest 10 | go install -v github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest 11 | go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest 12 | 13 | # https://docs.buf.build/installation 14 | # https://grpc-ecosystem.github.io/grpc-gateway/docs/tutorials/introduction/ 15 | buf lint 16 | buf generate 17 | 18 | echo "ALL SUCCESS" 19 | -------------------------------------------------------------------------------- /avalanchego-conformance/scripts/updatedep.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | if ! [[ "$0" =~ scripts/updatedep.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | # TODO: automatically bump up dependencies 10 | go mod tidy -v 11 | -------------------------------------------------------------------------------- /avalanchego-conformance/server/packer.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved. 2 | // See the file LICENSE for licensing terms. 3 | 4 | package server 5 | 6 | import ( 7 | "bytes" 8 | "context" 9 | "fmt" 10 | 11 | "github.com/ava-labs/avalanche-rs/avalanchego-conformance/rpcpb" 12 | "github.com/ava-labs/avalanchego/ids" 13 | "github.com/ava-labs/avalanchego/snow/engine/avalanche/vertex" 14 | "go.uber.org/zap" 15 | ) 16 | 17 | func (s *server) BuildVertex(ctx context.Context, req *rpcpb.BuildVertexRequest) (*rpcpb.BuildVertexResponse, error) { 18 | zap.L().Info("received BuildVertex request") 19 | 20 | chainID, err := ids.ToID(req.ChainId) 21 | if err != nil { 22 | return nil, err 23 | } 24 | parentIDs := make([]ids.ID, 0, len(req.ParentIds)) 25 | for _, b := range req.ParentIds { 26 | parentID, err := ids.ToID(b) 27 | if err != nil { 28 | return nil, err 29 | } 30 | parentIDs = append(parentIDs, parentID) 31 | } 32 | 33 | vtx, err := vertex.Build(chainID, req.Height, parentIDs, req.Txs) 34 | if err != nil { 35 | return nil, err 36 | } 37 | expectedVtxBytes := vtx.Bytes() 38 | 39 | resp := &rpcpb.BuildVertexResponse{ 40 | ExpectedBytes: expectedVtxBytes, 41 | Success: true, 42 | } 43 | if !bytes.Equal(req.VtxBytes, expectedVtxBytes) { 44 | resp.Message = fmt.Sprintf("expected 0x%x", expectedVtxBytes) 45 | resp.Success = false 46 | } 47 | 48 | return resp, nil 49 | } 50 | -------------------------------------------------------------------------------- /core/cert-manager/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cert-manager" 3 | version = "0.0.11" # https://crates.io/crates/cert-manager 4 | 5 | edition = "2021" 6 | rust-version = "1.69" 7 | publish = true 8 | description = "Cert manager in Rust" 9 | # copied-from: 10 | repository = "https://github.com/gyuho/cert-manager" 11 | readme = "README.md" 12 | license = "Apache-2.0" 13 | 14 | [dependencies] 15 | log = "0.4.20" 16 | rand = "0.8.5" 17 | random-manager = "0.0.5" # https://crates.io/crates/random-manager/versions 18 | rcgen = { version = "0.12.1", features = ["pem", "x509-parser"] } 19 | rsa = { version = "0.9.2", features = ["pem"] } # https://crates.io/crates/rsa 20 | rustls = "0.22.2" 21 | rustls-pemfile = "2.0.0" 22 | x509-parser = "0.16.0" 23 | 24 | [dev-dependencies] 25 | env_logger = "0.11.2" 26 | tempfile = "3.5.0" 27 | 28 | [package.metadata.cargo-udeps.ignore] 29 | normal = ["rsa"] 30 | -------------------------------------------------------------------------------- /core/cert-manager/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod x509; 2 | -------------------------------------------------------------------------------- /core/network/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "network" 3 | version = "0.0.1" 4 | edition = "2021" 5 | rust-version = "1.70" # use "rustup override set stable" to overwrite current toolchain 6 | publish = false 7 | description = "Avalanche network" 8 | license-file = "LICENSE" 9 | homepage = "https://avax.network" 10 | repository = "https://github.com/ava-labs/avalanche-rs/tree/main/core/network" 11 | readme = "README.md" 12 | 13 | [dependencies] 14 | avalanche-types = { path = "../../crates/avalanche-types", features = ["message"] } 15 | log = "0.4.20" 16 | rustls = { version = "0.22.2", features = ["logging"] } 17 | hyper-rustls = "0.26.0" 18 | rustls-native-certs = "0.7.0" 19 | hyper = { version = "0.14.27", features = ["full"], optional = true } 20 | tokio-rustls = { version = "0.25.0", optional = true } 21 | rand = "0.8.5" 22 | random-manager = "0.0.5" # https://crates.io/crates/random-manager/versions 23 | rcgen = { version = "0.12.1", features = ["pem", "x509-parser"] } 24 | rsa = { version = "0.9.2", features = ["pem"] } # https://crates.io/crates/rsa 25 | rustls-pemfile = "2.0.0" 26 | x509-parser = "0.16.0" 27 | # for feature "pem" 28 | pem = { version = "3.0.0", optional = true } # https://github.com/jcreekmore/pem-rs 29 | cert-manager = { path = "../../core/cert-manager" } 30 | 31 | [dev-dependencies] 32 | env_logger = "0.11.1" 33 | random-manager = "0.0.5" 34 | tempfile = "3.5.0" 35 | tokio = { version = "1.32.0", features = ["full"] } 36 | tracing = "0.1.37" 37 | tracing-subscriber = "0.3.17" 38 | 39 | [features] 40 | default = ["rustls", "pem_encoding"] 41 | rustls = ["hyper", "tokio-rustls"] 42 | pem_encoding = ["pem"] 43 | 44 | [[example]] 45 | name = "peer_outbound_ping" 46 | required-features = ["rustls", "pem_encoding"] 47 | 48 | [package.metadata.cargo-udeps.ignore] 49 | normal = ["hyper", "tokio-rustls"] 50 | -------------------------------------------------------------------------------- /core/network/README.md: -------------------------------------------------------------------------------- 1 | # core/network 2 | 3 | A library for building p2p inbound and outbound connections for an Avalanche client. 4 | -------------------------------------------------------------------------------- /core/network/examples/peer_outbound_ping.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | env::args, 3 | io, 4 | net::{IpAddr, SocketAddr}, 5 | str::FromStr, 6 | time::Duration, 7 | }; 8 | 9 | use avalanche_types::message; 10 | use network::peer::outbound; 11 | 12 | /// cargo run --example peer_outbound_ping -- [PEER IP] [STAKING PORT] 13 | /// cargo run --example peer_outbound_ping -- 34.222.2.60 9651 14 | /// cargo run --example peer_outbound_ping -- 35.167.53.168 9651 15 | /// cargo run --example peer_outbound_ping -- 52.43.89.51 9651 16 | /// cargo run --example peer_outbound_ping -- 35.89.110.175 9651 17 | /// NOTE: just pick random node/IP from https://github.com/ava-labs/avalanchego/blob/master/genesis/bootstrappers.json 18 | fn main() -> io::Result<()> { 19 | // ref. 20 | env_logger::init_from_env( 21 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 22 | ); 23 | 24 | let peer_ip = args().nth(1).expect("no peer IP given"); 25 | let peer_ip = IpAddr::from_str(&peer_ip).expect("invalid peer IP"); 26 | 27 | let port = args().nth(2).expect("no port given"); 28 | let port: u16 = port.parse().unwrap(); 29 | 30 | let addr = SocketAddr::new(peer_ip, port); 31 | 32 | let key_path = random_manager::tmp_path(10, Some(".key")).unwrap(); 33 | let cert_path = random_manager::tmp_path(10, Some(".cert")).unwrap(); 34 | cert_manager::x509::generate_and_write_pem(None, &key_path, &cert_path)?; 35 | 36 | let connector = outbound::Connector::new_from_pem(&key_path, &cert_path)?; 37 | let mut stream = connector.connect(addr, Duration::from_secs(10))?; 38 | log::info!("peer certificate:\n\n{}", stream.peer_certificate_pem); 39 | 40 | log::info!("sending ping..."); 41 | let ping_msg = message::ping::Message::default(); 42 | let ping_msg_bytes = ping_msg.serialize()?; 43 | stream.write(&ping_msg_bytes)?; 44 | stream.close()?; 45 | 46 | Ok(()) 47 | } 48 | -------------------------------------------------------------------------------- /core/network/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A library for building p2p inbound and outbound connections. 2 | pub mod peer; 3 | -------------------------------------------------------------------------------- /core/server/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /core/server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "server" 3 | version = "0.0.1" 4 | edition = "2021" 5 | rust-version = "1.70" # use "rustup override set stable" to overwrite current toolchain 6 | publish = false 7 | description = "avalanche-rs server" 8 | license-file = "LICENSE" 9 | homepage = "https://avax.network" 10 | repository = "https://github.com/ava-labs/avalanche-rs/tree/main/core/server" 11 | readme = "README.md" 12 | 13 | [dependencies] 14 | futures = "0.3.28" 15 | http = "0.2.9" 16 | hyper = { version = "0.14.25", features = ["full"] } 17 | log = "0.4.20" 18 | tokio = { version = "1.32.0", features = ["full"] } # https://github.com/tokio-rs/tokio/releases 19 | -------------------------------------------------------------------------------- /core/server/README.md: -------------------------------------------------------------------------------- 1 | # core/server 2 | 3 | A library for building the server portion of a p2p client in Avalanche. 4 | -------------------------------------------------------------------------------- /core/server/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A server handler with various endpoints for avalanche nodes. 2 | pub mod handler; 3 | -------------------------------------------------------------------------------- /crates/avalanche-consensus/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | # https://crates.io/crates/avalanche-consensus/versions 3 | name = "avalanche-consensus" 4 | version = "0.1.1" 5 | edition = "2021" 6 | rust-version = "1.70" # use "rustup override set stable" to overwrite current toolchain 7 | publish = true 8 | description = "Avalanche consensus" 9 | license-file = "LICENSE" 10 | homepage = "https://avax.network" 11 | repository = "https://github.com/ava-labs/avalanche-rs/tree/main/crates/avalanche-consensus" 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [dependencies] 17 | avalanche-types = { version = "0.1.1", path = "../../crates/avalanche-types", features = [] } # https://crates.io/crates/avalanche-types 18 | bytes = "1.4.0" 19 | log = "0.4.20" 20 | serde = { version = "1.0.186", features = ["derive"] } # https://github.com/serde-rs/serde/releases 21 | thiserror = "1.0.47" 22 | 23 | [dev-dependencies] 24 | env_logger = "0.11.1" 25 | 26 | [package.metadata.docs.rs] 27 | cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"] 28 | -------------------------------------------------------------------------------- /crates/avalanche-consensus/README.md: -------------------------------------------------------------------------------- 1 | # Avalanche snowman consensus 2 | 3 | Rust implementation of [`AvalancheGo/snow/consensus`](https://github.com/ava-labs/avalanchego/tree/master/snow/consensus) (including tests). 4 | -------------------------------------------------------------------------------- /crates/avalanche-consensus/src/context.rs: -------------------------------------------------------------------------------- 1 | //! The consensus execution context. 2 | use avalanche_types::ids::{node::Id as NodeId, Id}; 3 | 4 | /// Represents the current execution. 5 | /// ref. 6 | pub struct Context { 7 | network_id: u32, 8 | 9 | subnet_id: Id, 10 | chain_id: Id, 11 | node_id: NodeId, 12 | } 13 | 14 | impl Default for Context { 15 | fn default() -> Self { 16 | Self::new() 17 | } 18 | } 19 | 20 | impl Context { 21 | pub fn new() -> Self { 22 | Self { 23 | network_id: 1, 24 | subnet_id: Id::empty(), 25 | chain_id: Id::empty(), 26 | node_id: NodeId::empty(), 27 | } 28 | } 29 | 30 | pub fn network_id(&self) -> u32 { 31 | self.network_id 32 | } 33 | 34 | pub fn subnet_id(&self) -> Id { 35 | self.subnet_id 36 | } 37 | 38 | pub fn chain_id(&self) -> Id { 39 | self.chain_id 40 | } 41 | 42 | pub fn node_id(&self) -> NodeId { 43 | self.node_id 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /crates/avalanche-consensus/src/snowman/mod.rs: -------------------------------------------------------------------------------- 1 | //! The snowman consensus algorithm. 2 | pub mod block; 3 | pub mod snowball; 4 | pub mod topological; 5 | -------------------------------------------------------------------------------- /crates/avalanche-consensus/src/snowman/snowball/mod.rs: -------------------------------------------------------------------------------- 1 | //! Snowball consensus. 2 | pub mod binary; 3 | pub mod tree; 4 | pub mod unary; 5 | 6 | use avalanche_types::ids::{bag::Bag, Id}; 7 | 8 | /// Represents a node interface for binary trie. 9 | /// ref. "avalanchego/snow/consensus/snowball/tree.go#node" 10 | #[derive(Clone, Debug)] 11 | pub enum Node { 12 | Unary(unary::node::Node), 13 | Binary(binary::node::Node), 14 | } 15 | 16 | impl Node { 17 | /// Returns the preferred choice of this sub-tree. 18 | pub fn preference(&self) -> Id { 19 | match self { 20 | Node::Unary(n) => n.preference(), 21 | Node::Binary(n) => n.preference(), 22 | } 23 | } 24 | 25 | /// Returns the number of assumed decided bits of this node. 26 | /// Patricia trie places into each node the bit index to be tested 27 | /// in order to decide which path to take out of that node. 28 | /// Thus, it can skip directly to the bit where a significant 29 | /// decision is to be made by tracking "decided_prefix". 30 | pub fn decided_prefix(&self) -> i64 { 31 | match self { 32 | Node::Unary(n) => n.decided_prefix(), 33 | Node::Binary(n) => n.decided_prefix(), 34 | } 35 | } 36 | 37 | /// Returns "true" when the consensus has been reached on this node. 38 | pub fn finalized(&self) -> bool { 39 | match self { 40 | Node::Unary(n) => n.finalized(), 41 | Node::Binary(n) => n.finalized(), 42 | } 43 | } 44 | 45 | pub fn add(&mut self, new_choice: &Id) -> Node { 46 | match self { 47 | Node::Unary(n) => n.add(new_choice), 48 | Node::Binary(n) => n.add(new_choice), 49 | } 50 | } 51 | 52 | pub fn record_poll(&mut self, votes: Bag, reset: bool) -> (Node, bool) { 53 | match self { 54 | Node::Unary(n) => n.record_poll(votes, reset), 55 | Node::Binary(n) => n.record_poll(votes, reset), 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /crates/avalanche-consensus/tests.unit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xue 3 | 4 | if ! [[ "$0" =~ tests.unit.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | # uses nextest for faster test runs and better output 10 | # https://github.com/nextest-rs/nextest/tree/main 11 | # local use: cargo install nextest 12 | 13 | RUST_LOG=debug cargo test \ 14 | -p avalanche-consensus 15 | 16 | echo "ALL SUCCESS!" 17 | -------------------------------------------------------------------------------- /crates/avalanche-types/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /crates/avalanche-types/README.md: -------------------------------------------------------------------------------- 1 | # avalanche-types 2 | 3 | ## Introduction 4 | 5 | The `avalanche-types` crate implements and is the canonical representation of Avalanche primitive types in Rust. Avalanche types are separated by modules and are all under the `src` directory. 6 | 7 | This crate also provides an SDK library for developing subnets in Rust. For the SDK functionality, see `src/subnet` which contains everything required to build a subnet VM in Rust. 8 | 9 | The following VMs were built with the SDK: 10 | * Simple Rust VM: [TimestampVM](https://github.com/ava-labs/timestampvm-rs) 11 | * Complex Rust VM: [SpacesVM](https://github.com/ava-labs/spacesvm-rs) 12 | 13 | ## Getting Started 14 | 15 | Examples can be found in [`examples`](./examples) and are a good first step to getting an understanding of general usage. 16 | 17 | ### Resources 18 | 19 | - [How to Build a Simple Rust VM](https://docs.avax.network/subnets/create-a-simple-rust-vm) tutorial provides a basic example of using the Rust SDK. 20 | - [TimestampVM Template](https://github.com/ava-labs/timestampvm-rs-template) allows you to quickly generate a [TimestampVM](https://github.com/ava-labs/timestampvm-rs) based project with [cargo generate](https://cargo-generate.github.io/cargo-generate/) 21 | 22 | ### Rust Version 23 | 24 | This project uses the latest stable Rust toolchain. 25 | 26 | ## Getting Help 27 | 28 | First please try find the answer to your question in the code documentation. If more clarification is required, try opening an [issue] with the question. 29 | 30 | [issue]: https://github.com/ava-labs/avalanche-rs/issues/new 31 | 32 | ## Features 33 | 34 | - Ids (e.g., [`src/ids`](./src/ids)) 35 | - Transaction types/serialization (e.g., [`src/platformvm/txs`](./src/platformvm/txs)) 36 | - Certificates (e.g., [`src/key/cert`](./src/key/cert)) 37 | - Keys and addresses (e.g., [`src/key/secp256k1`](./src/key/secp256k1)) 38 | - Peer-to-peer messages (e.g., [`src/message`](./src/message)) 39 | - RPC chain VM (e.g., [`src/subnet/rpc`](./src/subnet/rpc)) 40 | - Genesis generate helper (e.g., [`src/subnet_evm`](./src/subnet_evm)) 41 | - Protobuf generated stubs and helpers (e.g., [`src/proto`](./src/proto)) 42 | - AvalancheGo APIs (e.g., [`/src/avalanchego`](./src/avalanchego)) 43 | 44 | The basic types available in this crate are used in other Avalanche Rust projects (e.g., distributed load tester [`blizzard`](https://talks.gyuho.dev/distributed-load-generator-avalanche-2022.html), [`avalanche-ops`](https://github.com/ava-labs/avalanche-ops)). 45 | -------------------------------------------------------------------------------- /crates/avalanche-types/artifacts/staker1.insecure.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV 3 | UzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFi 4 | czEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYT 5 | c3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMTVaGA8zMDE5MDcxMDE2 6 | MTIxNVowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFs 7 | YWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC 8 | AQDKYSRw/W0YpYH/MTQhiFrR0m89l6yTuzLpDtjudr/5RnhIPvtqk7YIGm/m9l29 9 | xwR4J5r7SZGs+70yBetkbS+h7PwJ2rmWDwbrdyJKvVBhqf8kSn+VU2LePSIcJj19 10 | 3LDyWhV1H4lqNkUkcAR76Fh9qjMvA2p0vJ66+eDLXlph/RYapQx9HgOj/0BmAKMr 11 | YCyo5BhRih+Ougg8aK4G9PQTIA5G2wTWW2QkHxM/QppFjZd/XwQeJ2H6ubWMFc5f 12 | ttf6AzpJvFIDBu/JDCKWiCu5m8t4GL8w2OrIx8Js19lF4YYE2eojCreqgPi64S3o 13 | cqwKsDoySTw6/5iKQ5BUYwUXX3z7EXOqD8SMHefUKeczj4WvAaZLzR27qXm55EgR 14 | YQAIX4fhmY7NfSop3Wh0Eo62+JHoM/1g+UgOXlbnWpY95Mgd7/fwDSWLu4IxE0/u 15 | q8VufIbfC4yrY8qlTVfAffI1ldRdvJjPJBPiQ0CNrOl60LVptpkGc9shH7wZ2bP0 16 | bEnYKTgLAfOzD8Ut71O2AOIa80A1GNFl4Yle/MSNJOcQOSpgtWdREzIUoenAjfuz 17 | M4OeTr4cRg4+VYTAo9KHKriN1DuewNzGd8WjKAVHmcIMjqISLTlzMhdsdm+OmfQ6 18 | OvyX7v0GTOBbhP09NGcww5A0gCzXN18FS5oxnxe6OG9D0wIDAQABMA0GCSqGSIb3 19 | DQEBCwUAA4ICAQAqL1TWI1PTMm3JaXkhdTBe8tsk7+FsHAFzTcBVBsB8dkJNGhxb 20 | dlu7XIm+AyGUn0j8siz8qojKbO+rEPV/ImTH5W7Q36rXSdgvNUWpKrKIC5S8PUF5 21 | T4pH+lpYIlQHnTaKMuqH3nO3I40IhEhPaa2wAwy2kDlz46fJcr6aMzj6Zg43J5UK 22 | Zid+BQsiWAUau5V7CpC7GMCx4YdOZWWsT3dAsug9hvwTe81kK1JoTH0juwPTBH0t 23 | xUgUVIWyuweM1UwYF3n8Hmwq6B46YmujhMDKT+3lgqZt7eZ1XvieLdBRlVQWzOa/ 24 | 6QYTkrqwPZioKIStrxVGYjk40qECNodCSCIwRDgbnQubRWrdslxiIyc5blJNuOV+ 25 | jgv5d2EeUpwUjvpZuEV7FqPKGRgiG0jfl6Psms9gYUXd+y3ytG9HeoDNmLTSTBE4 26 | nCQXX935P2/xOuok6CpiGpP89DX7t8yiwk8LFNnY3rvv50nVy8kerVdnfHTmoMZ9 27 | /IBgojSIKov4lmPKdgzFfimzhbssVCa4DO/LIhTF7bQbH1ut/Oq7npdOpMjLYIBE 28 | 9lagvRVTVFwT/uwrCcXHCb21b/puwV94SNXVwt7BheFTFBdtxJrR4jjr2T5odLkX 29 | 6nQcY8V2OT7KOxn0KVc6pl3saJTLmL+H/3CtAao9NtmuUDapKINRSVNyvg== 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /crates/avalanche-types/artifacts/staker2.insecure.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV 3 | UzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFi 4 | czEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYT 5 | c3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMTlaGA8zMDE5MDcxMDE2 6 | MTIxOVowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFs 7 | YWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC 8 | AQDdToR60na6NuR9iSAUMyzPXJNMWVQbLyT5/iZCiJ3BB4YWMBhfxpJWJiWXcM+z 9 | nDgpJuyCEeh5Dp6ZY3Fe7k6Hht6FmFpDjwnjpQmdkEKUg00G+ElPTp/UsmsPL+JA 10 | swPqBZWpMBS3dsXQNunMMtMGlrf5S0l6XX4y7kc/GTxYgveWZ9JtR/m2KNer+wjg 11 | BHqJ4rPqnHB30sDYPZg91Cz1Ak8Bb2w2I108zQVgKK6eIqNKXJJ/4pizSZdU4920 12 | wMxYBpnfDAchnxei9U/v3QbT7eKUI2fGr+hOWTIWU80+VeOBt8a6P4sS9AQh5/6G 13 | 8qwmAqO3YQ9dxN82iu/H3+N+GGa/M0r5rEWrzwIuFhwKvyQcpPRBm2yQnBnhL9G5 14 | kN6n4OBM0KsgZ3CYlHZSg4eWcNgBt1WCFsQc7vfUFaJnr8QP3pF4V/4Bok7wTO5H 15 | N0A1EYEVYuX53NGnrKVe+Fg9+xMOgXPWkUNqdvpI9ZbV3Z0S5866qF3/vBZrhgCr 16 | Kc5E/vMexBRe8Ki4wKqONVhi9WGUcRHvFEikc+7VrPj0YaG6zVLd+uOAJN81fKOP 17 | Yo4X4sZrMyPYl3OjGtMhfV4KvCaLEr1duOklqO6cCvGQ8iAlLVy3VJyW5GJ0D0Ky 18 | iAir4VNdAJKo1ZgiGivJLWulTfjUifCN9o115AiqJxiqwwIDAQABMA0GCSqGSIb3 19 | DQEBCwUAA4ICAQCQOdwD7eRIxBvbQHUc+m0TRzEa17BCfck1Y2WwN3TZXDGSkPVE 20 | 0uujA8SL3qi8/CTLGRqI9U3gRZJf+tJPBF/P021PEmyaFTS4htxcDxTxuZv2jCo9 21 | +XhUEyvRWitTmoy1esq3mkotVQHeTmQvwCsQJAhctVA/hRdJwmMPs1B8QxOUI6Bq 22 | SOBHa9CsXIzVOFv8FqE91PZA2ns30sKQYrrnbH99apfF5WglLUoyPwxf2e3AACh7 23 | beEdk45ivvKwi5Jk8nr85KDHYPlqkr0bd9Ehl8xplaNBdMPeRufqBDlztjcLJ3wo 24 | mnrt95gQMeSoLHY3UNsIRjbj43zImu7q9v/DD9ppQpu26aRDRmBNgLZA9GM5XnbZ 25 | RFi3VxLyqasGcSzaHwz5c7vOBOkOdlqcQzISRvWDxiN1HkAL+hkiQCuMchgORAgM 26 | wzPooa8rfWtLIpOXMpwuVGb/8rGNLEPovoCK9z6c+WZ+zkRo4+3TQkOMY66Xht7r 27 | Ahly3ler+Tyg6a5jXT92WKC/MXBYAy2ZQNoy204kNKevcH7R2cSkxITd3n5EacNy 28 | 5MAtCNIk7JweLCh9rLrLUBt+i4n44sP+LVhfWHemngA8CoF4n6eQ0pp0ixZTen0j 29 | 4uN0G2Nf+JeGMlqoObLWdIOdH/pbDppXGoZaKKDd7+bA74Fle5Uh7+1e3A== 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /crates/avalanche-types/artifacts/staker3.insecure.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV 3 | UzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFi 4 | czEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYT 5 | c3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMjJaGA8zMDE5MDcxMDE2 6 | MTIyMlowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFs 7 | YWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC 8 | AQC8mVDToHbkUF2gRdVfpydZLNKeQ38d6HZFkUM3U1dWLZFSZNvagN8hlQvY/tQu 9 | 3A40p19WgKbzWZre3tg1Akw8Jztdz9gl4RMn142IIO3CiwIptkE0JopbZhmG5fAC 10 | 2n/MXQtfieI3hzeR04LW4JgLKzf3Nn8xZdlBgJfBmL5qUUnE7O7IbJGGma6gSD3e 11 | wetE6KQZtNtf0xRIv08doZKYwTl6ItkdGK76ufqq098GVwWvA1wSune4+MFgs9N4 12 | eFJj6Jyt85fiK/cwPx7KRdgYgBzrZQ4EPshRnwWrBTieOOaJvAA2RMxMEYzKRrJA 13 | AsYI1zxtNyqIUaBTcxmaz+NXUGW+wHwITic0Gp/XQm2Lwr/lxIV6OnAlL3CgbSXi 14 | rSnoG+eHQ+vDzBAcRDkTAgv/GUIzlfqT2StTK02uIBgJYzvFTG4plHitccRfy8wx 15 | sh5Z8xG99lmPQQtLsnlQAV+Li06Cb8CH4hUVoiWiVs5QAahqWmv5fpoX0Es26RyU 16 | HXGbjE202pyMMA7jUerUVKMijOoGZtcH6zB4p/dJ0TtToRwOgrA7NCI9AYVtqVXr 17 | XG/udj8ur2r1bTVwIbHsOeTEP3gY0mHRWm2E/bLjt9vbYIRUxR8xWnLkbeBziNTw 18 | g+36jdDF+6gu3cUz/nbSn8YY+Y1jjXuM3lqF8iMaAobhuwIDAQABMA0GCSqGSIb3 19 | DQEBCwUAA4ICAQAe2kC0HjKZU+dlnU2RlfBpB4QgzzrFE5N9A8F1MlE4vV3AzCg1 20 | RVdHPvniXzdNhDiiflK0l/cnrFv2X1TzYMrrA677/usHf2Bw0xjm/ipHOt5V+4TN 21 | mZAIA4IPl09gP28IZLc9xSuq4FoHeM8OTxhttOlINhqpG9P5d6bPezW6ZzI3CdPP 22 | CF69xK4GFlj/NQnAoFogid4ojYYNTj/cM4PYQU2KbrlzLyPuUk/CgwefXLMH87/H 23 | e3kPDev80Tjv2Pm5nD937fZfgrEoyolKxiRVcfZVMxR7qhPhizjueD0DAkfQIs7L 24 | YVSyx/qjEv2bBYaim5RQakUeHR1Xu5Xj/k5zr33t979ede50byQrcWm4H5JxnEpD 25 | JxJnFfDOU6o14SKGHSrao5Z4C3dI55DM84WLASnlMI5BK4XtS3notLNzG8dfWWhT 26 | 9m0Hcry+wPNDcGr8Mtj1los/0bMDqMHC4jcFW1hrXCUUs9RYzE+N/xoqwCQSgN1P 27 | E73uXTySWj5ovMR5TPF6PhcftLB/OziqO7FverEBpvGGHUAnUT61JtjodjXPbEdj 28 | 0VgyMOBY2y53HTXnx3dxeFZkUdRX/VZYy8tMK3MTY+7UIU5cWYnCZAo5LNcc0ukR 29 | S6WS9+6eaQ6XRjhfNUjx9a7FzqapWdtTedpipmBP1Njap3g29iUuVnLQeg== 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /crates/avalanche-types/artifacts/staker4.insecure.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV 3 | UzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFi 4 | czEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYT 5 | c3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMjVaGA8zMDE5MDcxMDE2 6 | MTIyNVowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFs 7 | YWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC 8 | AQDZnDoDHE2nj82xDjH0Tb7OXMqQDHz+zbLidt6MSI1XB3vOAIEiPqrtenGnqRbV 9 | Fcm5GZxvxh4YQD8CjKSk1qgZJczs0DPSiGQ8Efl4PGO4xnEbllgL3PURPWp7mEV3 10 | oh6fxICgQKTBlT671EnFzB5lyJWpumRzvA1vyhBMsY8aO+xdq5LUFltYzBdvpgLX 11 | VaDwHZQ2PQEWtF0d0JO2N0WFFDGNmx6n8pKSeIAVDsTwZCZK+FCeeEyoGfXsINsc 12 | 0yCMQslawkfOMqA9yBV3Ji6QmFYKyGYt65MWGNqPA4XrIyliKwCCXwz9mjaWyN7r 13 | Ayw9cWlLMODNmDORWzGRZ5290MEAEIZsqjYHVitRTM/RnNIadToZGO0y5uAkM14c 14 | mTvnsK1CP92qtfSisq75W/I91drThoEtTK78UGOl/5Q1YBR08F+tSUWZWyHeI6UO 15 | BUCGC2bCtmzKMl7vU25lG6mbCR1JuQi6RYpnfMjXH36lV4S7fTvSwwuR03h2F3H1 16 | eFkWNG2lbFrW0dzDCPg3lXwmFQ65hUcQhctznoBz5C1lF2eW03wuVgxinnuVlJHj 17 | y/GrqmWsASn1PDuVs4k7k6DJfwyHAiA0uxXrGfxYvp7H8j4+2YOmWiWl5xYgrEDj 18 | ur5n8Zx46PHQer2Avq3sbEGEe1MCtXJlj3drd5Him3m+NQIDAQABMA0GCSqGSIb3 19 | DQEBCwUAA4ICAQA40ax0dAMrbWikaJ5s6kjaGkPkYuxHNJbw047Do0hjw+ncXsxc 20 | QDHmWcoHHpgMQCx0+vp8y+oKZ4pnqNfGSuOTo7/l05oQW/NbWw9mHwTiLMeI18/x 21 | Ay+5LpOasw+omqWLbdbbWqL0o/RvtBdK2rkcHzTVzECgGSoxUFfZD+ck2odpH+aR 22 | sQVu86AZVfclN2mjMyFSqMItqRcVw7rqr3Xy6FcgRQPykUnpguCEgcc9c54c1lQ9 23 | Zpddt4ezY7cTdk86oh7yA8QFchvtE9Zb5dJ5Vu9bdy9ig1kyscPTm+SeyhXRchUo 24 | ql4H/czGBVMHUY41wY2VFz7HitECcTAIpS6QvcxxgYevGNjZZxyZvEA8SYpLMZyb 25 | omk4enDTLd/xK1yF7VFodTDEyq63IAm0NTQZUVvIDfJeuzuNz55uxgdUq2RLpaJe 26 | 0bvrt9Obz+f5j2jonb2e0BuucwSdTyFXkUCxMW+piIUGkyrguAhlcHohDLEo2uB/ 27 | iQ4fosGqqsl47b+TezT5pSSblkgUjiwz6eDpM4lQpx22MxsHVlxFHrcBNm0Td92v 28 | FixrmllamAZbEz1tB//0bipKaOOZuhANJfrgN8BC6v2ahl4/SBuut09a0Azyxqpp 29 | uCsyTnfNEd1W6c6noaq24s+7W7KKLIekuNn1NunnHqKqriEuH1xlxxPjYA== 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /crates/avalanche-types/artifacts/staker5.insecure.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV 3 | UzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFi 4 | czEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYT 5 | c3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMjlaGA8zMDE5MDcxMDE2 6 | MTIyOVowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFs 7 | YWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC 8 | AQDgK5r5vdHtJFEgw7hGE/lzKaHcvwzr32armq0k9tYchJXfT3k1j1lXtBAdcUN3 9 | gSRKjgzH/vjbn0ea3AiDCUd2Mck/n0KcJZ43S5I7ZjP7rbav296bKCZ1Hr7r5gXY 10 | Fhk+3aUsVfDUqAPBwyP8KeV31ARVA/s+WPeWqs69QXTdyJuBYE5pr40v1Sf+ebUI 11 | nZ37uGY3kiO0Ex/JgcoQsGJzrWD/ztbRCFIvrdNJZd0pGvMlmTKp7XsMR3cpvqk7 12 | 70//MLCdyGW/1IArTSuD1vd7mBX1JyVXKycYN0vIOtbgxPOFutUyqDOeP7o51q4i 13 | PS3dCRgfmn/hWLwy+CtJe0BGKsb4tk0tKxo0se8v9JA8mUtnmzmMt4Y9jijOrCOB 14 | 7XwWKmJYEm8N5Ubcy6cp2oL8vQVtzz3PXrkFt+3cFt1jrjdpQYgH4jykkWDeOjEf 15 | y1FCwzsNRudLTvLhfLn86/ZT4cLZ9JI7/WW0IPC8Fc7lhznJ+bIQUeEndaGdgVkx 16 | uEg0MxdrMr0jU0IFoXySRXNRzcDWZShEjBTv7tnFxLmoNU+uJb/KpMH6sRYi3zs8 17 | 5ecaMKNyG+LDmBahUlHx5hKAH49O8855+AMhsg91ONZJldjQX0oZrIKzK5BpsqeT 18 | l4c2Yt/fALiZaeFk1pBEsvVeMOBCIuWE+b4UIEaLAOhxfwIDAQABMA0GCSqGSIb3 19 | DQEBCwUAA4ICAQB+2VXnqRqfG7H2/K0lgzxT+X9r1u+YDn0EaUGAG71s70Qnqbpn 20 | X7tBmCKLN6XgPL0HrN933nwiYrmfb8S33zZ7kw8GJDvaTamLNyem4/8qTBQmnRwe 21 | 6rQ7SY2l73Ig87mR0WTi+rTnTTtc66+/jLtFeaj0Ycl9hBZXHKiULSGhsbUbwtkz 22 | iuNlANhoNKXNIABRImUq6OwYhEQN0DwHXj79wkpyDYjKZwHuEZUknc8Pl2oQPBke 23 | mil3tsrvGRkwhisnXX7tqh6rWKVZNJkO68hy7XO9aTXjbcB/7Y1K83ISNEyGPsH/ 24 | pwFyd/j8O4modwh7Ulww1/hwcqnqiEFE3KzxX2pMh7VxeAmX2t5eXFZOlRx1lecM 25 | XRkVu19lYDKQHGSrGxng+BFlSOB96e5kXIbuIXKpPAACoBQ/JZYbtHks9H8OtNYO 26 | P2joqmnQ9wGkE5co1Ii//j2tuoCRCpK86mmbTlyNYvK+1/kkKcsaiiWXNrQsrIDZ 27 | BFs0FwX5g24OP5+brxTlRZE01R6St8lQj4IUwAcIzG8fFmMCWaYavrCZTeYaEiyF 28 | A0X2VA/vZ7x9D5P9Z5OakMhrMW+hJTYrpH1rm6KR7B26iU2kJRxTX7xQ9lrksqfB 29 | 7lX+q0iheeYA4cHbGJNWwWgd+FQsK/PTeiyr4rfqututdWA0IxoLRc3XFw== 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /crates/avalanche-types/artifacts/test.insecure.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIE7TCCAtWgAwIBAgIBADANBgkqhkiG9w0BAQsFADA6MQswCQYDVQQGEwJVUzEL 3 | MAkGA1UECAwCTlkxEDAOBgNVBAoMB0F2YWxhYnMxDDAKBgNVBAMMA2F2YTAeFw0y 4 | MjAyMDMwMTMwMjFaFw0yMzAyMDMwMTMwMjFaMDoxCzAJBgNVBAYTAlVTMQswCQYD 5 | VQQIDAJOWTEQMA4GA1UECgwHQXZhbGFiczEMMAoGA1UEAwwDYXZhMIICIjANBgkq 6 | hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0fI8k7ZD4zGFUCb0SyRB86zW+oywHpv1 7 | KJBBrkHFSD7+N5Sv+h8bnhyJ/BR/rBBUS0xWCVsKRlIWeCXfKginYJy2r/Gi6md9 8 | dL8km6GmECID2Xz7UZH68AW6zgEavToCF2ZSstOihOV+5gEByR5Zi3B4H1i7wglD 9 | qLp1rUvGGsf1yJpSy7arFLtsKVMPY3ifdRtgPeO3dn1ynSRz/nq28g8aMuueODpN 10 | iGVkW9VdvmvqWOKrthzMIhNOW7FjkMZUP9pIYBVdkRVRtoccX878jMVrYpnEgpze 11 | xmOJpINOrkLaGdRGETl+9iXtEVqgYnKrQ6bNbQ3IHjPfxB+HiJNc8JargxgD6DrO 12 | 5pTCdTQe76GpFaVH5WCzSaQ8YBi8fLiD9wwHOPtXXQAr4GG1tMU6MKxpMnAVaCMD 13 | izparuPsVJHkZfFkrK5qDXOF2FIj8C9HdgZCQ9zf8pV63YSCzIVCSEkXRG1jJcb2 14 | W2tul0zbfNYduGlRI4fQzr2UB4z6ZXy0PWrNO00ffvedsgEwMdBNufpvsgQZUmj6 15 | m4DkIbsceE2I8BhlnLX5X5Xgr4zPcvddbsAnFYkcZsOLU9u7/OB0GHl7Z3bIQ1In 16 | h9TQt3voNq5YcU//in5t5+bCIa+ypuFb9x69q4rNIiaW4DFi8/4xdwTA1wIMZHxf 17 | Z63ZkwuwpxMCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAGddw9iP5Fik4yRoYaFPN 18 | k3keMGV1txDGqBS5XVwoII3Y8dKiknwt5rbm0aEphsNYNqcVFa1sq4OIshbeVCEf 19 | i7JXqCDQwPGAEqUDk5OI+hyxOa9lmJgzVBxYfvJaljmsT5pARM+sR2HNfJOcXbfU 20 | U5zow2rrhy/vI1XSeSb1juHqzgb4BxKByKEUWqqKhlD765nu/W3exhsKtKI198bm 21 | B/6XZA3hTSkydEYlF4W4VLgoEOL4rnCOkl7Z6OGejTFNQo3nXXXHdlH2JvpUDiQ+ 22 | wTnq0qfa9t9U9M5qDSRBPqTe5ftBPatrTZl8/Wgc4sZX3FEgsnY4wSUklI2qWQ/b 23 | mqAXxmNj4eBmkx6sH7EPw3YdPdje3fxfVIjHfrREYHWpbbaMbEC0bonbgRFcgT0y 24 | pFtB2X991PPZyeXAIpt/hIh6VlAPKFq7F6MJoocKEvg5fSfHkmQUewOtrAODLqny 25 | c6zHJ5jyXbGbUeCj/25OI77J8SVKhy1GSY/LHMZbbheyn838jwCtqlMzI06b04Ed 26 | yr/Oiqxnsn+T367WJH+RS5myI0PqvSOsARRADdVcEjWa5T2Y0w5ldfeFPQsJ5GZb 27 | U23Dyaab2eSkVjdfVVuXddheZbrg/EMxWmnN6AwH0LFsqzr29AvEtpOi5Y/ah02p 28 | MxCw4Cee+3fi5y1ceYU5lw0= 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/evm_contract_abi_calldata.rs: -------------------------------------------------------------------------------- 1 | #![allow(deprecated)] 2 | 3 | use std::{io, str::FromStr}; 4 | 5 | use avalanche_types::evm::abi; 6 | use ethers_core::{ 7 | abi::{Function, Param, ParamType, StateMutability, Token}, 8 | types::{H160, U256}, 9 | }; 10 | 11 | /// cargo run --example evm_contract_abi_calldata --features="evm" 12 | fn main() -> io::Result<()> { 13 | let _ = env_logger::builder() 14 | .filter_level(log::LevelFilter::Debug) 15 | .is_test(true) 16 | .try_init(); 17 | 18 | // parsed function of "register(string name)" 19 | let func = Function { 20 | name: "register".to_string(), 21 | inputs: vec![Param { 22 | name: "name".to_string(), 23 | kind: ParamType::String, 24 | internal_type: None, 25 | }], 26 | outputs: Vec::new(), 27 | constant: None, 28 | state_mutability: StateMutability::NonPayable, 29 | }; 30 | let arg_tokens = vec![Token::String("abc".to_string())]; 31 | let calldata = abi::encode_calldata(func, &arg_tokens).unwrap(); 32 | log::info!("calldata: 0x{}", hex::encode(calldata)); 33 | 34 | // parsed function of "send(address receiver, uint amount)" 35 | let func = Function { 36 | name: "send".to_string(), 37 | inputs: vec![ 38 | Param { 39 | name: "receiver".to_string(), 40 | kind: ParamType::Address, 41 | internal_type: None, 42 | }, 43 | Param { 44 | name: "amount".to_string(), 45 | kind: ParamType::Uint(256), 46 | internal_type: None, 47 | }, 48 | ], 49 | outputs: Vec::new(), 50 | constant: None, 51 | state_mutability: StateMutability::NonPayable, 52 | }; 53 | let arg_tokens = vec![ 54 | Token::Address( 55 | H160::from_str("0x53C62F5d19f94556c4e9E9Ee97CeE274AB053399".trim_start_matches("0x")) 56 | .unwrap(), 57 | ), 58 | Token::Uint(U256::from(1)), 59 | ]; 60 | let calldata = abi::encode_calldata(func, &arg_tokens).unwrap(); 61 | log::info!("calldata: 0x{}", hex::encode(calldata)); 62 | 63 | Ok(()) 64 | } 65 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/evm_contract_counter_get_last.rs: -------------------------------------------------------------------------------- 1 | #![allow(deprecated)] 2 | 3 | use std::{env::args, io, str::FromStr}; 4 | 5 | use avalanche_types::{evm::abi, jsonrpc::client::evm as json_client_evm}; 6 | use ethers::prelude::Eip1559TransactionRequest; 7 | use ethers_core::{ 8 | abi::{Function, Param, ParamType, StateMutability}, 9 | types::transaction::eip2718::TypedTransaction, 10 | types::H160, 11 | }; 12 | use ethers_providers::{Http, Middleware, Provider}; 13 | 14 | /// cargo run --example evm_contract_counter_get_last --features="jsonrpc_client evm" -- [HTTP RPC ENDPOINT] [CONTRACT ADDRESS] 15 | /// cargo run --example evm_contract_counter_get_last --features="jsonrpc_client evm" -- http://127.0.0.1:9650/ext/bc/C/rpc 0x5DB9A7629912EBF95876228C24A848de0bfB43A9 16 | #[tokio::main] 17 | async fn main() -> io::Result<()> { 18 | // ref. 19 | env_logger::init_from_env( 20 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 21 | ); 22 | 23 | let chain_rpc_url = args().nth(1).expect("no chain RPC URL given"); 24 | let chain_rpc_provider = Provider::::try_from(chain_rpc_url.clone()) 25 | .expect("could not instantiate HTTP Provider"); 26 | log::info!("created chain rpc server provider for {chain_rpc_url}"); 27 | 28 | let contract_addr = args().nth(2).expect("no contract address given"); 29 | let contract_addr = H160::from_str(contract_addr.trim_start_matches("0x")).unwrap(); 30 | 31 | let chain_id = json_client_evm::chain_id(&chain_rpc_url).await.unwrap(); 32 | log::info!("running against {chain_rpc_url}, {chain_id} for contract {contract_addr}"); 33 | 34 | // parsed function of "getLast() public view returns (address)" 35 | let func = Function { 36 | name: "getLast".to_string(), 37 | inputs: vec![], 38 | outputs: vec![Param { 39 | name: "address".to_string(), 40 | kind: ParamType::Address, 41 | internal_type: None, 42 | }], 43 | constant: None, 44 | state_mutability: StateMutability::NonPayable, 45 | }; 46 | let arg_tokens = vec![]; 47 | let calldata = abi::encode_calldata(func, &arg_tokens).unwrap(); 48 | log::info!("calldata: 0x{}", hex::encode(calldata.clone())); 49 | 50 | let tx = Eip1559TransactionRequest::new() 51 | .chain_id(chain_id.as_u64()) 52 | .to(ethers::prelude::H160::from(contract_addr.as_fixed_bytes())) 53 | .data(calldata); 54 | let tx: TypedTransaction = tx.into(); 55 | 56 | let output = chain_rpc_provider.call(&tx, None).await.unwrap(); 57 | log::info!("output: {:?}", output); 58 | 59 | Ok(()) 60 | } 61 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/evm_eip712_gsn_domain_separator.rs: -------------------------------------------------------------------------------- 1 | use std::{env::args, io, str::FromStr}; 2 | 3 | use avalanche_types::evm::eip712::gsn::Tx; 4 | use ethers_core::types::{H160, U256}; 5 | 6 | /// "registerDomainSeparator(string name, string version)" "my name" "1" 7 | /// cargo run --example evm_eip712_gsn_domain_separator --features="evm" -- "my domain name" "1" 1234567 0x17aB05351fC94a1a67Bf3f56DdbB941aE6c63E25 8 | /// ref. "registerDomainSeparator" 9 | fn main() -> io::Result<()> { 10 | // ref. 11 | env_logger::init_from_env( 12 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 13 | ); 14 | 15 | let domain_name = args().nth(1).expect("no domain_name given"); 16 | log::info!("domain_name: {domain_name}"); 17 | 18 | let domain_version = args().nth(2).expect("no domain_version given"); 19 | log::info!("domain_version: {domain_version}"); 20 | 21 | let domain_chain_id = args().nth(3).expect("no domain_chain_id given"); 22 | let domain_chain_id = U256::from_str(&domain_chain_id).unwrap(); 23 | log::info!("domain_chain_id: {domain_chain_id}"); 24 | 25 | let domain_verifying_contract = args().nth(4).expect("no domain_verifying_contract given"); 26 | let domain_verifying_contract = 27 | H160::from_str(domain_verifying_contract.trim_start_matches("0x")).unwrap(); 28 | log::info!("domain_verifying_contract: {domain_verifying_contract}"); 29 | 30 | let domain_separator = Tx::new() 31 | .domain_name(domain_name) 32 | .domain_version(domain_version) 33 | .domain_chain_id(domain_chain_id) 34 | .domain_verifying_contract(domain_verifying_contract) 35 | .compute_domain_separator(); 36 | log::info!("domain separator: 0x{:x}", domain_separator); 37 | 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/evm_eip712_gsn_request_type_hash.rs: -------------------------------------------------------------------------------- 1 | use std::{env::args, io}; 2 | 3 | use avalanche_types::evm::eip712::gsn; 4 | 5 | /// "registerRequestType(string typeName, string typeSuffix)" "my name" "my suffix" 6 | /// cargo run --example evm_eip712_gsn_request_type_hash --features="evm" -- "my name" "my suffix" 7 | /// ref. 8 | fn main() -> io::Result<()> { 9 | // ref. 10 | env_logger::init_from_env( 11 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 12 | ); 13 | 14 | let type_name = args().nth(1).expect("no type_name given"); 15 | log::info!("type_name: {type_name}"); 16 | 17 | let type_suffix_data = args().nth(2).expect("no type_suffix_data given"); 18 | log::info!("type_suffix_data: {type_suffix_data}"); 19 | 20 | let request_type_hash = gsn::compute_request_type_hash(&type_name, &type_suffix_data); 21 | log::info!("request type hash: {:x}", request_type_hash); 22 | 23 | Ok(()) 24 | } 25 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/evm_send_raw_transaction_eip1559_hot_key.rs: -------------------------------------------------------------------------------- 1 | use std::{convert::TryFrom, env::args, io}; 2 | 3 | use avalanche_types::{evm::eip1559, key}; 4 | use ethers_providers::{Http, Middleware, Provider}; 5 | 6 | /// cargo run --example evm_send_raw_transaction_eip1559_hot_key -- [HTTP RPC ENDPOINT] 7 | /// cargo run --example evm_send_raw_transaction_eip1559_hot_key -- http://localhost:9876/rpc 8 | #[tokio::main] 9 | async fn main() -> io::Result<()> { 10 | // ref. 11 | env_logger::init_from_env( 12 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 13 | ); 14 | 15 | let chain_rpc_url = args().nth(1).expect("no chain rpc url given"); 16 | let chain_rpc_provider = Provider::::try_from(chain_rpc_url.clone()) 17 | .expect("could not instantiate HTTP Provider"); 18 | log::info!("created chain rpc server provider for {chain_rpc_url}"); 19 | 20 | let chain_id = random_manager::u64() % 3000; 21 | let signer_nonce = primitive_types::U256::from(random_manager::u64() % 10); 22 | let gas_limit = primitive_types::U256::from(random_manager::u64() % 10000); 23 | let max_fee_per_gas = primitive_types::U256::from(random_manager::u64() % 10000); 24 | let value = primitive_types::U256::from(random_manager::u64() % 100000); 25 | 26 | let k1 = key::secp256k1::TEST_KEYS[0].clone(); 27 | let key_info1 = k1.to_info(1).unwrap(); 28 | log::info!("created hot key:\n\n{}\n", key_info1); 29 | let k1_signer: ethers_signers::LocalWallet = k1.to_ethers_core_signing_key().into(); 30 | 31 | let k2 = key::secp256k1::private_key::Key::generate().unwrap(); 32 | let key_info2 = k2.to_info(1).unwrap(); 33 | log::info!("created hot key:\n\n{}\n", key_info2); 34 | 35 | let tx = eip1559::Transaction::new() 36 | .chain_id(chain_id) 37 | .from(key_info1.h160_address) 38 | .recipient(key_info2.h160_address) 39 | .signer_nonce(signer_nonce) 40 | .max_fee_per_gas(max_fee_per_gas) 41 | .gas_limit(gas_limit) 42 | .value(value); 43 | 44 | let signed_bytes = tx.sign_as_typed_transaction(k1_signer).await.unwrap(); 45 | log::info!("signed_bytes: {}", signed_bytes); 46 | 47 | let pending = chain_rpc_provider 48 | .send_raw_transaction(signed_bytes) 49 | .await 50 | .unwrap(); 51 | log::info!("pending tx hash 0x{:x}", pending.tx_hash()); 52 | 53 | Ok(()) 54 | } 55 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/jsonrpc_client_evm.rs: -------------------------------------------------------------------------------- 1 | use std::{env::args, io, str::FromStr}; 2 | 3 | use avalanche_types::jsonrpc::client::evm; 4 | 5 | /// cargo run --example jsonrpc_client_evm --features="jsonrpc_client evm" -- [HTTP RPC ENDPOINT] 0x613040a239BDfCF110969fecB41c6f92EA3515C0 6 | /// cargo run --example jsonrpc_client_evm --features="jsonrpc_client evm" -- http://localhost:9650 0x613040a239BDfCF110969fecB41c6f92EA3515C0 7 | /// cargo run --example jsonrpc_client_evm --features="jsonrpc_client evm" -- http://44.230.236.23:9650 0x613040a239BDfCF110969fecB41c6f92EA3515C0 8 | #[tokio::main] 9 | async fn main() -> io::Result<()> { 10 | // ref. 11 | env_logger::init_from_env( 12 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 13 | ); 14 | 15 | let http_rpc = args().nth(1).expect("no http_rpc given"); 16 | let caddr = args().nth(2).expect("no C-chain address given"); 17 | 18 | let chain_id = evm::chain_id(format!("{http_rpc}/ext/bc/C/rpc").as_str()) 19 | .await 20 | .unwrap(); 21 | log::info!("chain_id: {:?}", chain_id); 22 | 23 | let balance = evm::get_balance( 24 | format!("{http_rpc}/ext/bc/C/rpc").as_str(), 25 | primitive_types::H160::from_str(caddr.trim_start_matches("0x")).unwrap(), 26 | ) 27 | .await 28 | .unwrap(); 29 | log::info!("balance: {:?}", balance); 30 | 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/jsonrpc_client_p.rs: -------------------------------------------------------------------------------- 1 | use std::{env::args, io}; 2 | 3 | use avalanche_types::jsonrpc::client::p as jsonrpc_client_p; 4 | 5 | /// cargo run --example jsonrpc_client_p --features="jsonrpc_client" -- [HTTP RPC ENDPOINT] P-custom1qwmslrrqdv4slxvynhy9csq069l0u8mqwjzmcd 6 | /// cargo run --example jsonrpc_client_p --features="jsonrpc_client" -- http://52.42.183.125:9650 7 | /// cargo run --example jsonrpc_client_p --features="jsonrpc_client" -- http://52.42.183.125:9650 P-custom1qwmslrrqdv4slxvynhy9csq069l0u8mqwjzmcd 8 | /// 9 | /// ``` 10 | /// # or run this 11 | /// avalanche-cli-rust get-utxos \ 12 | /// --http-rpc-endpoint [HTTP RPC ENDPOINT] \ 13 | /// --p-chain-address P-custom1qwmslrrqdv4slxvynhy9csq069l0u8mqwjzmcd 14 | /// ``` 15 | /// 16 | #[tokio::main] 17 | async fn main() -> io::Result<()> { 18 | // ref. 19 | env_logger::init_from_env( 20 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 21 | ); 22 | 23 | let url = args().nth(1).expect("no url given"); 24 | println!("{}", url); 25 | 26 | if let Some(paddr) = &args().nth(2) { 27 | println!("{}", paddr); 28 | let resp = jsonrpc_client_p::get_balance(&url, paddr).await.unwrap(); 29 | log::info!( 30 | "get_balance response: {}", 31 | serde_json::to_string_pretty(&resp).unwrap() 32 | ); 33 | 34 | let resp = jsonrpc_client_p::get_utxos(&url, paddr).await.unwrap(); 35 | log::info!( 36 | "get_utxos response: {}", 37 | serde_json::to_string_pretty(&resp).unwrap() 38 | ); 39 | } 40 | 41 | let resp = jsonrpc_client_p::get_height(&url).await.unwrap(); 42 | log::info!( 43 | "get_height response: {}", 44 | serde_json::to_string_pretty(&resp).unwrap() 45 | ); 46 | 47 | let resp = jsonrpc_client_p::get_primary_network_validators(&url) 48 | .await 49 | .unwrap(); 50 | log::info!( 51 | "get_current_validators response: {}", 52 | serde_json::to_string_pretty(&resp).unwrap() 53 | ); 54 | 55 | let resp = jsonrpc_client_p::get_subnets(&url, None).await.unwrap(); 56 | log::info!( 57 | "get_subnets response: {}", 58 | serde_json::to_string_pretty(&resp).unwrap() 59 | ); 60 | 61 | let resp = jsonrpc_client_p::get_blockchains(&url).await.unwrap(); 62 | log::info!( 63 | "get_blockchains response: {}", 64 | serde_json::to_string_pretty(&resp).unwrap() 65 | ); 66 | 67 | Ok(()) 68 | } 69 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/jsonrpc_client_x.rs: -------------------------------------------------------------------------------- 1 | use std::{env::args, io}; 2 | 3 | use avalanche_types::jsonrpc::client::x as jsonrpc_client_x; 4 | 5 | /// cargo run --example jsonrpc_client_x --features="jsonrpc_client" -- [HTTP RPC ENDPOINT] X-custom152qlr6zunz7nw2kc4lfej3cn3wk46u3002k4w5 6 | /// cargo run --example jsonrpc_client_x --features="jsonrpc_client" -- http://44.230.236.23:9650 X-custom152qlr6zunz7nw2kc4lfej3cn3wk46u3002k4w5 7 | #[tokio::main] 8 | async fn main() -> io::Result<()> { 9 | // ref. 10 | env_logger::init_from_env( 11 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 12 | ); 13 | 14 | let url = args().nth(1).expect("no url given"); 15 | let xaddr = args().nth(2).expect("no x-chain address given"); 16 | 17 | let resp = jsonrpc_client_x::get_balance(&url, &xaddr).await.unwrap(); 18 | log::info!( 19 | "get_balance response: {}", 20 | serde_json::to_string_pretty(&resp).unwrap() 21 | ); 22 | 23 | let resp = jsonrpc_client_x::get_asset_description(&url, "AVAX") 24 | .await 25 | .unwrap(); 26 | log::info!( 27 | "get_asset_description response: {}", 28 | serde_json::to_string_pretty(&resp).unwrap() 29 | ); 30 | 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/key_cert.rs: -------------------------------------------------------------------------------- 1 | use std::{env::args, fs, path::Path}; 2 | 3 | use avalanche_types::ids::node; 4 | 5 | /// cargo run --example key_cert -- /tmp/test.insecure.key /tmp/test.insecure.cert 6 | fn main() { 7 | // ref. 8 | env_logger::init_from_env( 9 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 10 | ); 11 | 12 | let key_path = args().nth(1).expect("no key path given"); 13 | let cert_path = args().nth(2).expect("no cert path given"); 14 | 15 | if Path::new(&key_path).exists() { 16 | fs::remove_file(&key_path).expect("failed remove_file"); 17 | } 18 | if Path::new(&cert_path).exists() { 19 | fs::remove_file(&cert_path).expect("failed remove_file"); 20 | } 21 | 22 | cert_manager::x509::generate_and_write_pem(None, key_path.as_str(), cert_path.as_str()) 23 | .expect("failed to generate certs"); 24 | // openssl x509 -in /tmp/test.insecure.cert -text -noout 25 | // openssl x509 -in artifacts/staker1.insecure.crt -text -noout 26 | 27 | let node_id = node::Id::from_cert_pem_file(cert_path.as_str()).unwrap(); 28 | println!("Node ID: {}", node_id); 29 | 30 | let (loaded_node_id, generated) = 31 | node::Id::load_or_generate_pem(&key_path, &cert_path).unwrap(); 32 | assert!(!generated); 33 | assert_eq!(node_id, loaded_node_id); 34 | } 35 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/key_secp256k1_info_gen.rs: -------------------------------------------------------------------------------- 1 | use std::{env::args, fs::File, io::Write}; 2 | 3 | /// cargo run --example key_secp256k1_info_gen -- 1 1 9999 /tmp/key.json 4 | /// cargo run --example key_secp256k1_info_gen -- 50 1 9999 /tmp/key.json 5 | fn main() { 6 | // ref. 7 | env_logger::init_from_env( 8 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 9 | ); 10 | 11 | let keys = args().nth(1).expect("no network ID given"); 12 | let keys = keys.parse::().unwrap(); 13 | 14 | let network_id = args().nth(2).expect("no network ID given"); 15 | let network_id1 = network_id.parse::().unwrap(); 16 | 17 | let network_id = args().nth(3).expect("no network ID given"); 18 | let network_id2 = network_id.parse::().unwrap(); 19 | 20 | let file_path = args().nth(4).expect("no file path given"); 21 | 22 | let mut infos = Vec::new(); 23 | for i in 0..keys { 24 | let key = if i == 0 { 25 | avalanche_types::key::secp256k1::private_key::Key::from_cb58( 26 | "PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN", 27 | ) 28 | .expect("unexpected key generate failure") 29 | } else { 30 | avalanche_types::key::secp256k1::private_key::Key::generate() 31 | .expect("unexpected key generate failure") 32 | }; 33 | 34 | let mut k1 = key.to_info(network_id1).expect("failed to_info"); 35 | let k2 = key.to_info(network_id2).expect("failed to_info"); 36 | 37 | k1.addresses 38 | .insert(network_id2, k2.addresses.get(&network_id2).unwrap().clone()); 39 | infos.push(k1); 40 | } 41 | 42 | let d = serde_json::to_vec(&infos).unwrap(); 43 | let mut f = File::create(file_path).unwrap(); 44 | f.write_all(&d).unwrap(); 45 | } 46 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/key_secp256k1_info_load_avax.rs: -------------------------------------------------------------------------------- 1 | use std::env::args; 2 | 3 | /// cargo run --example key_secp256k1_info_load_avax -- PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN 1 4 | /// cargo run --example key_secp256k1_info_load_avax -- PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN 9999 5 | /// cargo run --example key_secp256k1_info_load_avax -- PrivateKey-2kqWNDaqUKQyE4ZsV5GLCGeizE6sHAJVyjnfjXoXrtcZpK9M67 1 6 | /// cargo run --example key_secp256k1_info_load_avax -- PrivateKey-2kqWNDaqUKQyE4ZsV5GLCGeizE6sHAJVyjnfjXoXrtcZpK9M67 9999 7 | fn main() { 8 | // ref. 9 | env_logger::init_from_env( 10 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 11 | ); 12 | 13 | let private_key = args().nth(1).expect("no private key given"); 14 | 15 | let network_id = args().nth(2).expect("no network ID given"); 16 | let network_id = network_id.parse::().unwrap(); 17 | 18 | log::info!("loading key"); 19 | let k = avalanche_types::key::secp256k1::private_key::Key::from_cb58(&private_key).unwrap(); 20 | let pubkey = k.to_public_key(); 21 | 22 | let entry = k.to_info(network_id).unwrap(); 23 | assert_eq!(private_key, entry.private_key_cb58.clone().unwrap()); 24 | assert_eq!( 25 | entry.addresses.get(&network_id).unwrap().x, 26 | pubkey.to_hrp_address(network_id, "X").unwrap() 27 | ); 28 | assert_eq!( 29 | entry.addresses.get(&network_id).unwrap().p, 30 | pubkey.to_hrp_address(network_id, "P").unwrap() 31 | ); 32 | assert_eq!(entry.short_address, pubkey.to_short_id().unwrap()); 33 | assert_eq!(entry.eth_address, pubkey.to_eth_address()); 34 | 35 | print!("{}", entry); 36 | } 37 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/key_secp256k1_info_load_eth.rs: -------------------------------------------------------------------------------- 1 | use std::env::args; 2 | 3 | /// cargo run --example key_secp256k1_info_load_eth -- 56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027 1 4 | /// cargo run --example key_secp256k1_info_load_eth -- 0x56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027 1 5 | /// cargo run --example key_secp256k1_info_load_eth -- 56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027 9999 6 | /// cargo run --example key_secp256k1_info_load_eth -- 0x56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027 9999 7 | /// cargo run --example key_secp256k1_info_load_eth -- e73b5812225f2e1c62de93fb6ec35a9338882991577f9a6d5651dce61cecd852 1 8 | /// cargo run --example key_secp256k1_info_load_eth -- 0xe73b5812225f2e1c62de93fb6ec35a9338882991577f9a6d5651dce61cecd852 1 9 | /// cargo run --example key_secp256k1_info_load_eth -- e73b5812225f2e1c62de93fb6ec35a9338882991577f9a6d5651dce61cecd852 9999 10 | /// cargo run --example key_secp256k1_info_load_eth -- 0xe73b5812225f2e1c62de93fb6ec35a9338882991577f9a6d5651dce61cecd852 9999 11 | fn main() { 12 | // ref. 13 | env_logger::init_from_env( 14 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 15 | ); 16 | 17 | let private_key = args().nth(1).expect("no private key given"); 18 | 19 | let network_id = args().nth(2).expect("no network ID given"); 20 | let network_id = network_id.parse::().unwrap(); 21 | 22 | log::info!("loading key"); 23 | let k = avalanche_types::key::secp256k1::private_key::Key::from_hex(&private_key).unwrap(); 24 | let pubkey = k.to_public_key(); 25 | 26 | let entry = k.to_info(network_id).unwrap(); 27 | assert_eq!( 28 | prefix_manager::prepend_0x(&private_key), 29 | entry.private_key_hex.clone().unwrap() 30 | ); 31 | assert_eq!( 32 | entry.addresses.get(&network_id).unwrap().x, 33 | pubkey.to_hrp_address(network_id, "X").unwrap() 34 | ); 35 | assert_eq!( 36 | entry.addresses.get(&network_id).unwrap().p, 37 | pubkey.to_hrp_address(network_id, "P").unwrap() 38 | ); 39 | assert_eq!(entry.short_address, pubkey.to_short_id().unwrap()); 40 | assert_eq!(entry.eth_address, pubkey.to_eth_address()); 41 | 42 | print!("{}", entry); 43 | } 44 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/key_secp256k1_kms_aws.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, env::args, io}; 2 | 3 | use avalanche_types::key; 4 | use aws_manager::{self, kms}; 5 | use tokio::time::{self, sleep}; 6 | 7 | /// cargo run --example key_secp256k1_kms_aws --features="kms_aws" 8 | /// cargo run --example key_secp256k1_kms_aws --features="kms_aws" -- arn:aws:sts::[ACCOUNT_ID]:assumed-role/[NAME]/[EMAIL] 9 | #[tokio::main] 10 | async fn main() -> io::Result<()> { 11 | // ref. 12 | env_logger::init_from_env( 13 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "debug"), 14 | ); 15 | 16 | log::info!("creating AWS KMS resources!"); 17 | let shared_config = aws_manager::load_config(None, None, None).await; 18 | let kms_manager = kms::Manager::new(&shared_config); 19 | 20 | let key_name = id_manager::time::with_prefix("test"); 21 | let mut tags = HashMap::new(); 22 | tags.insert(String::from("Name"), key_name); 23 | 24 | let mut key = key::secp256k1::kms::aws::Key::create(kms_manager.clone(), tags) 25 | .await 26 | .unwrap(); 27 | 28 | let grant_id = if let Some(arn_to_grant) = args().nth(1) { 29 | log::info!("creating kms grant"); 30 | let (grant_id, grant_token) = kms_manager 31 | .create_grant_for_sign_reads(&key.id, &arn_to_grant) 32 | .await 33 | .unwrap(); 34 | key.grant_token = Some(grant_token); 35 | Some(grant_id) 36 | } else { 37 | None 38 | }; 39 | 40 | let key_info = key.to_info(1).unwrap(); 41 | println!("key_info:\n{}", key_info); 42 | 43 | let key2 = key::secp256k1::kms::aws::Key::from_arn(kms_manager.clone(), &key.arn) 44 | .await 45 | .unwrap(); 46 | let key_info2 = key2.to_info(1).unwrap(); 47 | println!("key_info2:\n{}", key_info2); 48 | 49 | let digest = [0u8; ring::digest::SHA256_OUTPUT_LEN]; 50 | match key.sign_digest(&digest).await { 51 | Ok(sig) => { 52 | log::info!( 53 | "successfully signed with signature output {} bytes", 54 | sig.to_vec().len() 55 | ); 56 | } 57 | Err(e) => { 58 | log::warn!("failed to sign, error: {:?}", e); 59 | } 60 | } 61 | 62 | if let Some(grant_id) = &grant_id { 63 | log::info!("revoking kms grant"); 64 | kms_manager.revoke_grant(&key.id, grant_id).await.unwrap(); 65 | } 66 | 67 | sleep(time::Duration::from_secs(5)).await; 68 | key.delete(7).await.unwrap(); 69 | 70 | // error should be ignored if it's already scheduled for delete 71 | sleep(time::Duration::from_secs(5)).await; 72 | key.delete(7).await.unwrap(); 73 | 74 | Ok(()) 75 | } 76 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/key_secp256k1_mnemonic_derive_load.rs: -------------------------------------------------------------------------------- 1 | use std::env::args; 2 | 3 | /// m/44'/9000'/0'/0/n where n is the address index 4 | /// (P-chain use this as an external address!) 5 | /// 6 | /// cargo run --example key_secp256k1_mnemonic_derive_load "m/44'/9000'/0'/0/0" "vehicle arrive more spread busy regret onion fame argue nice grocery humble vocal slot quit toss learn artwork theory fault tip belt cloth disorder" 7 | /// cargo run --example key_secp256k1_mnemonic_derive_load "m/44'/9000'/0'/0/1" "vehicle arrive more spread busy regret onion fame argue nice grocery humble vocal slot quit toss learn artwork theory fault tip belt cloth disorder" 8 | fn main() { 9 | // ref. 10 | env_logger::init_from_env( 11 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 12 | ); 13 | 14 | let deriv_path = args().nth(1).expect("no phrase given"); 15 | let phrase = args().nth(2).expect("no phrase given"); 16 | let key = 17 | avalanche_types::key::secp256k1::private_key::Key::from_mnemonic_phrase(phrase, deriv_path) 18 | .unwrap(); 19 | 20 | let entry = key.to_info(1).expect("failed to_info"); 21 | log::info!("network ID 1:\n{}", entry); 22 | 23 | let entry = key.to_info(9999).expect("failed to_info"); 24 | log::info!("network ID 9999:\n{}", entry); 25 | } 26 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/proto_client.rs: -------------------------------------------------------------------------------- 1 | use avalanche_types::proto::pb::helloworld::{greeter_client::GreeterClient, HelloRequest}; 2 | 3 | #[tokio::main] 4 | async fn main() -> Result<(), Box> { 5 | let mut client = GreeterClient::connect("http://[::1]:50051").await?; 6 | let request = tonic::Request::new(HelloRequest { 7 | name: "Avalanche Rustaceans!".into(), 8 | }); 9 | let resp = client.say_hello(request).await?; 10 | 11 | println!("SUCCESSFUL response: {:?}", resp); 12 | 13 | Ok(()) 14 | } 15 | -------------------------------------------------------------------------------- /crates/avalanche-types/examples/proto_server.rs: -------------------------------------------------------------------------------- 1 | use avalanche_types::{ 2 | proto::pb::helloworld::{ 3 | self, 4 | greeter_server::{Greeter, GreeterServer}, 5 | HelloReply, HelloRequest, 6 | }, 7 | subnet::rpc::utils, 8 | }; 9 | use tonic::{Request, Response, Status}; 10 | 11 | #[derive(Default)] 12 | struct MyGreeter; 13 | 14 | #[tonic::async_trait] 15 | impl Greeter for MyGreeter { 16 | async fn say_hello( 17 | &self, 18 | request: Request, 19 | ) -> Result, Status> { 20 | println!("Got a request from {:?}", request.remote_addr()); 21 | 22 | let reply = HelloReply { 23 | message: format!("Hello {}!", request.into_inner().name), 24 | }; 25 | Ok(Response::new(reply)) 26 | } 27 | } 28 | 29 | #[tokio::main] 30 | async fn main() -> Result<(), Box> { 31 | let addr = "[::1]:50051".parse().unwrap(); 32 | println!("server listening on {}", addr); 33 | 34 | // ref. https://github.com/hyperium/tonic/blob/v0.8.1/examples/src/reflection/server.rs 35 | let reflection_svc = tonic_reflection::server::Builder::configure() 36 | .register_encoded_file_descriptor_set(helloworld::FILE_DESCRIPTOR_SET) 37 | .build() 38 | .expect("failed to build reflection service"); 39 | 40 | let greeter_svc = GreeterServer::new(MyGreeter); 41 | 42 | utils::grpc::default_server() 43 | .add_service(reflection_svc) 44 | .add_service(greeter_svc) 45 | .serve(addr) 46 | .await?; 47 | 48 | Ok(()) 49 | } 50 | -------------------------------------------------------------------------------- /crates/avalanche-types/fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | corpus 3 | artifacts 4 | -------------------------------------------------------------------------------- /crates/avalanche-types/fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "avalanche-types-fuzz" 3 | version = "0.0.0" 4 | authors = ["Automatically generated"] 5 | publish = false 6 | edition = "2018" 7 | 8 | [package.metadata] 9 | cargo-fuzz = true 10 | 11 | [dependencies] 12 | libfuzzer-sys = "0.4" 13 | 14 | [dependencies.avalanche-types] 15 | path = ".." 16 | 17 | # Prevent this from interfering with workspaces 18 | [workspace] 19 | members = ["."] 20 | 21 | [[bin]] 22 | name = "ids" 23 | path = "fuzz_targets/ids.rs" 24 | test = false 25 | doc = false 26 | -------------------------------------------------------------------------------- /crates/avalanche-types/fuzz/fuzz_targets/ids.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | use avalanche_types::ids; 5 | 6 | // ref. https://rust-fuzz.github.io/book/cargo-fuzz/tutorial.html 7 | fuzz_target!(|data: &[u8]| { 8 | for batch in data.chunks(ids::ID_LEN) { 9 | ids::Id::from_slice(batch); 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /crates/avalanche-types/scripts/examples.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xue 3 | 4 | if ! [[ "$0" =~ scripts/examples.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | cargo run --example key_cert -- /tmp/test.insecure.key /tmp/test.insecure.cert 10 | 11 | # cargo run --example key_secp256k1_kms_aws --features="kms_aws" 12 | 13 | cargo run --example key_secp256k1_info_gen -- 1 1 9999 /tmp/key.json 14 | 15 | cargo run --example key_secp256k1_info_load_avax -- PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN 1 16 | cargo run --example key_secp256k1_info_load_avax -- PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN 9999 17 | cargo run --example key_secp256k1_info_load_avax -- PrivateKey-2kqWNDaqUKQyE4ZsV5GLCGeizE6sHAJVyjnfjXoXrtcZpK9M67 1 18 | cargo run --example key_secp256k1_info_load_avax -- PrivateKey-2kqWNDaqUKQyE4ZsV5GLCGeizE6sHAJVyjnfjXoXrtcZpK9M67 9999 19 | 20 | cargo run --example key_secp256k1_info_load_eth -- 56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027 1 21 | cargo run --example key_secp256k1_info_load_eth -- 56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027 9999 22 | cargo run --example key_secp256k1_info_load_eth -- e73b5812225f2e1c62de93fb6ec35a9338882991577f9a6d5651dce61cecd852 1 23 | cargo run --example key_secp256k1_info_load_eth -- e73b5812225f2e1c62de93fb6ec35a9338882991577f9a6d5651dce61cecd852 9999 24 | 25 | cargo run --example proto_server --features="proto" --features="subnet" & 26 | sleep 5 27 | cargo run --example proto_client --features="proto" --features="subnet" 28 | -------------------------------------------------------------------------------- /crates/avalanche-types/scripts/protobuf_codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script is used to generate the protobuf stubs for the avalanche-types 4 | # crate. 5 | 6 | # protocol version is the version of the gRPC proto definitions 7 | # as defined by the avalanchego rpcchainvm. 8 | # ref. https://github.com/ava-labs/avalanchego/blob/v1.11.0/version/constants.go 9 | PROTOCOL_VERSION='33' 10 | 11 | if ! [[ "$0" =~ scripts/protobuf_codegen.sh ]]; then 12 | echo "must be run from repository root" 13 | exit 255 14 | fi 15 | 16 | # ref. https://docs.buf.build/installation 17 | BUF_VERSION='1.29.0' 18 | if [[ $(buf --version | cut -f2 -d' ') != "${BUF_VERSION}" ]]; then 19 | echo "could not find buf ${BUF_VERSION}, is it installed + in PATH?" 20 | exit 255 21 | fi 22 | 23 | # protoc-gen-prost and protoc-gen-tonic are now community modules hosted by buf 24 | # and not required by this script. 25 | # 26 | # ref. https://buf.build/community/neoeinstein-tonic 27 | # ref. https://buf.build/community/neoeinstein-prost 28 | 29 | # protoc plugin "protoc-gen-prost-crate" is required 30 | # 31 | # e.g., 32 | # cargo install protoc-gen-prost-crate --version 0.4.0 33 | # ref. https://crates.io/crates/protoc-gen-prost-crate 34 | PROTOC_GEN_PROST_CRATE_VERSION=0.4.0 35 | if [[ $(protoc-gen-prost-crate --version | cut -f2 -d' ') != "${PROTOC_GEN_PROST_CRATE_VERSION}" ]]; then 36 | echo "could not find protoc-gen-prost-crate version ${PROTOC_GEN_PROST_CRATE_VERSION} is it installed + in PATH?" 37 | exit 255 38 | fi 39 | 40 | pushd ./src/proto || return 41 | 42 | # cleanup previous protos 43 | rm -rf ./protos/avalanche 44 | 45 | # pull source from buf registry 46 | echo "Pulling proto source for protocol version: ${PROTOCOL_VERSION}..." 47 | 48 | # TODO: needs registry updates on https://buf.build/ava-labs/avalanche/tree/main 49 | # buf export buf.build/ava-labs/avalanche:v"${PROTOCOL_VERSION}" -o ./protos/avalanche 50 | 51 | buf export buf.build/ava-labs/avalanche:main -o ./protos/avalanche 52 | 53 | echo "Re-generating proto stubs..." 54 | buf generate 55 | 56 | if [[ $? -ne 0 ]]; then 57 | echo "ERROR: buf generate proto stubs failed" 58 | exit 1 59 | fi 60 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/avalanchego/aliases.rs: -------------------------------------------------------------------------------- 1 | //! Chain alias functionality for the avalanchego node. 2 | use std::collections::HashMap; 3 | 4 | /// A map from blockchainIDs to custom aliases 5 | /// ref. . 6 | pub type Aliases = HashMap>; 7 | 8 | #[test] 9 | fn test_aliases_json() { 10 | let json = r#"{"q2aTwKuyzgs8pynF7UXBZCU7DejbZbZ6EUyHr3JQzYgwNPUPi": ["DFK"]}"#; 11 | let aliases: Aliases = serde_json::from_str(json).unwrap(); 12 | assert_eq!( 13 | aliases 14 | .get("q2aTwKuyzgs8pynF7UXBZCU7DejbZbZ6EUyHr3JQzYgwNPUPi") 15 | .unwrap(), 16 | &vec!["DFK".to_string()] 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/avalanchego/mod.rs: -------------------------------------------------------------------------------- 1 | //! AvalancheGo APIs. 2 | pub mod aliases; 3 | pub mod config; 4 | pub mod genesis; 5 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/avm/mod.rs: -------------------------------------------------------------------------------- 1 | //! Transaction types for the Avalanche Virtual Machine. 2 | pub mod txs; 3 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/avm/txs/fx.rs: -------------------------------------------------------------------------------- 1 | //! Credential transaction type. 2 | use crate::{ids, key}; 3 | use serde::{Deserialize, Serialize}; 4 | 5 | /// ref. 6 | #[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)] 7 | pub struct Credential { 8 | pub fx_id: ids::Id, // skip serialization due to serialize:"false" 9 | pub cred: key::secp256k1::txs::Credential, 10 | } 11 | 12 | impl Default for Credential { 13 | fn default() -> Self { 14 | Self { 15 | fx_id: ids::Id::empty(), 16 | cred: key::secp256k1::txs::Credential::default(), 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/choices/decidable.rs: -------------------------------------------------------------------------------- 1 | //! The Decidable trait. 2 | use crate::errors::Result; 3 | use crate::{choices::status::Status, ids::Id}; 4 | 5 | /// Represents an element that can be decided. 6 | /// Decidable objects are transactions, blocks, or vertices. 7 | /// ref. 8 | pub trait Decidable { 9 | /// Returns the ID of this block's parent. 10 | fn id(&self) -> Id; 11 | 12 | /// Returns the current status. 13 | fn status(&self) -> Status; 14 | 15 | /// Accepts this element. 16 | /// TODO: use ? 17 | fn accept(&mut self) -> Result<()>; 18 | /// Rejects this element. 19 | /// TODO: use ? 20 | fn reject(&mut self) -> Result<()>; 21 | } 22 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/choices/mod.rs: -------------------------------------------------------------------------------- 1 | //! A generic interface for decidable problems. 2 | pub mod decidable; 3 | pub mod status; 4 | pub mod test_decidable; 5 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/codec/serde/hex_0x_primitive_types_u256.rs: -------------------------------------------------------------------------------- 1 | use primitive_types::U256; 2 | use serde::{self, Deserialize, Deserializer, Serializer}; 3 | use serde_with::{DeserializeAs, SerializeAs}; 4 | 5 | pub fn serialize(x: &U256, serializer: S) -> Result 6 | where 7 | S: Serializer, 8 | { 9 | serializer.serialize_str(&format!("0x{:x}", *x)) 10 | } 11 | 12 | pub fn deserialize<'de, D>(deserializer: D) -> Result 13 | where 14 | D: Deserializer<'de>, 15 | { 16 | let s = String::deserialize(deserializer)?; 17 | let s = s.trim_start_matches("0x"); 18 | 19 | U256::from_str_radix(s, 16).map_err(serde::de::Error::custom) 20 | } 21 | 22 | pub struct Hex0xU256; 23 | 24 | impl SerializeAs for Hex0xU256 { 25 | fn serialize_as(x: &U256, serializer: S) -> Result 26 | where 27 | S: Serializer, 28 | { 29 | serializer.serialize_str(&format!("0x{:x}", *x)) 30 | } 31 | } 32 | 33 | impl<'de> DeserializeAs<'de, U256> for Hex0xU256 { 34 | fn deserialize_as(deserializer: D) -> Result 35 | where 36 | D: Deserializer<'de>, 37 | { 38 | let s = String::deserialize(deserializer)?; 39 | let s = s.trim_start_matches("0x"); 40 | 41 | U256::from_str_radix(s, 16).map_err(serde::de::Error::custom) 42 | } 43 | } 44 | 45 | /// RUST_LOG=debug cargo test --package avalanche-types --lib -- codec::serde::hex_0x_primitive_types_u256::test_custom_de_serializer --exact --show-output 46 | #[test] 47 | fn test_custom_de_serializer() { 48 | use serde::Serialize; 49 | use serde_with::serde_as; 50 | 51 | #[serde_as] 52 | #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] 53 | struct Data { 54 | #[serde_as(as = "Vec")] 55 | data: Vec, 56 | } 57 | 58 | let d = Data { 59 | data: vec![ 60 | U256::from_dec_str("123").unwrap(), 61 | U256::from_dec_str("123").unwrap(), 62 | ], 63 | }; 64 | 65 | let yaml_encoded = serde_yaml::to_string(&d).unwrap(); 66 | println!("yaml_encoded:\n{}", yaml_encoded); 67 | let yaml_decoded = serde_yaml::from_str(&yaml_encoded).unwrap(); 68 | assert_eq!(d, yaml_decoded); 69 | 70 | let json_encoded = serde_json::to_string(&d).unwrap(); 71 | println!("json_encoded:\n{}", json_encoded); 72 | let json_decoded = serde_json::from_str(&json_encoded).unwrap(); 73 | assert_eq!(d, json_decoded); 74 | 75 | let json_decoded_2: Data = serde_json::from_str( 76 | " 77 | 78 | { 79 | \"data\":[\"0x7b\", \"0x7b\"] 80 | } 81 | 82 | ", 83 | ) 84 | .unwrap(); 85 | assert_eq!(d, json_decoded_2); 86 | } 87 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/codec/serde/hex_0x_u64.rs: -------------------------------------------------------------------------------- 1 | use serde::{self, Deserialize, Deserializer, Serializer}; 2 | use serde_with::{DeserializeAs, SerializeAs}; 3 | 4 | pub fn serialize(x: &u64, serializer: S) -> Result 5 | where 6 | S: Serializer, 7 | { 8 | serializer.serialize_str(&format!("0x{:x}", *x)) 9 | } 10 | 11 | pub fn deserialize<'de, D>(deserializer: D) -> Result 12 | where 13 | D: Deserializer<'de>, 14 | { 15 | let s = String::deserialize(deserializer)?; 16 | let s = s.trim_start_matches("0x"); 17 | 18 | u64::from_str_radix(s, 16).map_err(serde::de::Error::custom) 19 | } 20 | 21 | pub struct Hex0xU64; 22 | 23 | impl SerializeAs for Hex0xU64 { 24 | fn serialize_as(x: &u64, serializer: S) -> Result 25 | where 26 | S: Serializer, 27 | { 28 | serializer.serialize_str(&format!("0x{:x}", *x)) 29 | } 30 | } 31 | 32 | impl<'de> DeserializeAs<'de, u64> for Hex0xU64 { 33 | fn deserialize_as(deserializer: D) -> Result 34 | where 35 | D: Deserializer<'de>, 36 | { 37 | let s = String::deserialize(deserializer)?; 38 | let s = s.trim_start_matches("0x"); 39 | 40 | u64::from_str_radix(s, 16).map_err(serde::de::Error::custom) 41 | } 42 | } 43 | 44 | /// RUST_LOG=debug cargo test --package avalanche-types --lib -- codec::serde::hex_0x_u64::test_custom_de_serializer --exact --show-output 45 | #[test] 46 | fn test_custom_de_serializer() { 47 | use serde::Serialize; 48 | use serde_with::serde_as; 49 | 50 | #[serde_as] 51 | #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] 52 | struct Data { 53 | #[serde_as(as = "Vec")] 54 | data: Vec, 55 | } 56 | 57 | let d = Data { 58 | data: vec![123_u64, 123_u64], 59 | }; 60 | 61 | let yaml_encoded = serde_yaml::to_string(&d).unwrap(); 62 | println!("yaml_encoded:\n{}", yaml_encoded); 63 | let yaml_decoded = serde_yaml::from_str(&yaml_encoded).unwrap(); 64 | assert_eq!(d, yaml_decoded); 65 | 66 | let json_encoded = serde_json::to_string(&d).unwrap(); 67 | println!("json_encoded:\n{}", json_encoded); 68 | let json_decoded = serde_json::from_str(&json_encoded).unwrap(); 69 | assert_eq!(d, json_decoded); 70 | 71 | let json_decoded_2: Data = serde_json::from_str( 72 | " 73 | 74 | { 75 | \"data\":[\"0x7b\", \"0x7b\"] 76 | } 77 | 78 | ", 79 | ) 80 | .unwrap(); 81 | assert_eq!(d, json_decoded_2); 82 | } 83 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/codec/serde/hex_0x_utxo.rs: -------------------------------------------------------------------------------- 1 | use crate::txs::utxo::Utxo; 2 | use serde::{self, Deserialize, Deserializer, Serializer}; 3 | use serde_with::{DeserializeAs, SerializeAs}; 4 | 5 | pub fn serialize(x: &Utxo, serializer: S) -> Result 6 | where 7 | S: Serializer, 8 | { 9 | let utxo_hex = x.to_hex().map_err(serde::ser::Error::custom)?; 10 | serializer.serialize_str(&utxo_hex) 11 | } 12 | 13 | pub fn deserialize<'de, D>(deserializer: D) -> Result 14 | where 15 | D: Deserializer<'de>, 16 | { 17 | let s = String::deserialize(deserializer)?; 18 | 19 | Utxo::from_hex(&s).map_err(serde::de::Error::custom) 20 | } 21 | 22 | pub struct Hex0xUtxo; 23 | 24 | impl SerializeAs for Hex0xUtxo { 25 | fn serialize_as(x: &Utxo, serializer: S) -> Result 26 | where 27 | S: Serializer, 28 | { 29 | let s = x.to_hex().map_err(serde::ser::Error::custom)?; 30 | 31 | serializer.serialize_str(&s) 32 | } 33 | } 34 | 35 | impl<'de> DeserializeAs<'de, Utxo> for Hex0xUtxo { 36 | fn deserialize_as(deserializer: D) -> Result 37 | where 38 | D: Deserializer<'de>, 39 | { 40 | let s = String::deserialize(deserializer)?; 41 | 42 | Utxo::from_hex(&s).map_err(serde::de::Error::custom) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/codec/serde/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod hex_0x_bytes; 2 | pub mod hex_0x_primitive_types_h160; 3 | pub mod hex_0x_primitive_types_h256; 4 | pub mod hex_0x_primitive_types_u256; 5 | pub mod hex_0x_u64; 6 | pub mod hex_0x_utxo; 7 | pub mod ip_port; 8 | pub mod rfc_3339; 9 | 10 | #[cfg(feature = "codec_base64")] 11 | #[cfg_attr(docsrs, doc(cfg(feature = "codec_base64")))] 12 | pub mod base64_bytes; 13 | 14 | #[cfg(feature = "codec_big_int")] 15 | #[cfg_attr(docsrs, doc(cfg(feature = "codec_big_int")))] 16 | pub mod hex_0x_big_int; 17 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/codec/serde/rfc_3339.rs: -------------------------------------------------------------------------------- 1 | use chrono::{DateTime, SecondsFormat, TimeZone, Utc}; 2 | use serde::{self, Deserialize, Deserializer, Serializer}; 3 | use serde_with::{DeserializeAs, SerializeAs}; 4 | 5 | /// ref. 6 | pub fn serialize(x: &DateTime, serializer: S) -> Result 7 | where 8 | S: Serializer, 9 | { 10 | // ref. 11 | serializer.serialize_str(&x.to_rfc3339_opts(SecondsFormat::Millis, true)) 12 | } 13 | 14 | /// ref. 15 | pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> 16 | where 17 | D: Deserializer<'de>, 18 | { 19 | let s = String::deserialize(deserializer)?; 20 | 21 | // ref. 22 | match DateTime::parse_from_rfc3339(&s).map_err(serde::de::Error::custom) { 23 | Ok(dt) => Ok(Utc.from_utc_datetime(&dt.naive_utc())), 24 | Err(e) => Err(e), 25 | } 26 | } 27 | 28 | pub struct DateTimeUtc; 29 | 30 | impl SerializeAs> for DateTimeUtc { 31 | fn serialize_as(x: &DateTime, serializer: S) -> Result 32 | where 33 | S: Serializer, 34 | { 35 | serializer.serialize_str(&x.to_rfc3339_opts(SecondsFormat::Millis, true)) 36 | } 37 | } 38 | 39 | impl<'de> DeserializeAs<'de, DateTime> for DateTimeUtc { 40 | fn deserialize_as(deserializer: D) -> Result, D::Error> 41 | where 42 | D: Deserializer<'de>, 43 | { 44 | let s = String::deserialize(deserializer)?; 45 | 46 | match DateTime::parse_from_rfc3339(&s).map_err(serde::de::Error::custom) { 47 | Ok(dt) => Ok(Utc.from_utc_datetime(&dt.naive_utc())), 48 | Err(e) => Err(e), 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/constants.rs: -------------------------------------------------------------------------------- 1 | //! Constants for the Avalanche network. 2 | use std::collections::HashMap; 3 | 4 | use lazy_static::lazy_static; 5 | 6 | pub const DEFAULT_CUSTOM_NETWORK_ID: u32 = 1000000; 7 | 8 | pub const FALLBACK_HRP: &str = "custom"; 9 | 10 | lazy_static! { 11 | /// ref. 12 | pub static ref NETWORK_ID_TO_NETWORK_NAME: HashMap = { 13 | let mut m = HashMap::new(); 14 | m.insert(1, "mainnet"); 15 | m.insert(2, "cascade"); 16 | m.insert(3, "denali"); 17 | m.insert(4, "everest"); 18 | m.insert(5, "fuji"); 19 | m.insert(12345, "local"); 20 | m 21 | }; 22 | 23 | /// ref. 24 | pub static ref NETWORK_NAME_TO_NETWORK_ID: HashMap<&'static str, u32> = { 25 | let mut m = HashMap::new(); 26 | m.insert("mainnet", 1); 27 | m.insert("cascade", 2); 28 | m.insert("denali", 3); 29 | m.insert("everest", 4); 30 | m.insert("fuji", 5); 31 | m.insert("local", 12345); 32 | m 33 | }; 34 | 35 | /// ref. 36 | pub static ref NETWORK_ID_TO_HRP: HashMap = { 37 | let mut m = HashMap::new(); 38 | m.insert(1, "avax"); 39 | m.insert(2, "cascade"); 40 | m.insert(3, "denali"); 41 | m.insert(4, "everest"); 42 | m.insert(5, "fuji"); 43 | m.insert(12345, "local"); 44 | m 45 | }; 46 | 47 | /// ref. 48 | pub static ref HRP_TO_NETWORK_ID: HashMap<&'static str, u32> = { 49 | let mut m = HashMap::new(); 50 | m.insert("avax", 1); 51 | m.insert("cascade", 2); 52 | m.insert("denali", 3); 53 | m.insert("everest", 4); 54 | m.insert("fuji", 5); 55 | m.insert("local", 12345); 56 | m 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/coreth/mod.rs: -------------------------------------------------------------------------------- 1 | //! Coreth types. 2 | //! 3 | //! Includes the chain config and genesis. 4 | pub mod chain_config; 5 | pub mod genesis; 6 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/errors.rs: -------------------------------------------------------------------------------- 1 | //! Custom error types used in avalanche-types. 2 | use std::{cell::RefCell, fmt, rc::Rc}; 3 | 4 | use thiserror::Error; 5 | 6 | pub type Result = std::result::Result; 7 | 8 | /// Backing errors for all consensus operations. 9 | #[derive(Clone, Debug, Error)] 10 | pub enum Error { 11 | #[error("failed API (message: {message:?}, retryable: {retryable:?})")] 12 | API { message: String, retryable: bool }, 13 | #[error("failed for other reasons (message: {message:?}, retryable: {retryable:?})")] 14 | Other { message: String, retryable: bool }, 15 | } 16 | 17 | impl Error { 18 | /// Returns the error message in "String". 19 | #[inline] 20 | #[must_use] 21 | pub fn message(&self) -> String { 22 | match self { 23 | Error::API { message, .. } | Error::Other { message, .. } => message.clone(), 24 | } 25 | } 26 | 27 | /// Returns if the error is retryable. 28 | #[inline] 29 | #[must_use] 30 | pub fn retryable(&self) -> bool { 31 | match self { 32 | Error::API { retryable, .. } | Error::Other { retryable, .. } => *retryable, 33 | } 34 | } 35 | 36 | /// Returns true if the error message contains the substring. 37 | #[inline] 38 | #[must_use] 39 | pub fn contains(&self, s: &str) -> bool { 40 | self.message().contains(s) 41 | } 42 | } 43 | 44 | #[derive(Debug)] 45 | pub struct Errors { 46 | d: Rc>>, 47 | } 48 | 49 | impl Errors { 50 | pub fn new() -> Self { 51 | Self { 52 | d: Rc::new(RefCell::new(Vec::new())), 53 | } 54 | } 55 | 56 | pub fn errored(&self) -> bool { 57 | !self.d.borrow().is_empty() 58 | } 59 | 60 | pub fn add(&self, e: Error) { 61 | self.d.borrow_mut().push(e); 62 | } 63 | } 64 | 65 | impl Default for Errors { 66 | fn default() -> Self { 67 | Self::new() 68 | } 69 | } 70 | 71 | /// ref. 72 | /// ref. 73 | /// Use "Self.to_string()" to directly invoke this. 74 | impl fmt::Display for Errors { 75 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 76 | let mut errs: Vec = Vec::new(); 77 | for e in self.d.borrow().iter() { 78 | errs.push(e.message()); 79 | } 80 | write!(f, "{}", errs.join(", ")) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/evm/eip712/mod.rs: -------------------------------------------------------------------------------- 1 | //! Module for gas relaying via Gas Station Network (GSN). 2 | pub mod gsn; 3 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/evm/foundry/mod.rs: -------------------------------------------------------------------------------- 1 | //! Module for Paradigm's Foundry project. 2 | pub mod forge; 3 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/evm/mod.rs: -------------------------------------------------------------------------------- 1 | //! Modules for various EVM functionality. 2 | //! 3 | //! Includes the Ethereum ABI, EIP-1559, EIP-712, and Foundry. 4 | pub mod abi; 5 | pub mod eip1559; 6 | pub mod eip712; 7 | pub mod foundry; 8 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/jsonrpc/client/evm.rs: -------------------------------------------------------------------------------- 1 | //! EVM RPC client. 2 | use std::time::Duration; 3 | 4 | use crate::errors::{Error, Result}; 5 | use ethers_providers::{Http, Middleware, Provider}; 6 | use primitive_types::{H160, U256}; 7 | 8 | /// Fetches the chain Id from "{http_rpc}/ext/bc/{chain_id_alias}/rpc". 9 | /// "chain_id_alias" is "C" for C-chain, and blockchain Id for subnet-evm. 10 | pub async fn chain_id(rpc_ep: &str) -> Result { 11 | let provider = Provider::::try_from(rpc_ep) 12 | .map_err(|e| { 13 | // TODO: check retryable 14 | Error::API { 15 | message: format!("failed to create provider '{}'", e), 16 | retryable: false, 17 | } 18 | })? 19 | .interval(Duration::from_millis(2000u64)); 20 | 21 | log::info!("getting chain id via {rpc_ep}"); 22 | provider.get_chainid().await.map_err(|e| 23 | // TODO: check retryable 24 | Error::API { 25 | message: format!("failed to get_chainid '{}'", e), 26 | retryable: false, 27 | }) 28 | } 29 | 30 | /// Fetches the balance from "{http_rpc}/ext/bc/{chain_id_alias}/rpc". 31 | /// "chain_id_alias" is "C" for C-chain, and blockchain Id for subnet-evm. 32 | /// ref. 33 | pub async fn get_balance(rpc_ep: &str, eth_addr: H160) -> Result { 34 | let provider = Provider::::try_from(rpc_ep) 35 | .map_err(|e| { 36 | // TODO: check retryable 37 | Error::API { 38 | message: format!("failed to create provider '{}'", e), 39 | retryable: false, 40 | } 41 | })? 42 | .interval(Duration::from_millis(2000u64)); 43 | 44 | log::info!("getting balances for {} via {rpc_ep}", eth_addr); 45 | provider.get_balance(eth_addr, None).await.map_err(|e| 46 | // TODO: check retryable 47 | Error::API { 48 | message: format!("failed get_balance '{}'", e), 49 | retryable: false, 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/jsonrpc/client/mod.rs: -------------------------------------------------------------------------------- 1 | //! JSON-RPC client methods and URL utilities. 2 | 3 | pub mod admin; 4 | pub mod evm; 5 | pub mod health; 6 | pub mod info; 7 | pub mod p; 8 | pub mod url; 9 | pub mod x; 10 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/key/mod.rs: -------------------------------------------------------------------------------- 1 | //! APIs for cryptographic operations on Avalanche. 2 | //! 3 | //! Includes both BLS and secp256k1 keys. 4 | pub mod bls; 5 | pub mod secp256k1; 6 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/key/secp256k1/kms/mod.rs: -------------------------------------------------------------------------------- 1 | //! AWS KMS support for secp256k1 keys. 2 | #[cfg(feature = "kms_aws")] 3 | #[cfg_attr(docsrs, doc(cfg(feature = "kms_aws")))] 4 | pub mod aws; 5 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/key/secp256k1/mnemonic.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::{Error, Result}; 2 | use bip32::{DerivationPath, Language, Mnemonic, XPrv}; 3 | use rand_core::OsRng; 4 | 5 | /// ref. 6 | pub const AVAX_ACCOUNT_DERIV_PATH: &str = "m/44'/9000'/0'"; 7 | pub const AVAX_ACCOUNT_DERIV_PATH_0: &str = "m/44'/9000'/0'/0/0"; 8 | 9 | /// ref. 10 | pub const AVAX_ACCOUNT_EXT_PUB_KEY_DERIV_PATH: &str = "m/44'/9000'/0'"; 11 | pub const ETH_ACCOUNT_EXT_PUB_KEY_DERIV_PATH: &str = "m/44'/60'/0'/0/0"; 12 | 13 | /// Only supports "English" for now. 14 | /// ref. 15 | /// ref. 16 | /// ref. 17 | /// ref. 18 | pub fn gen_24() -> String { 19 | let m = Mnemonic::random(OsRng, Language::English); 20 | let s = m.phrase(); 21 | assert_eq!(s.split(' ').count(), 24); 22 | String::from(s) 23 | } 24 | 25 | impl crate::key::secp256k1::private_key::Key { 26 | /// Loads the private key from the mnemonic phrase. 27 | pub fn from_mnemonic_phrase(phrase: S, derive_path: S) -> Result 28 | where 29 | S: AsRef, 30 | { 31 | let deriv: DerivationPath = derive_path.as_ref().parse().map_err(|e| Error::Other { 32 | message: format!("failed to parse derive path ({})", e), 33 | retryable: false, 34 | })?; 35 | 36 | let mnemonic = Mnemonic::new(phrase, Language::English).map_err(|e| Error::Other { 37 | message: format!("failed to read mnemonic phrase ({})", e), 38 | retryable: false, 39 | })?; 40 | let seed = mnemonic.to_seed("password"); 41 | 42 | // ref. https://github.com/ava-labs/avalanche-wallet/blob/v0.3.8/src/js/wallets/MnemonicWallet.ts 43 | let child_xprv = XPrv::derive_from_path(&seed, &deriv).map_err(|e| Error::Other { 44 | message: format!("failed to derive AVAX account path ({})", e), 45 | retryable: false, 46 | })?; 47 | 48 | let pk = child_xprv.private_key().to_bytes(); 49 | Self::from_bytes(&pk) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # avalanche-types 2 | //! 3 | //! avalanche-types contains the foundational types used in the Avalanche ecosystem in Rust. 4 | //! This include types used by the Avalanche JSON-RPC API and the EVM. Modules 5 | //! for serialization/deserialization, hashing, and codecs are all provided. 6 | //! 7 | //! The APIs can be used to build a custom, high-performance Rust VM that can run on 8 | //! Avalanche. See the `subnet` subdirectory for an SDK that makes it easy to build a 9 | //! custom VM in Rust. 10 | //! 11 | //! avalanche-types can also be used to build Rust clients and tooling within the Avalanche 12 | //! ecosystem. 13 | //! 14 | #![cfg_attr(docsrs, feature(doc_cfg))] 15 | pub mod avm; 16 | pub mod choices; 17 | pub mod codec; 18 | pub mod constants; 19 | pub mod errors; 20 | pub mod formatting; 21 | pub mod hash; 22 | pub mod ids; 23 | pub mod jsonrpc; 24 | pub mod key; 25 | pub mod node; 26 | pub mod packer; 27 | pub mod platformvm; 28 | pub mod txs; 29 | pub mod units; 30 | pub mod utils; 31 | pub mod verify; 32 | 33 | #[cfg(feature = "avalanchego")] 34 | #[cfg_attr(docsrs, doc(cfg(feature = "avalanchego")))] 35 | pub mod avalanchego; 36 | 37 | #[cfg(feature = "coreth")] 38 | #[cfg_attr(docsrs, doc(cfg(feature = "coreth")))] 39 | pub mod coreth; 40 | 41 | #[cfg(feature = "subnet_evm")] 42 | #[cfg_attr(docsrs, doc(cfg(feature = "subnet_evm")))] 43 | pub mod subnet_evm; 44 | 45 | #[cfg(feature = "xsvm")] 46 | #[cfg_attr(docsrs, doc(cfg(feature = "xsvm")))] 47 | pub mod xsvm; 48 | 49 | #[cfg(feature = "evm")] 50 | #[cfg_attr(docsrs, doc(cfg(feature = "evm")))] 51 | pub mod evm; 52 | 53 | #[cfg(feature = "message")] 54 | #[cfg_attr(docsrs, doc(cfg(feature = "message")))] 55 | pub mod message; 56 | 57 | #[cfg(feature = "wallet")] 58 | #[cfg_attr(docsrs, doc(cfg(feature = "wallet")))] 59 | pub mod wallet; 60 | 61 | #[cfg(feature = "proto")] 62 | #[cfg_attr(docsrs, doc(cfg(feature = "proto")))] 63 | pub mod proto; 64 | 65 | #[cfg(feature = "subnet")] 66 | #[cfg_attr(docsrs, doc(cfg(feature = "subnet")))] 67 | pub mod subnet; 68 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/message/compress.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, Cursor, Read}; 2 | 3 | use flate2::{ 4 | bufread::{GzDecoder, GzEncoder}, 5 | Compression, 6 | }; 7 | 8 | /// Compress the input bytes. 9 | 10 | pub fn pack_gzip(d: S) -> io::Result> 11 | where 12 | S: AsRef<[u8]>, 13 | { 14 | // ref. "golang/compress/flag.DefaultCompression" is -1 which is level 6 15 | // "Compression::default()" returns 6 16 | let mut gz = GzEncoder::new(Cursor::new(d), Compression::new(6)); 17 | let mut encoded = Vec::new(); 18 | gz.read_to_end(&mut encoded)?; 19 | Ok(encoded) 20 | } 21 | 22 | /// Decompress the input bytes. 23 | 24 | pub fn unpack_gzip(d: S) -> io::Result> 25 | where 26 | S: AsRef<[u8]>, 27 | { 28 | let mut gz = GzDecoder::new(Cursor::new(d)); 29 | let mut decoded = Vec::new(); 30 | gz.read_to_end(&mut decoded)?; 31 | Ok(decoded) 32 | } 33 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/message/mod.rs: -------------------------------------------------------------------------------- 1 | //! Definitions of messages that can be sent between nodes. 2 | pub mod accepted; 3 | pub mod accepted_frontier; 4 | pub mod accepted_state_summary; 5 | pub mod ancestors; 6 | pub mod app_gossip; 7 | pub mod app_request; 8 | pub mod app_response; 9 | pub mod chits; 10 | pub mod compress; 11 | pub mod get; 12 | pub mod get_accepted; 13 | pub mod get_accepted_frontier; 14 | pub mod get_accepted_state_summary; 15 | pub mod get_ancestors; 16 | pub mod get_state_summary_frontier; 17 | pub mod peerlist; 18 | pub mod ping; 19 | pub mod pong; 20 | pub mod pull_query; 21 | pub mod push_query; 22 | pub mod put; 23 | pub mod state_summary_frontier; 24 | 25 | pub fn ip_addr_to_bytes(ip_addr: std::net::IpAddr) -> Vec { 26 | match ip_addr { 27 | std::net::IpAddr::V4(v) => { 28 | // "avalanchego" encodes IPv4 address as it is 29 | // (not compatible with IPv6, e.g., prepends 2 "0xFF"s as in Rust) 30 | let octets = v.octets(); 31 | vec![ 32 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, octets[0], octets[1], octets[2], octets[3], 33 | ] 34 | } 35 | std::net::IpAddr::V6(v) => v.octets().to_vec(), 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/node.rs: -------------------------------------------------------------------------------- 1 | //! Defines the node type. 2 | use serde::{Deserialize, Serialize}; 3 | 4 | /// Defines the node type. 5 | /// MUST BE either "anchor" or "non-anchor" 6 | #[derive( 7 | Deserialize, 8 | Serialize, 9 | std::clone::Clone, 10 | std::cmp::Eq, 11 | std::cmp::Ord, 12 | std::cmp::PartialEq, 13 | std::cmp::PartialOrd, 14 | std::fmt::Debug, 15 | std::hash::Hash, 16 | )] 17 | pub enum Kind { 18 | #[serde(rename = "anchor")] 19 | Anchor, 20 | #[serde(rename = "non-anchor")] 21 | NonAnchor, 22 | Unknown(String), 23 | } 24 | 25 | impl std::convert::From<&str> for Kind { 26 | fn from(s: &str) -> Self { 27 | match s { 28 | "anchor" => Kind::Anchor, 29 | "non-anchor" => Kind::NonAnchor, 30 | "non_anchor" => Kind::NonAnchor, 31 | 32 | other => Kind::Unknown(other.to_owned()), 33 | } 34 | } 35 | } 36 | 37 | impl std::str::FromStr for Kind { 38 | type Err = std::convert::Infallible; 39 | 40 | fn from_str(s: &str) -> std::result::Result { 41 | Ok(Kind::from(s)) 42 | } 43 | } 44 | 45 | impl Kind { 46 | /// Returns the `&str` value of the enum member. 47 | pub fn as_str(&self) -> &str { 48 | match self { 49 | Kind::Anchor => "anchor", 50 | Kind::NonAnchor => "non-anchor", 51 | 52 | Kind::Unknown(s) => s.as_ref(), 53 | } 54 | } 55 | 56 | /// Returns all the `&str` values of the enum members. 57 | pub fn values() -> &'static [&'static str] { 58 | &[ 59 | "anchor", // 60 | "non-anchor", // 61 | ] 62 | } 63 | } 64 | 65 | impl AsRef for Kind { 66 | fn as_ref(&self) -> &str { 67 | self.as_str() 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/platformvm/mod.rs: -------------------------------------------------------------------------------- 1 | //! Avalanche platformvm utilities. 2 | pub mod txs; 3 | 4 | use crate::ids; 5 | 6 | /// ref. 7 | pub fn chain_id() -> ids::Id { 8 | ids::Id::empty() 9 | } 10 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/README.md: -------------------------------------------------------------------------------- 1 | # Avalanche-rs Proto 2 | 3 | Now Serving: **Protocol Version 28** 4 | 5 | Protobuf files are hosted at 6 | [https://buf.build/ava-labs/avalanche](https://buf.build/ava-labs/avalanche) and 7 | can be used as dependencies in other projects. 8 | 9 | Protobuf linting and generation for this project is managed by 10 | [buf](https://github.com/bufbuild/buf). 11 | 12 | Please find installation instructions on 13 | [https://docs.buf.build/installation/](https://docs.buf.build/installation/) or 14 | use `Dockerfile.buf` provided in the `proto/` directory of AvalancheGo. 15 | 16 | Introduction to `buf` 17 | [https://docs.buf.build/tour/introduction](https://docs.buf.build/tour/introduction) 18 | 19 | To update the protocol version update the `PROTOCOL_VERSION` environment variable 20 | in `scripts/protobuf_codegen.sh` and `mod.rs` then run the script. 21 | 22 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: buf.build/community/neoeinstein-prost:v0.2.3 4 | out: pb 5 | opt: 6 | - bytes=. 7 | # https://docs.rs/prost-build/latest/prost_build/struct.Config.html#method.compile_well_known_types 8 | - compile_well_known_types 9 | # https://github.com/neoeinstein/protoc-gen-prost/blob/main/protoc-gen-prost/README.md#protoc-gen-prost 10 | - file_descriptor_set 11 | 12 | - plugin: buf.build/community/neoeinstein-tonic:v0.3.0 13 | out: pb 14 | opt: 15 | # https://docs.rs/prost-build/latest/prost_build/struct.Config.html#method.compile_well_known_types 16 | - compile_well_known_types 17 | 18 | - name: prost-crate # remote plugin not supported yet 19 | out: pb 20 | strategy: all 21 | opt: 22 | # https://docs.rs/protoc-gen-prost-crate/latest/protoc_gen_prost_crate/#options 23 | - include_file=mod.rs 24 | - no_features=true 25 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/buf.work.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | directories: 3 | # temporary directory created by scripts/protobuf_codegen.sh 4 | - protos/avalanche 5 | - protos/static 6 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | name: buf.build/ava-labs/avalanche-proto 3 | breaking: 4 | use: 5 | - FILE 6 | lint: 7 | use: 8 | - DEFAULT 9 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/mod.rs: -------------------------------------------------------------------------------- 1 | //! Generated protobuf stubs and helpers for Avalanche. 2 | //! 3 | //! ref. 4 | #[allow(clippy::all)] 5 | pub mod pb; 6 | 7 | #[doc(hidden)] 8 | pub use pb::*; 9 | 10 | /// ref. 11 | pub const PROTOCOL_VERSION: u32 = 33; 12 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/aliasreader/aliasreader.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package aliasreader; 4 | 5 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/aliasreader"; 6 | 7 | service AliasReader { 8 | rpc Lookup(Alias) returns (ID); 9 | rpc PrimaryAlias(ID) returns (Alias); 10 | rpc Aliases(ID) returns (AliasList); 11 | } 12 | 13 | message ID { 14 | bytes id = 1; 15 | } 16 | 17 | message Alias { 18 | string alias = 1; 19 | } 20 | 21 | message AliasList { 22 | repeated string aliases = 1; 23 | } 24 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/appsender/appsender.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package appsender; 4 | 5 | import "google/protobuf/empty.proto"; 6 | 7 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/appsender"; 8 | 9 | service AppSender { 10 | rpc SendAppRequest(SendAppRequestMsg) returns (google.protobuf.Empty); 11 | rpc SendAppResponse(SendAppResponseMsg) returns (google.protobuf.Empty); 12 | rpc SendAppError(SendAppErrorMsg) returns (google.protobuf.Empty); 13 | rpc SendAppGossip(SendAppGossipMsg) returns (google.protobuf.Empty); 14 | rpc SendAppGossipSpecific(SendAppGossipSpecificMsg) returns (google.protobuf.Empty); 15 | 16 | rpc SendCrossChainAppRequest(SendCrossChainAppRequestMsg) returns (google.protobuf.Empty); 17 | rpc SendCrossChainAppResponse(SendCrossChainAppResponseMsg) returns (google.protobuf.Empty); 18 | rpc SendCrossChainAppError(SendCrossChainAppErrorMsg) returns (google.protobuf.Empty); 19 | } 20 | 21 | message SendAppRequestMsg { 22 | // The nodes to send this request to 23 | repeated bytes node_ids = 1; 24 | // The ID of this request 25 | uint32 request_id = 2; 26 | // The request body 27 | bytes request = 3; 28 | } 29 | 30 | message SendAppResponseMsg { 31 | // The node to send a response to 32 | bytes node_id = 1; 33 | // ID of this request 34 | uint32 request_id = 2; 35 | // The response body 36 | bytes response = 3; 37 | } 38 | 39 | message SendAppErrorMsg { 40 | // The node to send a response to 41 | bytes node_id = 1; 42 | // ID of this request 43 | uint32 request_id = 2; 44 | // Application-defined error code 45 | sint32 error_code = 3; 46 | // Application-defined error message 47 | string error_message = 4; 48 | } 49 | 50 | message SendAppGossipMsg { 51 | // The message body 52 | bytes msg = 1; 53 | } 54 | 55 | message SendAppGossipSpecificMsg { 56 | // The nodes to send this request to 57 | repeated bytes node_ids = 1; 58 | // The message body 59 | bytes msg = 2; 60 | } 61 | 62 | message SendCrossChainAppRequestMsg { 63 | // The chain to send this request to 64 | bytes chain_id = 1; 65 | // the ID of this request 66 | uint32 request_id = 2; 67 | // The request body 68 | bytes request = 3; 69 | } 70 | 71 | message SendCrossChainAppResponseMsg { 72 | // The chain to send this response to 73 | bytes chain_id = 1; 74 | // the ID of this request 75 | uint32 request_id = 2; 76 | // The response body 77 | bytes response = 3; 78 | } 79 | 80 | message SendCrossChainAppErrorMsg { 81 | // The chain to send a response to 82 | bytes chain_id = 1; 83 | // ID of this request 84 | uint32 request_id = 2; 85 | // Application-defined error code 86 | sint32 error_code = 3; 87 | // Application-defined error message 88 | string error_message = 4; 89 | } 90 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/http/responsewriter/responsewriter.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package http.responsewriter; 4 | 5 | import "google/protobuf/empty.proto"; 6 | 7 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/http/responsewriter"; 8 | 9 | // Writer is an http.ResponseWriter see: https://pkg.go.dev/net/http#ResponseWriter 10 | service Writer { 11 | // Write writes the data to the connection as part of an HTTP reply 12 | rpc Write(WriteRequest) returns (WriteResponse); 13 | // WriteHeader sends an HTTP response header with the provided 14 | // status code 15 | rpc WriteHeader(WriteHeaderRequest) returns (google.protobuf.Empty); 16 | // Flush is a no-op 17 | rpc Flush(google.protobuf.Empty) returns (google.protobuf.Empty); 18 | // Hijack lets the caller take over the connection 19 | rpc Hijack(google.protobuf.Empty) returns (HijackResponse); 20 | } 21 | 22 | message Header { 23 | // key is a element key in a key value pair 24 | string key = 1; 25 | // values are a list of strings coresponding to the key 26 | repeated string values = 2; 27 | } 28 | 29 | message WriteRequest { 30 | // headers represents the key-value pairs in an HTTP header 31 | repeated Header headers = 1; 32 | // payload is the write request in bytes 33 | bytes payload = 2; 34 | } 35 | 36 | message WriteResponse { 37 | // written is the number of bytes written in body 38 | int32 written = 1; 39 | } 40 | 41 | message WriteHeaderRequest { 42 | // headers represents the key-value pairs in an HTTP header 43 | repeated Header headers = 1; 44 | // status_code must be a valid HTTP 1xx-5xx status code 45 | int32 status_code = 2; 46 | } 47 | 48 | message HijackResponse { 49 | // local_network is the name of the network (for example, "tcp", "udp") 50 | string local_network = 1; 51 | // local_string is string form of address 52 | string local_string = 2; 53 | // remote_network is the name of the network (for example, "tcp", "udp") 54 | string remote_network = 3; 55 | // remote_string is string form of address 56 | string remote_string = 4; 57 | // server_addr is the address of the gRPC server serving the Conn, Reader 58 | // and Writer services which facilitate Hijacking 59 | string server_addr = 5; 60 | } 61 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/io/reader/reader.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package io.reader; 4 | 5 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/io/reader"; 6 | 7 | // Reader is an io.Reader see: https://pkg.go.dev/io#Reader 8 | service Reader { 9 | rpc Read(ReadRequest) returns (ReadResponse); 10 | } 11 | 12 | message ReadRequest { 13 | // length is the request in bytes 14 | int32 length = 1; 15 | } 16 | 17 | message ReadResponse { 18 | // read is the payload in bytes 19 | bytes read = 1; 20 | // error is an error message 21 | optional string error = 2; 22 | } 23 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/io/writer/writer.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package io.writer; 4 | 5 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/io/writer"; 6 | 7 | // Writer see: io.Writer https://pkg.go.dev/io#Writer 8 | service Writer { 9 | // Write writes len(p) bytes from p to the underlying data stream. 10 | rpc Write(WriteRequest) returns (WriteResponse); 11 | } 12 | 13 | message WriteRequest { 14 | // payload is the write request in bytes 15 | bytes payload = 1; 16 | } 17 | 18 | message WriteResponse { 19 | // written is the length of payload in bytes 20 | int32 written = 1; 21 | // error is an error message 22 | optional string error = 2; 23 | } 24 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/keystore/keystore.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package keystore; 4 | 5 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/keystore"; 6 | 7 | service Keystore { 8 | rpc GetDatabase(GetDatabaseRequest) returns (GetDatabaseResponse); 9 | } 10 | 11 | message GetDatabaseRequest { 12 | string username = 1; 13 | string password = 2; 14 | } 15 | 16 | message GetDatabaseResponse { 17 | // reserved for backward compatibility 18 | // avalanchego <=v1.7.9 used the field "1" as an id to identify the gRPC server 19 | // address which served the Database service via the now removed service broker 20 | reserved 1; 21 | // server_addr is the address of the gRPC server hosting the Database service 22 | string server_addr = 2; 23 | } 24 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/message/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package message; 4 | 5 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/message"; 6 | 7 | message Message { 8 | oneof message { 9 | Tx tx = 1; 10 | } 11 | } 12 | 13 | message Tx { 14 | // The byte representation of this transaction. 15 | bytes tx = 1; 16 | } 17 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/messenger/messenger.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package messenger; 4 | 5 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/messenger"; 6 | 7 | service Messenger { 8 | rpc Notify(NotifyRequest) returns (NotifyResponse); 9 | } 10 | 11 | enum Message { 12 | MESSAGE_UNSPECIFIED = 0; 13 | MESSAGE_BUILD_BLOCK = 1; 14 | MESSAGE_STATE_SYNC_FINISHED = 2; 15 | } 16 | 17 | message NotifyRequest { 18 | Message message = 1; 19 | } 20 | 21 | message NotifyResponse {} 22 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/net/conn/conn.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package net.conn; 4 | 5 | import "google/protobuf/empty.proto"; 6 | 7 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/net/conn"; 8 | 9 | // Conn is a net.Conn see: https://pkg.go.dev/net#Conn 10 | service Conn { 11 | // Read reads data from the connection. 12 | rpc Read(ReadRequest) returns (ReadResponse); 13 | // Write writes data to the connection. 14 | rpc Write(WriteRequest) returns (WriteResponse); 15 | // Close closes the connection. 16 | rpc Close(google.protobuf.Empty) returns (google.protobuf.Empty); 17 | // SetDeadline sets the read and write deadlines associated 18 | // with the connection. 19 | rpc SetDeadline(SetDeadlineRequest) returns (google.protobuf.Empty); 20 | // SetReadDeadline sets the deadline for future Read calls 21 | // and any currently-blocked Read call. 22 | rpc SetReadDeadline(SetDeadlineRequest) returns (google.protobuf.Empty); 23 | // SetWriteDeadline sets the deadline for future Write calls 24 | // and any currently-blocked Write call. 25 | rpc SetWriteDeadline(SetDeadlineRequest) returns (google.protobuf.Empty); 26 | } 27 | 28 | message ReadRequest { 29 | // length of the request in bytes 30 | int32 length = 1; 31 | } 32 | 33 | message ReadResponse { 34 | // read is the payload in bytes 35 | bytes read = 1; 36 | // error is an error message 37 | optional string error = 2; 38 | } 39 | 40 | message WriteRequest { 41 | // payload is the write request in bytes 42 | bytes payload = 1; 43 | } 44 | 45 | message WriteResponse { 46 | // length of the response in bytes 47 | int32 length = 1; 48 | // error is an error message 49 | optional string error = 2; 50 | } 51 | 52 | message SetDeadlineRequest { 53 | // time represents an instant in time in bytes 54 | bytes time = 1; 55 | } 56 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/sdk/sdk.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package sdk; 4 | 5 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/sdk"; 6 | 7 | message PullGossipRequest { 8 | // TODO: Remove reservation after v1.11.x activates. 9 | reserved 1; 10 | bytes salt = 2; 11 | bytes filter = 3; 12 | } 13 | 14 | message PullGossipResponse { 15 | repeated bytes gossip = 1; 16 | } 17 | 18 | message PushGossip { 19 | repeated bytes gossip = 1; 20 | } 21 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/sharedmemory/sharedmemory.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package sharedmemory; 4 | 5 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/sharedmemory"; 6 | 7 | service SharedMemory { 8 | rpc Get(GetRequest) returns (GetResponse); 9 | rpc Indexed(IndexedRequest) returns (IndexedResponse); 10 | rpc Apply(ApplyRequest) returns (ApplyResponse); 11 | } 12 | 13 | message BatchPut { 14 | bytes key = 1; 15 | bytes value = 2; 16 | } 17 | 18 | message BatchDelete { 19 | bytes key = 1; 20 | } 21 | 22 | message Batch { 23 | repeated BatchPut puts = 1; 24 | repeated BatchDelete deletes = 2; 25 | } 26 | 27 | message AtomicRequest { 28 | repeated bytes remove_requests = 1; 29 | repeated Element put_requests = 2; 30 | bytes peer_chain_id = 3; 31 | } 32 | 33 | message Element { 34 | bytes key = 1; 35 | bytes value = 2; 36 | repeated bytes traits = 3; 37 | } 38 | 39 | message GetRequest { 40 | bytes peer_chain_id = 1; 41 | repeated bytes keys = 2; 42 | } 43 | 44 | message GetResponse { 45 | repeated bytes values = 1; 46 | } 47 | 48 | message IndexedRequest { 49 | bytes peer_chain_id = 1; 50 | repeated bytes traits = 2; 51 | bytes start_trait = 3; 52 | bytes start_key = 4; 53 | int32 limit = 5; 54 | } 55 | 56 | message IndexedResponse { 57 | repeated bytes values = 1; 58 | bytes last_trait = 2; 59 | bytes last_key = 3; 60 | } 61 | 62 | message ApplyRequest { 63 | repeated AtomicRequest requests = 1; 64 | repeated Batch batches = 2; 65 | } 66 | 67 | message ApplyResponse {} 68 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/validatorstate/validator_state.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package validatorstate; 4 | 5 | import "google/protobuf/empty.proto"; 6 | 7 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/validatorstate"; 8 | 9 | service ValidatorState { 10 | // GetMinimumHeight returns the minimum height of the blocks in the optimal 11 | // proposal window. 12 | rpc GetMinimumHeight(google.protobuf.Empty) returns (GetMinimumHeightResponse); 13 | // GetCurrentHeight returns the current height of the P-chain. 14 | rpc GetCurrentHeight(google.protobuf.Empty) returns (GetCurrentHeightResponse); 15 | // GetSubnetID returns the subnetID of the provided chain. 16 | rpc GetSubnetID(GetSubnetIDRequest) returns (GetSubnetIDResponse); 17 | // GetValidatorSet returns the weights of the nodeIDs for the provided 18 | // subnet at the requested P-chain height. 19 | rpc GetValidatorSet(GetValidatorSetRequest) returns (GetValidatorSetResponse); 20 | } 21 | 22 | message GetMinimumHeightResponse { 23 | uint64 height = 1; 24 | } 25 | 26 | message GetCurrentHeightResponse { 27 | uint64 height = 1; 28 | } 29 | 30 | message GetSubnetIDRequest { 31 | bytes chain_id = 1; 32 | } 33 | 34 | message GetSubnetIDResponse { 35 | bytes subnet_id = 1; 36 | } 37 | 38 | message GetValidatorSetRequest { 39 | uint64 height = 1; 40 | bytes subnet_id = 2; 41 | } 42 | 43 | message Validator { 44 | bytes node_id = 1; 45 | uint64 weight = 2; 46 | bytes public_key = 3; 47 | } 48 | 49 | message GetValidatorSetResponse { 50 | repeated Validator validators = 1; 51 | } 52 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/vm/runtime/runtime.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package vm.runtime; 4 | 5 | import "google/protobuf/empty.proto"; 6 | 7 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/vm/manager"; 8 | 9 | // Manages the lifecycle of a subnet VM process. 10 | service Runtime { 11 | // Initialize a VM Runtime. 12 | rpc Initialize(InitializeRequest) returns (google.protobuf.Empty); 13 | } 14 | 15 | message InitializeRequest { 16 | // ProtocolVersion is used to identify incompatibilities with AvalancheGo and a VM. 17 | uint32 protocol_version = 1; 18 | // Address of the gRPC server endpoint serving the handshake logic. 19 | // Example: 127.0.0.1:50001 20 | string addr = 2; 21 | } 22 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/avalanche/warp/message.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package warp; 4 | 5 | option go_package = "github.com/ava-labs/avalanchego/proto/pb/warp"; 6 | 7 | service Signer { 8 | rpc Sign(SignRequest) returns (SignResponse); 9 | } 10 | 11 | message SignRequest { 12 | uint32 network_id = 1; 13 | bytes source_chain_id = 2; 14 | bytes payload = 3; 15 | } 16 | 17 | message SignResponse { 18 | bytes signature = 1; 19 | } 20 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/static/google/protobuf/empty.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option go_package = "google.golang.org/protobuf/types/known/emptypb"; 37 | option java_package = "com.google.protobuf"; 38 | option java_outer_classname = "EmptyProto"; 39 | option java_multiple_files = true; 40 | option objc_class_prefix = "GPB"; 41 | option cc_enable_arenas = true; 42 | 43 | // A generic empty message that you can re-use to avoid defining duplicated 44 | // empty messages in your APIs. A typical example is to use it as the request 45 | // or the response type of an API method. For instance: 46 | // 47 | // service Foo { 48 | // rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); 49 | // } 50 | // 51 | message Empty {} 52 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/proto/protos/static/helloworld/helloworld.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 gRPC authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package helloworld; 18 | 19 | // The greeting service definition. 20 | service Greeter { 21 | // Sends a greeting 22 | rpc SayHello (HelloRequest) returns (HelloReply) {} 23 | } 24 | 25 | // The request message containing the user's name. 26 | message HelloRequest { 27 | string name = 1; 28 | } 29 | 30 | // The response message containing the greetings 31 | message HelloReply { 32 | string message = 1; 33 | } -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/README.md: -------------------------------------------------------------------------------- 1 | # The Rust VM SDK 2 | 3 | The Rust SDK provides a series of abstractions for building Avalanche VMs in pure Rust. Modules for consensus, gossip, and all JSON-RPC endpoints are provided. 4 | 5 | The following VMs were built with the SDK: 6 | * Simple Rust VM: [TimestampVM](https://github.com/ava-labs/timestampvm-rs) 7 | * Complex Rust VM: [SpacesVM](https://github.com/ava-labs/spacesvm-rs) 8 | 9 | See [this walkthrough guide](https://docs.avax.network/build/vm/create/rust-vm) for detailed information on how to use the SDK to build an Avalanche VM. 10 | 11 | If you are interested in contributing to the SDK, or have a question, please open a [Github Issue](https://github.com/ava-labs/avalanche-rs/issues/new) to discuss. 12 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/config/consensus.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | /// ref. 4 | /// 5 | /// ref. 6 | #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] 7 | #[serde(rename_all = "camelCase")] 8 | pub struct SnowballParameters { 9 | /// Sample size. 10 | pub k: i32, 11 | /// Quorum size. 12 | pub alpha: i32, 13 | 14 | /// Virtuous commit threshold. 15 | pub beta_virtuous: i32, 16 | /// Rogue commit threshold. 17 | pub beta_rogue: i32, 18 | 19 | /// Minimum number of concurrent polls for finalizing consensus. 20 | pub concurrent_repolls: i32, 21 | /// Optimal number of processing containers in consensus. 22 | pub optimal_processing: i32, 23 | 24 | /// Maximum number of processing items to be considered healthy. 25 | pub max_outstanding_items: i32, 26 | /// Maximum amount of time an item should be processing and still be healthy. 27 | pub max_item_processing_time: i64, 28 | 29 | pub mixed_query_num_push_vdr: i32, 30 | pub mixed_query_num_push_non_vdr: i32, 31 | } 32 | 33 | impl Default for SnowballParameters { 34 | /// The defaults do not match with the ones in avalanchego, 35 | /// as this is for avalanche-ops based deployments. 36 | fn default() -> Self { 37 | Self { 38 | k: 20, 39 | alpha: 15, 40 | beta_virtuous: 15, 41 | beta_rogue: 20, 42 | concurrent_repolls: 4, 43 | optimal_processing: 50, 44 | max_outstanding_items: 1024, 45 | max_item_processing_time: 2 * 1000 * 1000 * 1000, // 2-minute 46 | mixed_query_num_push_vdr: 10, 47 | mixed_query_num_push_non_vdr: 0, 48 | } 49 | } 50 | } 51 | 52 | #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] 53 | #[serde(rename_all = "camelCase")] 54 | pub struct Parameters { 55 | /// Embeds "SnowballParameters" at the same level as other fields. 56 | #[serde(flatten)] 57 | pub snowball_parameters: SnowballParameters, 58 | pub parents: i32, 59 | pub batch_size: i32, 60 | } 61 | 62 | impl Default for Parameters { 63 | /// The defaults do not match with the ones in avalanchego, 64 | /// as this is for avalanche-ops based deployments. 65 | fn default() -> Self { 66 | Self { 67 | snowball_parameters: SnowballParameters::default(), 68 | parents: 5, 69 | batch_size: 30, 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/config/gossip.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] 4 | #[serde(rename_all = "camelCase")] 5 | pub struct SenderConfig { 6 | pub gossip_accepted_frontier_validator_size: u32, 7 | pub gossip_accepted_frontier_non_validator_size: u32, 8 | pub gossip_accepted_frontier_peer_size: u32, 9 | pub gossip_on_accept_validator_size: u32, 10 | pub gossip_on_accept_non_validator_size: u32, 11 | pub gossip_on_accept_peer_size: u32, 12 | pub app_gossip_validator_size: u32, 13 | pub app_gossip_non_validator_size: u32, 14 | pub app_gossip_peer_size: u32, 15 | } 16 | 17 | impl Default for SenderConfig { 18 | /// The defaults do not match with the ones in avalanchego, 19 | /// as this is for avalanche-ops based deployments. 20 | fn default() -> Self { 21 | Self { 22 | gossip_accepted_frontier_validator_size: 0, 23 | gossip_accepted_frontier_non_validator_size: 0, 24 | gossip_accepted_frontier_peer_size: 15, 25 | gossip_on_accept_validator_size: 0, 26 | gossip_on_accept_non_validator_size: 0, 27 | gossip_on_accept_peer_size: 10, 28 | app_gossip_validator_size: 10, 29 | app_gossip_non_validator_size: 0, 30 | app_gossip_peer_size: 0, 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/mod.rs: -------------------------------------------------------------------------------- 1 | //! Avalanche Rust SDK: Types and building blocks to assist with creating a custom `subnet` VM. 2 | //! 3 | //! Example VM's created with SDK: 4 | //! * Simple Rust VM: [TimestampVM](https://github.com/ava-labs/timestampvm-rs) 5 | //! * Complex Rust VM: [SpacesVM](https://github.com/ava-labs/spacesvm-rs) 6 | 7 | pub mod config; 8 | pub mod rpc; 9 | 10 | use std::io::{self, Error, ErrorKind}; 11 | 12 | use crate::ids; 13 | 14 | /// Convert a given Vm name to an encoded Vm Id. 15 | pub fn vm_name_to_id(s: impl AsRef<[u8]>) -> io::Result { 16 | let d = s.as_ref(); 17 | if d.len() > ids::LEN { 18 | return Err(Error::new( 19 | ErrorKind::Other, 20 | format!("non-hashed name must be <= 32 bytes, found {}", d.len()), 21 | )); 22 | } 23 | Ok(ids::Id::from_slice(d)) 24 | } 25 | 26 | /// RUST_LOG=debug cargo test --package avalanche-types --lib -- subnet::test_vm_name_to_id --exact --show-output 27 | #[test] 28 | fn test_vm_name_to_id() { 29 | let id = vm_name_to_id("timestampvm").unwrap(); 30 | println!("{id}"); 31 | assert_eq!( 32 | id.to_string(), 33 | "tGas3T58KzdjcJ2iKSyiYsWiqYctRXaPTqBCA11BqEkNg8kPc" 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/consensus/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod snowman; 2 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/consensus/snowman.rs: -------------------------------------------------------------------------------- 1 | use std::io::Result; 2 | 3 | use crate::{choices::status::Status, ids::Id}; 4 | 5 | /// ref. 6 | #[tonic::async_trait] 7 | pub trait Block: Decidable + Send + Sync { 8 | /// Returns the binary representation of this block. 9 | /// 10 | /// This is used for sending blocks to peers. The bytes should be able to be 11 | /// parsed into the same block on another node. 12 | async fn bytes(&self) -> &[u8]; 13 | 14 | /// Returns the height of the block in the chain. 15 | async fn height(&self) -> u64; 16 | 17 | /// Time this block was proposed at. This value should be consistent across 18 | /// all nodes. If this block hasn't been successfully verified, any value can 19 | /// be returned. If this block is the last accepted block, the timestamp must 20 | /// be returned correctly. Otherwise, accepted blocks can return any value. 21 | async fn timestamp(&self) -> u64; 22 | 23 | /// Returns the ID of this block's parent. 24 | async fn parent(&self) -> Id; 25 | 26 | /// Returns error if the block can not be verified. 27 | async fn verify(&mut self) -> Result<()>; 28 | } 29 | 30 | /// ref. 31 | #[tonic::async_trait] 32 | pub trait Decidable { 33 | /// Returns a unique ID for this element. 34 | /// 35 | /// Typically, this is implemented by using a cryptographic hash of a 36 | /// binary representation of this element. An element should return the same 37 | /// IDs upon repeated calls. 38 | async fn id(&self) -> Id; 39 | 40 | /// Status returns this element's current status. 41 | /// 42 | /// If Accept has been called on an element with this ID, Accepted should be 43 | /// returned. Similarly, if Reject has been called on an element with this 44 | /// ID, Rejected should be returned. If the contents of this element are 45 | /// unknown, then Unknown should be returned. Otherwise, Processing should be 46 | /// returned. 47 | async fn status(&self) -> Status; 48 | 49 | /// Accept this element. 50 | /// 51 | /// This element will be accepted by every correct node in the network. 52 | async fn accept(&mut self) -> Result<()>; 53 | 54 | /// Rejects this element. 55 | /// 56 | /// This element will not be accepted by any correct node in the network. 57 | async fn reject(&mut self) -> Result<()>; 58 | } 59 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/context.rs: -------------------------------------------------------------------------------- 1 | //! Snow Context. 2 | use crate::{ 3 | ids::node::Id as NodeId, 4 | ids::Id, 5 | proto::pb::{ 6 | aliasreader::alias_reader_client::AliasReaderClient, 7 | keystore::keystore_client::KeystoreClient, 8 | sharedmemory::shared_memory_client::SharedMemoryClient, 9 | }, 10 | }; 11 | use tonic::transport::Channel; 12 | 13 | use super::snow::validators; 14 | 15 | /// ref. 16 | #[derive(Debug, Clone)] 17 | pub struct Context { 18 | pub network_id: u32, 19 | pub subnet_id: Id, 20 | pub chain_id: Id, 21 | pub node_id: NodeId, 22 | pub x_chain_id: Id, 23 | pub c_chain_id: Id, 24 | pub avax_asset_id: Id, 25 | pub keystore: KeystoreClient, 26 | pub shared_memory: SharedMemoryClient, 27 | pub bc_lookup: AliasReaderClient, 28 | pub chain_data_dir: String, 29 | pub validator_state: S, 30 | // TODO metrics 31 | } 32 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/database/batch.rs: -------------------------------------------------------------------------------- 1 | use std::{io::Result, sync::Arc}; 2 | 3 | use tokio::sync::Mutex; 4 | 5 | use super::BoxedDatabase; 6 | 7 | /// If, when a batch is reset, the cap(batch)/len(batch) > MAX_EXCESS_CAPACITY_FACTOR, 8 | /// Higher value for MAX_EXCESS_CAPACITY_FACTOR --> less aggressive array downsizing --> less memory allocations 9 | /// but more unnecessary data in the underlying array that can't be garbage collected. 10 | pub const MAX_EXCESS_CAPACITY_FACTOR: usize = 4; 11 | 12 | /// The underlying array's capacity will be reduced by a factor of CAPACITY_REDUCTION_FACTOR. 13 | /// Higher value for CapacityReductionFactor --> more aggressive array downsizing --> more memory allocations 14 | /// but less unnecessary data in the underlying array that can't be garbage collected. 15 | pub const CAPACITY_REDUCTION_FACTOR: usize = 2; 16 | 17 | /// ref. 18 | #[tonic::async_trait] 19 | pub trait Batch: CloneBox { 20 | async fn put(&mut self, key: &[u8], value: &[u8]) -> Result<()>; 21 | async fn delete(&mut self, key: &[u8]) -> Result<()>; 22 | 23 | /// Retrieves the amount of data queued up for writing, this includes 24 | /// the keys, values, and deleted keys. 25 | async fn size(&self) -> Result; 26 | 27 | /// Flushes any accumulated data to disk. 28 | async fn write(&self) -> Result<()>; 29 | 30 | /// Resets the batch for reuse. 31 | async fn reset(&mut self); 32 | 33 | /// Replays the batch contents in the same order they were written 34 | /// to the batch. 35 | async fn replay(&self, k: Arc>) -> Result<()>; 36 | } 37 | 38 | /// Helper type which defines a thread safe boxed Batch trait. 39 | pub type BoxedBatch = Box; 40 | 41 | pub trait CloneBox { 42 | /// Returns a Boxed clone of the underlying Batch trait implementation. 43 | fn clone_box(&self) -> BoxedBatch; 44 | } 45 | 46 | impl CloneBox for T 47 | where 48 | T: 'static + Batch + Clone + Send + Sync, 49 | { 50 | fn clone_box(&self) -> BoxedBatch { 51 | Box::new(self.clone()) 52 | } 53 | } 54 | 55 | impl Clone for BoxedBatch { 56 | fn clone(&self) -> BoxedBatch { 57 | self.clone_box() 58 | } 59 | } 60 | 61 | /// ref. 62 | #[tonic::async_trait] 63 | pub trait Batcher { 64 | /// Creates a write-only database that buffers changes to its host db 65 | /// until a final write is called. 66 | async fn new_batch(&self) -> Result; 67 | } 68 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/database/iterator.rs: -------------------------------------------------------------------------------- 1 | use std::io::Result; 2 | 3 | /// ref. 4 | #[tonic::async_trait] 5 | pub trait Iterator { 6 | /// Attempts to move the iterator to the next key/value pair. It returns whether 7 | /// the iterator successfully moved to a new key/value pair. 8 | /// The iterator may return false if the underlying database has been closed 9 | /// before the iteration has completed, in which case future calls to Error() 10 | /// must return ErrorKind::Other, "database closed") 11 | async fn next(&mut self) -> Result; 12 | 13 | /// Returns any accumulated error. Exhausting all the key/value pairs 14 | /// is not considered to be an error. 15 | /// Error should be called after all key/value pairs have been exhausted ie. 16 | /// after Next() has returned false. 17 | async fn error(&mut self) -> Result<()>; 18 | 19 | /// Returns the key of the current key/value pair, or empty slice if done. 20 | async fn key(&self) -> Result<&[u8]>; 21 | 22 | /// Returns the key of the current k&ey/value pair, or empty slice if done. 23 | async fn value(&self) -> Result<&[u8]>; 24 | 25 | /// Releases associated resources. Release should always succeed and 26 | /// can be called multiple times without causing error. 27 | async fn release(&mut self); 28 | } 29 | 30 | /// Helper type which defines a thread safe boxed Iterator interface. 31 | pub type BoxedIterator = Box; 32 | 33 | /// ref. 34 | #[tonic::async_trait] 35 | pub trait Iteratee { 36 | /// Creates an iterator over the entire keyspace contained within 37 | /// the key-value database. 38 | async fn new_iterator(&self) -> Result; 39 | 40 | /// Creates an iterator over a subset of database content starting 41 | /// at a particular initial key. 42 | async fn new_iterator_with_start(&self, start: &[u8]) -> Result; 43 | 44 | /// Creates an iterator over a subset of database content with a 45 | /// particular key prefix. 46 | async fn new_iterator_with_prefix(&self, prefix: &[u8]) -> Result; 47 | 48 | /// Creates an iterator over a subset of database content with a 49 | /// particular key prefix starting at a specified key. 50 | async fn new_iterator_with_start_and_prefix( 51 | &self, 52 | start: &[u8], 53 | prefix: &[u8], 54 | ) -> Result; 55 | } 56 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/database/manager/mod.rs: -------------------------------------------------------------------------------- 1 | //! Database manager. 2 | pub mod versioned_database; 3 | 4 | use std::{ 5 | io::{self, Error, ErrorKind}, 6 | sync::Arc, 7 | }; 8 | 9 | use tokio::sync::RwLock; 10 | 11 | use crate::subnet::rpc::database::manager::versioned_database::VersionedDatabase; 12 | 13 | /// ref. 14 | #[tonic::async_trait] 15 | pub trait Manager { 16 | async fn current(&self) -> io::Result; 17 | async fn previous(&self) -> Option; 18 | async fn close(&self) -> io::Result<()>; 19 | } 20 | 21 | #[derive(Clone)] 22 | pub struct DatabaseManager { 23 | inner: Arc>>, 24 | } 25 | 26 | impl DatabaseManager { 27 | /// Returns a database manager from a Vec of versioned database. 28 | pub fn from_databases(dbs: Vec) -> Self { 29 | Self { 30 | inner: Arc::new(RwLock::new(dbs)), 31 | } 32 | } 33 | } 34 | 35 | #[tonic::async_trait] 36 | impl Manager for DatabaseManager { 37 | /// Returns the database with the current database version. 38 | async fn current(&self) -> io::Result { 39 | let dbs = self.inner.read().await; 40 | Ok(dbs[0].clone()) 41 | } 42 | 43 | /// Returns the database prior to the current database and true if a 44 | // previous database exists. 45 | async fn previous(&self) -> Option { 46 | let dbs = self.inner.read().await; 47 | 48 | if dbs.len() < 2 { 49 | return None; 50 | } 51 | Some(dbs[1].clone()) 52 | } 53 | 54 | /// Close all of the databases controlled by the manager. 55 | async fn close(&self) -> io::Result<()> { 56 | let dbs = self.inner.read().await; 57 | 58 | let mut errors = Vec::with_capacity(dbs.len()); 59 | for db in dbs.iter() { 60 | let db = &db.db; 61 | match db.close().await { 62 | Ok(_) => continue, 63 | Err(e) => errors.push(e.to_string()), 64 | } 65 | } 66 | 67 | if !errors.is_empty() { 68 | return Err(Error::new( 69 | ErrorKind::Other, 70 | errors.first().unwrap().to_string(), 71 | )); 72 | } 73 | Ok(()) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/database/manager/versioned_database.rs: -------------------------------------------------------------------------------- 1 | use std::io::Result; 2 | 3 | use semver::Version; 4 | 5 | use crate::subnet::rpc::database::{self, BoxedDatabase}; 6 | 7 | /// ref. 8 | #[derive(Clone)] 9 | pub struct VersionedDatabase { 10 | pub db: BoxedDatabase, 11 | pub version: Version, 12 | } 13 | 14 | impl VersionedDatabase { 15 | pub fn new(db: BoxedDatabase, version: Version) -> Self { 16 | Self { db, version } 17 | } 18 | } 19 | 20 | #[tonic::async_trait] 21 | impl database::VersionedDatabase for VersionedDatabase { 22 | async fn close(&mut self) -> Result<()> { 23 | let db = &self.db; 24 | match db.close().await { 25 | Ok(_) => Ok(()), 26 | Err(e) => Err(e), 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/database/nodb.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Error, Result}; 2 | 3 | use super::iterator::BoxedIterator; 4 | 5 | pub struct Iterator { 6 | err: Option, 7 | } 8 | 9 | /// NoDB Iterator is used in cases where condition expects an empty iterator. 10 | /// 11 | /// ref. 12 | impl Iterator { 13 | pub fn new_boxed(err: Option) -> BoxedIterator { 14 | Box::new(Iterator { err }) 15 | } 16 | } 17 | 18 | #[tonic::async_trait] 19 | impl crate::subnet::rpc::database::iterator::Iterator for Iterator { 20 | /// Implements the \[`crate::subnet::rpc::database::Iterator`\] trait. 21 | async fn next(&mut self) -> Result { 22 | Ok(false) 23 | } 24 | 25 | /// Implements the \[`crate::subnet::rpc::database::Iterator`\] trait. 26 | async fn error(&mut self) -> Result<()> { 27 | if let Some(err) = &self.err { 28 | return Err(Error::new(err.kind(), err.to_string())); 29 | } 30 | Ok(()) 31 | } 32 | 33 | /// Implements the \[`crate::subnet::rpc::database::Iterator`\] trait. 34 | async fn key(&self) -> Result<&[u8]> { 35 | Ok(&[]) 36 | } 37 | 38 | /// Implements the \[`crate::subnet::rpc::database::Iterator`\] trait. 39 | async fn value(&self) -> Result<&[u8]> { 40 | Ok(&[]) 41 | } 42 | 43 | /// Implements the \[`crate::subnet::rpc::database::Iterator`\] trait. 44 | async fn release(&mut self) {} 45 | } 46 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/database/rpcdb/mod.rs: -------------------------------------------------------------------------------- 1 | //! Implements a database exposed by RPC. 2 | pub mod client; 3 | pub mod server; 4 | 5 | use std::collections::HashMap; 6 | 7 | use lazy_static::lazy_static; 8 | 9 | use crate::proto::pb; 10 | 11 | lazy_static! { 12 | static ref ERROR_TO_ERROR_CODE: HashMap<&'static str, i32> = { 13 | let mut m = HashMap::new(); 14 | m.insert("database closed", pb::rpcdb::Error::Closed.into()); 15 | m.insert("not found", pb::rpcdb::Error::NotFound.into()); 16 | m 17 | }; 18 | } 19 | 20 | pub fn error_to_error_code(msg: &str) -> i32 { 21 | match ERROR_TO_ERROR_CODE.get(msg) { 22 | None => 0_i32, 23 | Some(code) => *code, 24 | } 25 | } 26 | 27 | #[test] 28 | fn database_errors() { 29 | assert_eq!( 30 | *ERROR_TO_ERROR_CODE.get("database closed").unwrap(), 31 | pb::rpcdb::Error::Closed as i32 32 | ); 33 | assert_eq!( 34 | *ERROR_TO_ERROR_CODE.get("not found").unwrap(), 35 | pb::rpcdb::Error::NotFound as i32 36 | ); 37 | assert!(ERROR_TO_ERROR_CODE.get("ohh snap!").is_none()); 38 | } 39 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/health.rs: -------------------------------------------------------------------------------- 1 | //! Provides health checking. 2 | use std::io::Result; 3 | 4 | /// Checkable can have its health checked 5 | /// 6 | /// ref. 7 | #[tonic::async_trait] 8 | pub trait Checkable { 9 | async fn health_check(&self) -> Result>; 10 | } 11 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/http/handle/mod.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | use bytes::Bytes; 4 | 5 | use crate::proto::http::Element; 6 | 7 | #[tonic::async_trait] 8 | pub trait Handle: Send + Sync + Clone { 9 | /// Provides handling of HTTP requests. 10 | async fn request(&self, req: &Bytes, headers: &[Element]) -> io::Result<(Bytes, Vec)>; 11 | } 12 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/http/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod handle; 3 | pub mod server; 4 | 5 | /// ref: 6 | #[tonic::async_trait] 7 | pub trait Handler { 8 | async fn serve_http( 9 | &mut self, 10 | req: http::Request>, 11 | ) -> std::io::Result>>; 12 | 13 | async fn serve_http_simple( 14 | &mut self, 15 | req: http::Request>, 16 | ) -> std::io::Result>>; 17 | } 18 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/http/server.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use crate::proto::pb::{ 4 | self, 5 | google::protobuf::Empty, 6 | http::{HandleSimpleHttpRequest, HandleSimpleHttpResponse, HttpRequest}, 7 | }; 8 | 9 | use tonic::codegen::http; 10 | 11 | use super::handle::Handle; 12 | 13 | #[derive(Clone)] 14 | pub struct Server { 15 | /// handler generated from create_handlers 16 | handle: Arc, 17 | } 18 | 19 | impl Server 20 | where 21 | T: Handle + Send + Sync + 'static, 22 | { 23 | pub fn new(handler: T) -> Self { 24 | Server { 25 | handle: Arc::new(handler), 26 | } 27 | } 28 | } 29 | 30 | #[tonic::async_trait] 31 | impl pb::http::http_server::Http for Server 32 | where 33 | T: Handle + Send + Sync + 'static, 34 | { 35 | /// handles http requests including websockets 36 | async fn handle( 37 | &self, 38 | _request: tonic::Request, 39 | ) -> Result, tonic::Status> { 40 | Err(tonic::Status::unimplemented("handle")) 41 | } 42 | 43 | /// handles http simple (non web-socket) requests 44 | async fn handle_simple( 45 | &self, 46 | request: tonic::Request, 47 | ) -> Result, tonic::Status> { 48 | let request = request.into_inner(); 49 | 50 | let (body, headers) = self.handle.request(&request.body, &request.headers).await?; 51 | 52 | Ok(tonic::Response::new(HandleSimpleHttpResponse { 53 | code: http::StatusCode::OK.as_u16() as i32, 54 | body, 55 | headers, 56 | })) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod consensus; 2 | pub mod context; 3 | pub mod database; 4 | pub mod errors; 5 | pub mod health; 6 | pub mod http; 7 | pub mod runtime; 8 | pub mod snow; 9 | pub mod snowman; 10 | pub mod utils; 11 | pub mod vm; 12 | 13 | #[cfg(any(doc, feature = "subnet_metrics"))] 14 | pub mod metrics; 15 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/runtime/client.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Error, ErrorKind, Result}; 2 | 3 | use tonic::transport::Channel; 4 | 5 | use crate::proto::vm::runtime::{runtime_client::RuntimeClient, InitializeRequest}; 6 | 7 | use super::Initializer; 8 | 9 | /// Client is an implementation of [`crate::subnet::rpc::runtime::Initializer`] that talks over RPC. 10 | /// 11 | /// ref. 12 | #[derive(Debug, Clone)] 13 | pub struct Client { 14 | inner: RuntimeClient, 15 | } 16 | 17 | impl Client { 18 | pub fn new(client_conn: Channel) -> Self { 19 | Self { 20 | inner: RuntimeClient::new(client_conn) 21 | .max_decoding_message_size(usize::MAX) 22 | .max_encoding_message_size(usize::MAX), 23 | } 24 | } 25 | } 26 | 27 | #[tonic::async_trait] 28 | impl Initializer for Client { 29 | async fn initialize(&self, protocol_version: u32, vm_server_addr: &str) -> Result<()> { 30 | let mut client = self.inner.clone(); 31 | 32 | client 33 | .initialize(InitializeRequest { 34 | protocol_version, 35 | addr: vm_server_addr.to_owned(), 36 | }) 37 | .await 38 | .map_err(|e| Error::new(ErrorKind::Other, format!("vm initializer failed: {e}")))?; 39 | 40 | Ok(()) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/runtime/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | 3 | use std::io::Result; 4 | 5 | /// Runtime client dial timeout in seconds. 6 | pub(crate) const DEFAULT_DIAL_TIMEOUT: u64 = 10; 7 | /// Address of the VM runtime engine server. 8 | pub(crate) const ENGINE_ADDR_KEY: &str = "AVALANCHE_VM_RUNTIME_ENGINE_ADDR"; 9 | 10 | /// ref. 11 | #[tonic::async_trait] 12 | pub trait Initializer { 13 | // Provides AvalancheGo with compatibility, networking and process 14 | // information of a VM. 15 | async fn initialize(&self, protocol_version: u32, vm_server_addr: &str) -> Result<()>; 16 | } 17 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/snow/engine/common/appsender/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod server; 3 | 4 | use std::io::Result; 5 | 6 | use crate::ids; 7 | 8 | /// AppSender sends application (Vm) level messages. 9 | /// 10 | /// ref. 11 | #[tonic::async_trait] 12 | pub trait AppSender: Send + Sync + CloneBox { 13 | async fn send_app_request( 14 | &self, 15 | node_ids: ids::node::Set, 16 | request_id: u32, 17 | request: Vec, 18 | ) -> Result<()>; 19 | async fn send_app_response( 20 | &self, 21 | node_if: ids::node::Id, 22 | request_id: u32, 23 | response: Vec, 24 | ) -> Result<()>; 25 | async fn send_app_gossip(&self, msg: Vec) -> Result<()>; 26 | async fn send_app_gossip_specific(&self, node_ids: ids::node::Set, msg: Vec) -> Result<()>; 27 | async fn send_cross_chain_app_request( 28 | &self, 29 | chain_id: ids::Id, 30 | request_id: u32, 31 | app_request_bytes: Vec, 32 | ) -> Result<()>; 33 | async fn send_cross_chain_app_response( 34 | &self, 35 | chain_id: ids::Id, 36 | request_id: u32, 37 | app_response_bytes: Vec, 38 | ) -> Result<()>; 39 | } 40 | 41 | pub trait CloneBox { 42 | fn clone_box(&self) -> Box; 43 | } 44 | 45 | impl CloneBox for T 46 | where 47 | T: 'static + AppSender + Clone + Send + Sync, 48 | { 49 | fn clone_box(&self) -> Box { 50 | Box::new(self.clone()) 51 | } 52 | } 53 | 54 | impl Clone for Box { 55 | fn clone(&self) -> Box { 56 | self.clone_box() 57 | } 58 | } 59 | 60 | #[tokio::test] 61 | async fn clone_box_test() { 62 | use crate::subnet::rpc::snow::engine::common::appsender::client::AppSenderClient; 63 | use tokio::net::TcpListener; 64 | use tonic::transport::Channel; 65 | 66 | let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); 67 | let addr = listener.local_addr().unwrap(); 68 | let client_conn = Channel::builder(format!("http://{}", addr).parse().unwrap()) 69 | .connect() 70 | .await 71 | .unwrap(); 72 | let _app_sender = AppSenderClient::new(client_conn).clone(); 73 | } 74 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/snow/engine/common/engine.rs: -------------------------------------------------------------------------------- 1 | use std::io::Result; 2 | 3 | use crate::ids; 4 | use chrono::{DateTime, Utc}; 5 | 6 | /// ref. 7 | #[tonic::async_trait] 8 | pub trait NetworkAppHandler { 9 | async fn app_request( 10 | &self, 11 | node_id: &ids::node::Id, 12 | request_id: u32, 13 | deadline: DateTime, 14 | request: &[u8], 15 | ) -> Result<()>; 16 | async fn app_request_failed(&self, node_id: &ids::node::Id, request_id: u32) -> Result<()>; 17 | async fn app_response( 18 | &self, 19 | node_id: &ids::node::Id, 20 | request_id: u32, 21 | response: &[u8], 22 | ) -> Result<()>; 23 | async fn app_gossip(&self, node_id: &ids::node::Id, msg: &[u8]) -> Result<()>; 24 | } 25 | 26 | /// ref. 27 | #[tonic::async_trait] 28 | pub trait CrossChainAppHandler { 29 | async fn cross_chain_app_request( 30 | &self, 31 | chain_id: &ids::Id, 32 | request_id: u32, 33 | deadline: DateTime, 34 | request: &[u8], 35 | ) -> Result<()>; 36 | async fn cross_chain_app_request_failed( 37 | &self, 38 | chain_id: &ids::Id, 39 | request_id: u32, 40 | ) -> Result<()>; 41 | async fn cross_chain_app_response( 42 | &self, 43 | chain_id: &ids::Id, 44 | request_id: u32, 45 | response: &[u8], 46 | ) -> Result<()>; 47 | } 48 | 49 | // Defines how a consensus engine reacts to app specific messages. 50 | // Functions only return fatal errors. 51 | pub trait AppHandler: NetworkAppHandler + CrossChainAppHandler {} 52 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/snow/engine/common/http_handler.rs: -------------------------------------------------------------------------------- 1 | /// ref. 2 | #[derive(Debug, Clone, Copy)] 3 | pub enum LockOptions { 4 | WriteLock = 0, 5 | ReadLock, 6 | NoLock, 7 | } 8 | 9 | /// ref. 10 | #[derive(Debug, Clone)] 11 | pub struct HttpHandler { 12 | pub lock_option: LockOptions, 13 | pub handler: T, 14 | pub server_addr: Option, 15 | } 16 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/snow/engine/common/message.rs: -------------------------------------------------------------------------------- 1 | //! Consensus engine message type. 2 | use num_derive::{FromPrimitive, ToPrimitive}; 3 | 4 | /// Message is an enum of the message types that vms can send to consensus. 5 | /// 6 | /// ref. 7 | #[derive(FromPrimitive, ToPrimitive, PartialEq, Eq, Debug)] 8 | #[repr(u32)] 9 | pub enum Message { 10 | /// Notifies a consensus engine that its VM has pending transactions 11 | /// (i.e. it would like to add a new block/vertex to consensus) 12 | PendingTxs = 1, // 0 is reserved for grpc unspecified. 13 | 14 | /// Notifies the state syncer engine that the VM has finishing 15 | /// syncing the requested state summary. 16 | StateSyncDone, 17 | 18 | /// StopVertex notifies a consensus that it has a pending stop vertex. 19 | StopVertex, 20 | } 21 | 22 | impl Message { 23 | /// ref. 24 | pub fn as_str(&self) -> &str { 25 | match self { 26 | Message::PendingTxs => "Pending Transactions", 27 | Message::StateSyncDone => "State Sync Done", 28 | Message::StopVertex => "Pending Stop Vertex", 29 | } 30 | } 31 | } 32 | 33 | impl TryFrom for Message { 34 | type Error = String; 35 | fn try_from(v: u32) -> Result { 36 | match v { 37 | x if x == Message::PendingTxs as u32 => Ok(Message::PendingTxs), 38 | x if x == Message::StateSyncDone as u32 => Ok(Message::StateSyncDone), 39 | x if x == Message::StopVertex as u32 => Ok(Message::StopVertex), 40 | _ => Err("invalid message enum".to_string()), 41 | } 42 | } 43 | } 44 | 45 | #[test] 46 | fn test_message() { 47 | let m = Message::try_from(1).unwrap(); 48 | assert_eq!(m, Message::PendingTxs); 49 | assert!(m.as_str().contains("Pending Transactions")); 50 | assert!(Message::try_from(5).is_err()); 51 | } 52 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/snow/engine/common/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod appsender; 2 | pub mod engine; 3 | pub mod http_handler; 4 | pub mod message; 5 | pub mod vm; 6 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/snow/engine/common/vm.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, io::Result}; 2 | 3 | use crate::{ 4 | ids, 5 | subnet::rpc::{ 6 | context::Context, 7 | database::{manager::Manager, BoxedDatabase}, 8 | health::Checkable, 9 | http::handle::Handle, 10 | snow::State, 11 | snow::{ 12 | engine::common::{ 13 | appsender::AppSender, engine::AppHandler, http_handler::HttpHandler, 14 | message::Message, 15 | }, 16 | validators, 17 | }, 18 | }, 19 | }; 20 | 21 | use tokio::sync::mpsc::Sender; 22 | 23 | /// Vm describes the trait that all consensus VMs must implement. 24 | /// 25 | /// ref. 26 | #[tonic::async_trait] 27 | pub trait CommonVm: AppHandler + Connector + Checkable { 28 | type DatabaseManager: Manager; 29 | type AppSender: AppSender; 30 | type ChainHandler: Handle; 31 | type StaticHandler: Handle; 32 | type ValidatorState: validators::State; 33 | 34 | #[allow(clippy::too_many_arguments)] 35 | async fn initialize( 36 | &mut self, 37 | ctx: Option>, 38 | db_manager: BoxedDatabase, 39 | genesis_bytes: &[u8], 40 | upgrade_bytes: &[u8], 41 | config_bytes: &[u8], 42 | to_engine: Sender, 43 | fxs: &[Fx], 44 | app_sender: Self::AppSender, 45 | ) -> Result<()>; 46 | async fn set_state(&self, state: State) -> Result<()>; 47 | async fn shutdown(&self) -> Result<()>; 48 | async fn version(&self) -> Result; 49 | async fn create_static_handlers( 50 | &mut self, 51 | ) -> Result>>; 52 | async fn create_handlers(&mut self) 53 | -> Result>>; 54 | } 55 | 56 | /// snow.validators.Connector 57 | /// 58 | /// ref. 59 | #[tonic::async_trait] 60 | pub trait Connector { 61 | async fn connected(&self, id: &ids::node::Id) -> Result<()>; 62 | async fn disconnected(&self, id: &ids::node::Id) -> Result<()>; 63 | } 64 | 65 | /// TODO: Currently not implemented 66 | pub type Fx = (); 67 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/snow/engine/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod common; 2 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/snow/validators/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | 3 | use std::{collections::BTreeMap, fmt::Debug, io}; 4 | 5 | use crate::{ids, key::bls::public_key::Key}; 6 | 7 | /// Contains the base values representing a validator 8 | /// of the Avalanche Network. 9 | /// 10 | /// ref. 11 | #[derive(Clone, Debug)] 12 | #[allow(dead_code)] 13 | pub struct Validator { 14 | pub node_id: ids::node::Id, 15 | pub public_key: Key, 16 | pub tx_id: ids::Id, 17 | pub weight: u64, 18 | 19 | /// Used to efficiently remove validators from the validator set. It 20 | /// represents the index of this validator in the vdrSlice and weights 21 | /// arrays. 22 | index: u32, 23 | } 24 | 25 | /// Contains the publicly relevant values of a validator of the Avalanche 26 | /// Network for the output of GetValidator. 27 | /// 28 | /// ref. 29 | #[derive(Clone, Debug, Eq, PartialEq)] 30 | pub struct GetValidatorOutput { 31 | pub node_id: ids::node::Id, 32 | pub public_key: Option, 33 | pub weight: u64, 34 | } 35 | 36 | /// Allows the lookup of validator sets on specified subnets at the 37 | /// requested P-chain height. 38 | /// 39 | /// ref. 40 | #[tonic::async_trait] 41 | pub trait State: Debug { 42 | /// Returns the minimum height of the block still in the 43 | /// proposal window. 44 | async fn get_minimum_height(&self) -> io::Result; 45 | 46 | /// Returns the current height of the P-chain. 47 | async fn get_current_height(&self) -> io::Result; 48 | 49 | /// Returns the subnet ID of the provided chain. 50 | async fn get_subnet_id(&self, chain_id: ids::Id) -> io::Result; 51 | 52 | /// Returns the validators of the provided subnet at the 53 | /// requested P-chain height. 54 | /// The returned map should not be modified. 55 | async fn get_validator_set( 56 | &self, 57 | height: u64, 58 | subnet_id: ids::Id, 59 | ) -> io::Result>; 60 | } 61 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/snowman/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod block; 2 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet/rpc/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod grpc; 2 | 3 | use std::{ 4 | io::{Error, Result}, 5 | net::{SocketAddr, UdpSocket}, 6 | }; 7 | 8 | /// Returns a localhost address with next available port. 9 | pub fn new_socket_addr() -> SocketAddr { 10 | UdpSocket::bind("127.0.0.1:0") 11 | .unwrap() 12 | .local_addr() 13 | .unwrap() 14 | } 15 | 16 | /// Persists first \[`io::Error`\] collected. 17 | #[derive(Debug)] 18 | pub struct Errors { 19 | err: Option, 20 | } 21 | 22 | impl Default for Errors { 23 | fn default() -> Self { 24 | Self::new() 25 | } 26 | } 27 | 28 | impl Errors { 29 | pub fn new() -> Self { 30 | Self { err: None } 31 | } 32 | 33 | /// Persists the error if no error currently exists. 34 | pub fn add(&mut self, error: &Error) { 35 | if self.err.is_none() { 36 | self.err = Some(Error::new(error.kind(), error.to_string())) 37 | } 38 | } 39 | 40 | /// Returns an io::Error if collected. 41 | pub fn err(&self) -> Result<()> { 42 | if let Some(e) = &self.err { 43 | return Err(Error::new(e.kind(), e.to_string())); 44 | } 45 | Ok(()) 46 | } 47 | 48 | /// Returns true an error has been collected. 49 | pub fn is_some(&self) -> bool { 50 | self.err.is_some() 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/subnet_evm/mod.rs: -------------------------------------------------------------------------------- 1 | //! Subnet-EVM configuration. 2 | pub mod chain_config; 3 | pub mod genesis; 4 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | //! Utilities for URLs and versioning. 2 | pub mod urls; 3 | pub mod version; 4 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/verify.rs: -------------------------------------------------------------------------------- 1 | //! Verifiable trait. 2 | use crate::errors::Result; 3 | 4 | /// Verifiable can be verified. 5 | /// ref. 6 | pub trait Verifiable { 7 | /// Verifies the block or vertex. 8 | /// The protocol must ensure that its parents has already been verified. 9 | fn verify(&self) -> Result<()>; 10 | } 11 | -------------------------------------------------------------------------------- /crates/avalanche-types/src/xsvm/mod.rs: -------------------------------------------------------------------------------- 1 | //! An example of a VM. 2 | pub mod genesis; 3 | -------------------------------------------------------------------------------- /crates/avalanche-types/tests.unit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xue 3 | 4 | if ! [[ "$0" =~ tests.unit.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | # uses nextest for faster test runs and better output 10 | # https://github.com/nextest-rs/nextest/tree/main 11 | # local use: cargo install nextest 12 | 13 | RUST_LOG=debug cargo test \ 14 | -p avalanche-types 15 | 16 | echo "ALL SUCCESS!" 17 | -------------------------------------------------------------------------------- /crates/avalanche-types/tests/integration_tests.rs: -------------------------------------------------------------------------------- 1 | #[cfg(any(test, feature = "subnet"))] 2 | mod rpc; 3 | -------------------------------------------------------------------------------- /crates/avalanche-types/tests/rpc/database/concurrency.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use super::serve_test_database; 4 | use avalanche_types::subnet::rpc::database::{ 5 | memdb::Database as MemDb, 6 | rpcdb::{client::DatabaseClient, server::Server as RpcDb}, 7 | }; 8 | use futures::{stream::FuturesUnordered, StreamExt}; 9 | use tokio::net::TcpListener; 10 | use tonic::transport::Channel; 11 | 12 | #[tokio::test(flavor = "multi_thread")] 13 | async fn rpcdb_mutation_test() { 14 | let db = MemDb::new_boxed(); 15 | let server = RpcDb::new_boxed(db); 16 | 17 | let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); 18 | let addr = listener.local_addr().unwrap(); 19 | tokio::spawn(async move { 20 | serve_test_database(server, listener).await.unwrap(); 21 | }); 22 | tokio::time::sleep(Duration::from_millis(100)).await; 23 | 24 | let client_conn = Channel::builder(format!("http://{}", addr).parse().unwrap()) 25 | .connect() 26 | .await 27 | .unwrap(); 28 | 29 | let client = DatabaseClient::new_boxed(client_conn); 30 | let mut futures = FuturesUnordered::new(); 31 | // 1000 requests 32 | for i in 0..1000_i32 { 33 | let mut client = client.clone(); 34 | futures.push(async move { 35 | client 36 | .put("foo".as_bytes(), format!("bar-{}", i).as_bytes()) 37 | .await 38 | }); 39 | } 40 | 41 | while let Some(res) = futures.next().await { 42 | assert!(res.is_ok()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /crates/avalanche-types/tests/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | mod database; 2 | mod shutdown; 3 | 4 | #[cfg(any(test, feature = "proto"))] 5 | use std::io::{self, Error, ErrorKind}; 6 | 7 | use avalanche_types::{ 8 | proto::pb::rpcdb::database_server::{Database, DatabaseServer}, 9 | subnet::rpc::utils::grpc::default_server, 10 | }; 11 | use tokio::net::TcpListener; 12 | use tokio_stream::wrappers::TcpListenerStream; 13 | 14 | pub async fn serve_test_database(database: D, listener: TcpListener) -> io::Result<()> 15 | where 16 | D: Database, 17 | { 18 | default_server() 19 | .add_service(DatabaseServer::new(database)) 20 | .serve_with_incoming(TcpListenerStream::new(listener)) 21 | .await 22 | .map_err(|e| { 23 | Error::new( 24 | ErrorKind::Other, 25 | format!("failed to serve test database service: {}", e), 26 | ) 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /crates/avalanche-types/tests/rpc/shutdown.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use avalanche_types::{ 4 | proto::pb::rpcdb::database_server::DatabaseServer, 5 | subnet::rpc::{ 6 | database::{ 7 | memdb::Database as MemDb, 8 | rpcdb::{client::DatabaseClient, server::Server as RpcDb}, 9 | }, 10 | utils, 11 | }, 12 | }; 13 | use tokio::sync::broadcast::{Receiver, Sender}; 14 | use tonic::transport::Channel; 15 | 16 | #[tokio::test] 17 | async fn test_shutdown() { 18 | // initialize broadcast channel 19 | let (tx, _rx): (Sender<()>, Receiver<()>) = tokio::sync::broadcast::channel(1); 20 | 21 | // setup rpcdb service 22 | let memdb = MemDb::new_boxed(); 23 | let server = RpcDb::new_boxed(memdb); 24 | let svc = DatabaseServer::new(server); 25 | let addr = utils::new_socket_addr(); 26 | 27 | // start gRPC service 28 | let server = utils::grpc::Server::new(addr, tx.subscribe()); 29 | let resp = server.serve(svc); 30 | assert!(resp.is_ok()); 31 | tokio::time::sleep(Duration::from_millis(100)).await; 32 | 33 | // setup gRPC client 34 | let client_conn = Channel::builder(format!("http://{}", addr).parse().unwrap()) 35 | .connect() 36 | .await 37 | .unwrap(); 38 | let mut client = DatabaseClient::new_boxed(client_conn); 39 | 40 | // client request ok 41 | let resp = client.put("foo".as_bytes(), "bar".as_bytes()).await; 42 | assert!(resp.is_ok()); 43 | 44 | // broadcast shutdown to server 45 | let _ = tx.send(()); 46 | tokio::time::sleep(Duration::from_millis(100)).await; 47 | 48 | // client request fail 49 | let resp = client.put("foo".as_bytes(), "bar".as_bytes()).await; 50 | assert!(resp.is_err()); 51 | } 52 | -------------------------------------------------------------------------------- /scripts/build.release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xue 3 | 4 | if ! [[ "$0" =~ scripts/build.release.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | # "--bin" can be specified multiple times for each directory in "bin/*" or workspaces 10 | # cargo build \ 11 | # --release \ 12 | # --bin avalanche-node-rust \ 13 | # --bin avalanche-cli-rust \ 14 | # --bin avalanche-e2e 15 | 16 | # ./target/release/avalanche-node-rust --help 17 | # ./target/release/avalanche-cli-rust --help 18 | # ./target/release/avalanche-e2e --help 19 | 20 | cargo build \ 21 | --release \ 22 | -p avalanche-types \ 23 | -p avalanche-consensus 24 | -------------------------------------------------------------------------------- /scripts/check_crate_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CRATE=$1 4 | if [[ $CRATE == "avalanche-types" ]]; then 5 | echo "Checking avalanche-types" 6 | 7 | avalanche_types_published_version=$(cargo search avalanche-types | head -1 | cut -d'"' -f 2) 8 | echo $avalanche_types_published_version 9 | 10 | avalanche_types_current_version=$(cargo pkgid -p avalanche-types | cut -d "#" -f2) 11 | echo $avalanche_types_current_version 12 | 13 | if [ $avalanche_types_published_version = $avalanche_types_current_version ]; then 14 | echo "The current and published versions are equal." 15 | exit 1 16 | else 17 | echo "The current and published versions are different." 18 | exit 0 19 | fi 20 | 21 | elif [[ $CRATE == "avalanche-consensus" ]]; then 22 | echo "Checking avalanche-consensus" 23 | 24 | avalanche_consensus_published_version=$(cargo search avalanche-consensus | head -1 | cut -d'"' -f 2) 25 | echo $avalanche_consensus_published_version 26 | 27 | avalanche_consensus_current_version=$(cargo pkgid -p avalanche-consensus | cut -d "#" -f2) 28 | echo $avalanche_consensus_current_version 29 | 30 | if [ $avalanche_consensus_published_version = $avalanche_consensus_current_version ]; then 31 | echo "The current and published versions are equal." 32 | exit 1 33 | else 34 | echo "The current and published versions are different." 35 | exit 0 36 | fi 37 | 38 | else 39 | echo "Invalid crate name" 40 | exit 1 41 | fi 42 | -------------------------------------------------------------------------------- /scripts/tests.avalanchego-byzantine.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # ./scripts/tests.avalanchego-byzantine.sh 5 | # ./scripts/tests.avalanchego-byzantine.sh /Users/leegyuho/avalanchego/build/avalanchego 6 | if ! [[ "$0" =~ scripts/tests.avalanchego-byzantine.sh ]]; then 7 | echo "must be run from repository root" 8 | exit 255 9 | fi 10 | 11 | NETWORK_RUNNER_AVALANCHEGO_PATH=${1:-""} 12 | 13 | echo "Running with:" 14 | echo NETWORK_RUNNER_AVALANCHEGO_PATH: "${NETWORK_RUNNER_AVALANCHEGO_PATH}" 15 | 16 | ################################# 17 | # download avalanche-network-runner 18 | # https://github.com/ava-labs/avalanche-network-runner 19 | # TODO: use "go install -v github.com/ava-labs/avalanche-network-runner/cmd/avalanche-network-runner@v${NETWORK_RUNNER_VERSION}" 20 | GOOS=$(go env GOOS) 21 | NETWORK_RUNNER_VERSION=1.7.7 22 | DOWNLOAD_PATH=/tmp/avalanche-network-runner.tar.gz 23 | DOWNLOAD_URL=https://github.com/ava-labs/avalanche-network-runner/releases/download/v${NETWORK_RUNNER_VERSION}/avalanche-network-runner_${NETWORK_RUNNER_VERSION}_linux_amd64.tar.gz 24 | if [[ ${GOOS} == "darwin" ]]; then 25 | DOWNLOAD_URL=https://github.com/ava-labs/avalanche-network-runner/releases/download/v${NETWORK_RUNNER_VERSION}/avalanche-network-runner_${NETWORK_RUNNER_VERSION}_darwin_amd64.tar.gz 26 | fi 27 | 28 | rm -f ${DOWNLOAD_PATH} 29 | rm -f /tmp/avalanche-network-runner 30 | 31 | echo "downloading avalanche-network-runner ${NETWORK_RUNNER_VERSION} at ${DOWNLOAD_URL}" 32 | curl -L ${DOWNLOAD_URL} -o ${DOWNLOAD_PATH} 33 | 34 | echo "extracting downloaded avalanche-network-runner" 35 | tar xzvf ${DOWNLOAD_PATH} -C /tmp 36 | /tmp/avalanche-network-runner -h 37 | 38 | ################################# 39 | # run "avalanche-network-runner" server 40 | echo "launch avalanche-network-runner in the background" 41 | /tmp/avalanche-network-runner \ 42 | server \ 43 | --log-level debug \ 44 | --port=":13342" \ 45 | --disable-grpc-gateway & 46 | NETWORK_RUNNER_PID=${!} 47 | sleep 5 48 | 49 | ################################# 50 | # for testing local 51 | # AVALANCHEGO_PATH=/Users/leegyuho/avalanchego/build/avalanchego 52 | # 53 | # do not run in parallel, to run in sequence 54 | echo "running byzantine tests" 55 | NETWORK_RUNNER_GRPC_ENDPOINT=http://127.0.0.1:13342 \ 56 | RUST_LOG=debug \ 57 | cargo test --all-features --package avalanchego-byzantine -- --show-output --nocapture 58 | 59 | ################################# 60 | # "e2e.test" already terminates the cluster for "test" mode 61 | # just in case tests are aborted, manually terminate them again 62 | echo "network-runner RPC server was running on NETWORK_RUNNER_PID ${NETWORK_RUNNER_PID} as test mode; terminating the process..." 63 | pkill -P ${NETWORK_RUNNER_PID} || true 64 | kill -2 ${NETWORK_RUNNER_PID} || true 65 | 66 | echo "TEST SUCCESS" 67 | -------------------------------------------------------------------------------- /scripts/tests.avalanchego-conformance.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | if ! [[ "$0" =~ scripts/tests.avalanchego-conformance.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | ################################# 10 | pushd avalanchego-conformance 11 | go install -v ./cmd/avalanchego-conformance 12 | popd 13 | 14 | ################################# 15 | # run "avalanchego-conformance" server 16 | echo "launch avalanchego-conformance in the background" 17 | avalanchego-conformance \ 18 | server \ 19 | --log-level debug \ 20 | --port=22342 \ 21 | --grpc-gateway-port=22343 & 22 | AVALANCHEGO_CONFORMANCE_PID=${!} 23 | echo "avalanchego-conformance server is running on PID ${AVALANCHEGO_CONFORMANCE_PID}" 24 | 25 | ################################# 26 | echo "running conformance tests" 27 | AVALANCHEGO_CONFORMANCE_SERVER_RPC_ENDPOINT=http://127.0.0.1:22342 \ 28 | RUST_LOG=debug \ 29 | cargo test --all-features --package avalanchego-conformance -- --show-output --nocapture 30 | 31 | ################################# 32 | echo "SUCCESS conformance tests" 33 | kill -2 ${AVALANCHEGO_CONFORMANCE_PID} || true 34 | 35 | echo "TEST SUCCESS" 36 | -------------------------------------------------------------------------------- /scripts/tests.fuzz.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xue 3 | 4 | if ! [[ "$0" =~ scripts/tests.fuzz.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | # ref. https://github.com/rust-fuzz/cargo-fuzz 10 | # ref. https://rust-fuzz.github.io/book/cargo-fuzz/setup.html 11 | rustup default nightly 12 | 13 | pushd crates/avalanche-types 14 | cargo fuzz run ids 15 | popd 16 | 17 | rustup default stable 18 | 19 | cargo clean 20 | 21 | echo "ALL SUCCESS!" 22 | -------------------------------------------------------------------------------- /scripts/tests.lint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xue 3 | 4 | if ! [[ "$0" =~ scripts/tests.lint.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | # https://rust-lang.github.io/rustup/installation/index.html 10 | # rustup toolchain install nightly --allow-downgrade --profile minimal --component clippy 11 | # 12 | # https://github.com/rust-lang/rustfmt 13 | # rustup component add rustfmt 14 | # rustup component add rustfmt --toolchain nightly 15 | # rustup component add clippy 16 | # rustup component add clippy --toolchain nightly 17 | 18 | rustup default stable 19 | cargo fmt --all --verbose -- --check 20 | 21 | # TODO: enable nightly fmt 22 | rustup default nightly 23 | cargo +nightly fmt --all -- --config-path .rustfmt.nightly.toml --verbose --check || true 24 | 25 | # TODO: enable this 26 | # cargo +nightly clippy --all --all-features -- -D warnings || true 27 | 28 | # ref. https://github.com/rust-lang/rust-clippy 29 | cargo +nightly clippy --all --all-features -- \ 30 | -D clippy::suspicious \ 31 | -D clippy::style \ 32 | -D clippy::complexity \ 33 | -D clippy::perf \ 34 | -D clippy::pedantic \ 35 | -D clippy::restriction \ 36 | -D clippy::nursery \ 37 | -D clippy::cargo \ 38 | || true 39 | 40 | rustup default stable 41 | 42 | cargo clean 43 | 44 | echo "ALL SUCCESS!" 45 | -------------------------------------------------------------------------------- /scripts/tests.unit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xue 3 | 4 | if ! [[ "$0" =~ scripts/tests.unit.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | # uses nextest for faster test runs and better output 10 | # https://github.com/nextest-rs/nextest/tree/main 11 | # local use: cargo install nextest 12 | 13 | RUST_LOG=debug cargo test \ 14 | --all-features \ 15 | -p avalanche-types \ 16 | -p avalanche-consensus 17 | 18 | echo "ALL SUCCESS!" 19 | -------------------------------------------------------------------------------- /scripts/tests.unused.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -xue 3 | 4 | if ! [[ "$0" =~ scripts/tests.unused.sh ]]; then 5 | echo "must be run from repository root" 6 | exit 255 7 | fi 8 | 9 | # cargo install cargo-udeps --locked 10 | # https://github.com/est31/cargo-udeps 11 | cargo install cargo-udeps --locked 12 | 13 | # TODO: re-enable "--all-targets" 14 | cargo +nightly udeps --all-targets 15 | 16 | echo "ALL SUCCESS!" 17 | -------------------------------------------------------------------------------- /tests/avalanche-e2e/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "avalanche-e2e" 3 | version = "0.0.0" 4 | edition = "2021" 5 | rust-version = "1.70" # use "rustup override set stable" to overwrite current toolchain 6 | publish = false 7 | description = "e2e tests for Avalanche" 8 | license-file = "LICENSE" 9 | homepage = "https://avax.network" 10 | 11 | [dependencies] 12 | avalanche-installer = "0.0.77" 13 | avalanche-network-runner-sdk = "0.3.3" # https://crates.io/crates/avalanche-network-runner-sdk 14 | avalanche-types = { path = "../../crates/avalanche-types", features = ["jsonrpc_client", "wallet", "wallet_evm", "kms_aws"] } # https://crates.io/crates/avalanche-types 15 | aws-manager = { version = "0.30.2", features = ["kms"] } # https://github.com/gyuho/aws-manager/tags 16 | clap = { version = "4.3.19", features = ["cargo", "derive"] } # https://github.com/clap-rs/clap/releases 17 | crossterm = "0.27.0" 18 | dialoguer = "0.11.0" 19 | env_logger = "0.11.1" 20 | ethers = { version = "=2.0.11" } # https://github.com/gakonst/ethers-rs/releases 21 | ethers-core = { version = "=2.0.13", features = ["eip712"] } # https://github.com/gakonst/ethers-rs/releases 22 | ethers-signers = { version = "=2.0.13" } # https://github.com/gakonst/ethers-rs/releases 23 | log = "0.4.20" 24 | primitive-types = { version = "0.12.1", features = ["impl-serde"] } # https://crates.io/crates/primitive-types 25 | prometheus-manager = "0.0.30" 26 | rand = "0.8.5" 27 | random-manager = "0.0.5" 28 | reqwest = "0.11.20" 29 | serde = { version = "1.0.186", features = ["derive"] } 30 | serde_json = "1.0.105" # https://github.com/serde-rs/json/releases 31 | serde_yaml = "0.9.25" # https://github.com/dtolnay/serde-yaml/releases 32 | tokio = { version = "1.32.0", features = [] } # https://github.com/tokio-rs/tokio/releases 33 | 34 | [dev-dependencies] 35 | tempfile = "3.5.0" 36 | -------------------------------------------------------------------------------- /tests/avalanche-e2e/README.md: -------------------------------------------------------------------------------- 1 | 2 | ```bash 3 | ./scripts/build.release.sh 4 | 5 | ./target/release/avalanche-e2e -h 6 | ./target/release/avalanche-e2e default-spec -h 7 | 8 | ./target/release/avalanche-e2e \ 9 | --spec-path /tmp/tests.avalanchego-e2e.yaml \ 10 | default-spec \ 11 | --keys-to-generate 5 \ 12 | --network-runner-grpc-endpoint http://127.0.0.1:12342 13 | 14 | ./target/release/avalanche-e2e \ 15 | --skip-prompt \ 16 | --spec-path /tmp/tests.avalanchego-e2e.yaml 17 | ``` 18 | -------------------------------------------------------------------------------- /tests/avalanche-e2e/src/c/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod simple_transfers; 2 | -------------------------------------------------------------------------------- /tests/avalanche-e2e/src/flags.rs: -------------------------------------------------------------------------------- 1 | /// Defines flag options. 2 | #[derive(Debug)] 3 | pub struct Options { 4 | pub log_level: String, 5 | pub spec_path: String, 6 | pub skip_prompt: bool, 7 | } 8 | -------------------------------------------------------------------------------- /tests/avalanche-e2e/src/logs.rs: -------------------------------------------------------------------------------- 1 | pub fn setup_logger(log_level: String) { 2 | let lvl = match log_level.to_lowercase().as_str() { 3 | "off" => log::LevelFilter::Off, 4 | "error" => log::LevelFilter::Error, 5 | "warn" => log::LevelFilter::Warn, 6 | "info" => log::LevelFilter::Info, 7 | "debug" => log::LevelFilter::Debug, 8 | "trace" => log::LevelFilter::Trace, 9 | _ => { 10 | println!("defaulting {} to 'info' level", log_level); 11 | log::LevelFilter::Info 12 | } 13 | }; 14 | 15 | let mut builder = env_logger::Builder::new(); 16 | builder.filter(None, lvl); 17 | 18 | if let Ok(env) = std::env::var("RUST_LOG") { 19 | builder.parse_filters(&env); 20 | } 21 | 22 | let _r = builder.try_init(); 23 | } 24 | -------------------------------------------------------------------------------- /tests/avalanche-e2e/src/p/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod transfer; 2 | -------------------------------------------------------------------------------- /tests/avalanche-e2e/src/p/transfer.rs: -------------------------------------------------------------------------------- 1 | pub async fn run() {} 2 | -------------------------------------------------------------------------------- /tests/avalanche-e2e/src/x/byzantine/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod conflicting_parallel_transfers; 2 | pub mod conflicting_transfers; 3 | -------------------------------------------------------------------------------- /tests/avalanche-e2e/src/x/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod byzantine; 2 | pub mod exports; 3 | pub mod simple_transfers; 4 | -------------------------------------------------------------------------------- /tests/avalanchego-byzantine/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "avalanchego-byzantine" 3 | version = "0.0.0" 4 | edition = "2021" 5 | rust-version = "1.70" # use "rustup override set stable" to overwrite current toolchain 6 | publish = false 7 | description = "Byzantine tests for Avalanche Go" 8 | license-file = "LICENSE" 9 | homepage = "https://avax.network" 10 | 11 | [dependencies] 12 | 13 | [dev-dependencies] 14 | avalanche-installer = "0.0.77" 15 | avalanche-network-runner-sdk = "0.3.3" # https://crates.io/crates/avalanche-network-runner-sdk 16 | avalanche-types = { path = "../../crates/avalanche-types", features = ["jsonrpc_client"] } # https://crates.io/crates/avalanche-types 17 | cert-manager = { path = "../../core/cert-manager" } 18 | env_logger = "0.11.1" 19 | hex = "0.4.3" 20 | log = "0.4.20" 21 | network = { path = "../../core/network" } 22 | random-manager = "0.0.5" 23 | serde_json = "1.0.104" # https://github.com/serde-rs/json/releases 24 | tokio = { version = "1.32.0", features = [] } # https://github.com/tokio-rs/tokio/releases 25 | -------------------------------------------------------------------------------- /tests/avalanchego-byzantine/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests; 3 | 4 | pub fn get_network_runner_grpc_endpoint() -> (String, bool) { 5 | match std::env::var("NETWORK_RUNNER_GRPC_ENDPOINT") { 6 | Ok(s) => (s, true), 7 | _ => (String::new(), false), 8 | } 9 | } 10 | 11 | pub fn get_network_runner_avalanchego_path() -> (String, bool) { 12 | match std::env::var("NETWORK_RUNNER_AVALANCHEGO_PATH") { 13 | Ok(s) => (s, true), 14 | _ => (String::new(), false), 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "avalanchego-conformance" 3 | version = "0.0.0" 4 | edition = "2021" 5 | rust-version = "1.70" # use "rustup override set stable" to overwrite current toolchain 6 | publish = false 7 | description = "Conformance tests on AvalancheGo" 8 | license-file = "LICENSE" 9 | homepage = "https://avax.network" 10 | 11 | [dependencies] 12 | 13 | [dev-dependencies] 14 | avalanche-types = { path = "../../crates/avalanche-types", features = ["libsecp256k1", "message"] } 15 | avalanchego-conformance-sdk = { path = "../../avalanchego-conformance-sdk" } 16 | cert-manager = { path = "../../core/cert-manager" } 17 | env_logger = "0.11.1" 18 | log = "0.4.20" 19 | random-manager = "0.0.5" 20 | serde_json = "1.0.104" # https://github.com/serde-rs/json/releases 21 | tokio = { version = "1.32.0", features = [] } # https://github.com/tokio-rs/tokio/releases 22 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests; 3 | 4 | pub fn get_endpoint() -> (String, bool) { 5 | match std::env::var("AVALANCHEGO_CONFORMANCE_SERVER_RPC_ENDPOINT") { 6 | Ok(s) => (s, true), 7 | _ => (String::new(), false), 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/tests/key/bls.rs: -------------------------------------------------------------------------------- 1 | use avalanche_types::key::bls; 2 | use avalanchego_conformance_sdk::{BlsSignatureRequest, Client}; 3 | 4 | #[tokio::test] 5 | async fn generate_bls_signature() { 6 | let _ = env_logger::builder() 7 | .filter_level(log::LevelFilter::Info) 8 | .is_test(true) 9 | .try_init(); 10 | 11 | let (ep, is_set) = crate::get_endpoint(); 12 | assert!(is_set); 13 | let cli = Client::new(&ep).await; 14 | 15 | let msg = random_manager::secure_bytes(100).unwrap(); 16 | 17 | let sk = bls::private_key::Key::generate().unwrap(); 18 | log::debug!("key: {} bytes", sk.to_bytes().len()); 19 | 20 | let sig = sk.sign(&msg); 21 | let sig_pop = sk.sign_proof_of_possession(&msg); 22 | 23 | let resp = cli 24 | .bls_signature(BlsSignatureRequest { 25 | private_key: sk.to_bytes().to_vec(), 26 | public_key: sk.to_public_key().to_compressed_bytes().to_vec(), 27 | message: msg, 28 | signature: sig.to_compressed_bytes().to_vec(), 29 | signature_proof_of_possession: sig_pop.to_compressed_bytes().to_vec(), 30 | }) 31 | .await 32 | .expect("failed bls_signature"); 33 | assert!(resp.success); 34 | } 35 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/tests/key/mod.rs: -------------------------------------------------------------------------------- 1 | mod bls; 2 | mod certificates; 3 | mod secp256k1; 4 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/tests/message/chits.rs: -------------------------------------------------------------------------------- 1 | use avalanche_types::{ids, message::chits}; 2 | 3 | use avalanchego_conformance_sdk::{ChitsRequest, Client}; 4 | 5 | #[tokio::test] 6 | async fn chits() { 7 | let _ = env_logger::builder() 8 | .filter_level(log::LevelFilter::Info) 9 | .is_test(true) 10 | .try_init(); 11 | 12 | let (ep, is_set) = crate::get_endpoint(); 13 | assert!(is_set); 14 | let cli = Client::new(&ep).await; 15 | 16 | let chain_id = ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()); 17 | let request_id = random_manager::u32(); 18 | let container_ids = vec![ 19 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 20 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 21 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 22 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 23 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 24 | ]; 25 | let msg = chits::Message::default() 26 | .chain_id(chain_id.clone()) 27 | .request_id(request_id) 28 | .container_ids(container_ids.clone()); 29 | let serialized_msg = msg.serialize().expect("failed serialize"); 30 | 31 | log::info!("sending message ({} bytes)", serialized_msg.len()); 32 | 33 | let mut container_ids_bytes: Vec> = Vec::new(); 34 | for id in container_ids.iter() { 35 | container_ids_bytes.push(id.as_ref().to_vec()); 36 | } 37 | let resp = cli 38 | .chits(ChitsRequest { 39 | chain_id: chain_id.as_ref().to_vec(), 40 | request_id, 41 | container_ids: container_ids_bytes, 42 | serialized_msg, 43 | }) 44 | .await 45 | .expect("failed chits"); 46 | assert!(resp.success); 47 | } 48 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/tests/message/mod.rs: -------------------------------------------------------------------------------- 1 | mod accepted; 2 | mod accepted_frontier; 3 | mod accepted_state_summary; 4 | mod ancestors; 5 | mod app; 6 | mod chits; 7 | mod get_put; 8 | mod peerlist; 9 | mod ping_pong; 10 | mod pull_query; 11 | mod push_query; 12 | mod state_summary_frontier; 13 | mod version; 14 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/tests/message/ping_pong.rs: -------------------------------------------------------------------------------- 1 | use avalanche_types::message::{ping, pong}; 2 | use avalanchego_conformance_sdk::{Client, PingRequest, PongRequest}; 3 | 4 | #[tokio::test] 5 | async fn ping() { 6 | let _ = env_logger::builder() 7 | .filter_level(log::LevelFilter::Info) 8 | .is_test(true) 9 | .try_init(); 10 | 11 | let (ep, is_set) = crate::get_endpoint(); 12 | assert!(is_set); 13 | let cli = Client::new(&ep).await; 14 | 15 | let msg = ping::Message::default(); 16 | let serialized_msg = msg.serialize().expect("failed serialize"); 17 | 18 | log::info!("sending message ({} bytes)", serialized_msg.len()); 19 | 20 | let resp = cli 21 | .ping(PingRequest { serialized_msg }) 22 | .await 23 | .expect("failed ping"); 24 | assert!(resp.success); 25 | } 26 | 27 | #[tokio::test] 28 | async fn pong() { 29 | let _ = env_logger::builder() 30 | .filter_level(log::LevelFilter::Info) 31 | .is_test(true) 32 | .try_init(); 33 | 34 | let (ep, is_set) = crate::get_endpoint(); 35 | assert!(is_set); 36 | let cli = Client::new(&ep).await; 37 | 38 | let uptime_pct = random_manager::u32(); 39 | let msg = pong::Message::default().uptime_pct(uptime_pct); 40 | let serialized_msg = msg.serialize().expect("failed serialize"); 41 | 42 | log::info!("sending message ({} bytes)", serialized_msg.len()); 43 | 44 | let resp = cli 45 | .pong(PongRequest { 46 | uptime_pct, 47 | serialized_msg, 48 | }) 49 | .await 50 | .expect("failed message_pong"); 51 | assert!(resp.success); 52 | } 53 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/tests/message/pull_query.rs: -------------------------------------------------------------------------------- 1 | use avalanche_types::{ids, message::pull_query}; 2 | use avalanchego_conformance_sdk::{Client, PullQueryRequest}; 3 | 4 | #[tokio::test] 5 | async fn pull_query() { 6 | let _ = env_logger::builder() 7 | .filter_level(log::LevelFilter::Info) 8 | .is_test(true) 9 | .try_init(); 10 | 11 | let (ep, is_set) = crate::get_endpoint(); 12 | assert!(is_set); 13 | let cli = Client::new(&ep).await; 14 | 15 | let chain_id = ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()); 16 | let request_id = random_manager::u32(); 17 | let deadline = random_manager::u64(); 18 | let container_id = ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()); 19 | let msg = pull_query::Message::default() 20 | .chain_id(chain_id.clone()) 21 | .request_id(request_id) 22 | .deadline(deadline) 23 | .container_id(container_id.clone()); 24 | let serialized_msg = msg.serialize().expect("failed serialize"); 25 | 26 | log::info!("sending message ({} bytes)", serialized_msg.len()); 27 | 28 | let resp = cli 29 | .pull_query(PullQueryRequest { 30 | chain_id: chain_id.as_ref().to_vec(), 31 | request_id, 32 | deadline, 33 | container_id: container_id.as_ref().to_vec(), 34 | serialized_msg, 35 | }) 36 | .await 37 | .expect("failed pull_query"); 38 | assert!(resp.success); 39 | } 40 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/tests/message/version.rs: -------------------------------------------------------------------------------- 1 | use std::net::{IpAddr, Ipv6Addr}; 2 | 3 | use avalanche_types::{ids, message::version}; 4 | use avalanchego_conformance_sdk::{Client, VersionRequest}; 5 | use log::info; 6 | 7 | #[tokio::test] 8 | async fn version() { 9 | let _ = env_logger::builder() 10 | .filter_level(log::LevelFilter::Info) 11 | .is_test(true) 12 | .try_init(); 13 | 14 | let (ep, is_set) = crate::get_endpoint(); 15 | assert!(is_set); 16 | let cli = Client::new(&ep).await; 17 | 18 | let my_time = random_manager::u64(); 19 | let sig = random_manager::secure_bytes(64).unwrap(); 20 | let tracked_subnets = vec![ 21 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 22 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 23 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 24 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 25 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 26 | ]; 27 | let mut tracked_subnets_bytes: Vec> = Vec::new(); 28 | for id in tracked_subnets.iter() { 29 | tracked_subnets_bytes.push(id.as_ref().to_vec()); 30 | } 31 | 32 | let msg = version::Message::default() 33 | .network_id(9999) 34 | .my_time(my_time) 35 | .ip_addr(IpAddr::V6(Ipv6Addr::LOCALHOST)) 36 | .ip_port(8080) 37 | .my_version(String::from("v1.2.3")) 38 | .my_version_time(my_time) 39 | .sig(sig.clone()) 40 | .tracked_subnets(tracked_subnets.clone()); 41 | let serialized_msg = msg.serialize().expect("failed serialize"); 42 | 43 | info!("sending message ({} bytes)", serialized_msg.len()); 44 | 45 | let resp = cli 46 | .version(VersionRequest { 47 | network_id: 9999, 48 | my_time: my_time, 49 | ip_addr: Ipv6Addr::LOCALHOST.octets().to_vec(), 50 | ip_port: 8080, 51 | my_version: String::from("v1.2.3"), 52 | my_version_time: my_time, 53 | sig, 54 | tracked_subnets: tracked_subnets_bytes, 55 | serialized_msg, 56 | }) 57 | .await 58 | .expect("failed version"); 59 | assert!(resp.success); 60 | } 61 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod key; 2 | pub mod packer; 3 | 4 | // TODO: add it back... failing 5 | // pub mod message; 6 | 7 | use avalanchego_conformance_sdk::Client; 8 | 9 | #[tokio::test] 10 | async fn ping() { 11 | let _ = env_logger::builder() 12 | .filter_level(log::LevelFilter::Info) 13 | .is_test(true) 14 | .try_init(); 15 | 16 | let (ep, is_set) = crate::get_endpoint(); 17 | assert!(is_set); 18 | let cli = Client::new(&ep).await; 19 | 20 | let resp = cli.ping_service().await.expect("failed ping_service"); 21 | log::info!( 22 | "conformance test server is running (ping_service response {:?})", 23 | resp 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/tests/packer/build_vertex.rs: -------------------------------------------------------------------------------- 1 | use avalanche_types::{avm::txs::vertex::Vertex, ids, packer::Packer}; 2 | use avalanchego_conformance_sdk::{BuildVertexRequest, Client}; 3 | use log::info; 4 | 5 | #[tokio::test] 6 | async fn build_vertex() { 7 | let _ = env_logger::builder() 8 | .filter_level(log::LevelFilter::Info) 9 | .is_test(true) 10 | .try_init(); 11 | 12 | let (ep, is_set) = crate::get_endpoint(); 13 | assert!(is_set); 14 | let cli = Client::new(&ep).await; 15 | 16 | let mut vtx = Vertex { 17 | codec_version: 0, 18 | chain_id: ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 19 | height: random_manager::u64(), 20 | epoch: 0, 21 | parent_ids: vec![ 22 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 23 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 24 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 25 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 26 | ids::Id::from_slice(&random_manager::secure_bytes(32).unwrap()), 27 | ], 28 | txs: vec![ 29 | random_manager::secure_bytes(32).unwrap(), 30 | random_manager::secure_bytes(32).unwrap(), 31 | random_manager::secure_bytes(32).unwrap(), 32 | random_manager::secure_bytes(32).unwrap(), 33 | random_manager::secure_bytes(32).unwrap(), 34 | ], 35 | }; 36 | 37 | let mut parent_ids_copied: Vec> = Vec::new(); 38 | for id in vtx.parent_ids.iter() { 39 | parent_ids_copied.push(id.as_ref().to_vec().clone()); 40 | } 41 | let mut txs_copied: Vec> = Vec::new(); 42 | for tx in vtx.txs.iter() { 43 | txs_copied.push(tx.clone()); 44 | } 45 | 46 | let mut req = BuildVertexRequest { 47 | codec_version: 0, 48 | chain_id: vtx.chain_id.clone().as_ref().to_vec(), 49 | height: vtx.height, 50 | epoch: 0, 51 | parent_ids: parent_ids_copied, 52 | txs: txs_copied, 53 | vtx_bytes: Vec::new(), 54 | }; 55 | let packer = Packer::new(1024, 0); 56 | packer.pack_vertex(&mut vtx).unwrap(); 57 | let b = packer.take_bytes(); 58 | 59 | req.vtx_bytes = b.as_ref().to_vec().clone(); 60 | info!("built vertex ({} bytes)", req.vtx_bytes.len()); 61 | // info!("{:?}", req); 62 | 63 | let resp = cli.build_vertex(req).await.expect("failed build_vertex"); 64 | assert!(resp.success); 65 | } 66 | -------------------------------------------------------------------------------- /tests/avalanchego-conformance/src/tests/packer/mod.rs: -------------------------------------------------------------------------------- 1 | mod build_vertex; 2 | --------------------------------------------------------------------------------