Showing preview only (8,380K chars total). Download the full file or copy to clipboard to get everything.
Repository: nomic-io/nomic
Branch: develop
Commit: 3dccaf5d6349
Files: 144
Total size: 62.3 MB
Directory structure:
gitextract_c0qz_ec1/
├── .github/
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
├── SECURITY.md
├── build.rs
├── build.sh
├── genesis/
│ ├── stakenet-2.json
│ ├── stakenet-3.json
│ ├── testnet-4.json
│ └── testnet-4d.json
├── networks/
│ ├── stakenet.toml
│ └── testnet.toml
├── rest/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── rust-toolchain
├── rustfmt.toml
├── src/
│ ├── airdrop.rs
│ ├── app/
│ │ └── migrations.rs
│ ├── app.rs
│ ├── babylon/
│ │ ├── mod.rs
│ │ ├── proto/
│ │ │ ├── babylon/
│ │ │ │ ├── btccheckpoint/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── btccheckpoint.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── btclightclient/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── btclightclient.proto
│ │ │ │ │ ├── event.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── btcstaking/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── btcstaking.proto
│ │ │ │ │ ├── events.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── incentive.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── pop.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── checkpointing/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── bls_key.proto
│ │ │ │ │ ├── checkpoint.proto
│ │ │ │ │ ├── events.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── epoching/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── epoching.proto
│ │ │ │ │ ├── events.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── finality/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── events.proto
│ │ │ │ │ ├── finality.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── incentive/
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── incentive.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── monitor/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ └── query.proto
│ │ │ │ └── zoneconcierge/
│ │ │ │ └── v1/
│ │ │ │ ├── genesis.proto
│ │ │ │ ├── packet.proto
│ │ │ │ ├── params.proto
│ │ │ │ ├── query.proto
│ │ │ │ ├── tx.proto
│ │ │ │ └── zoneconcierge.proto
│ │ │ ├── btccheckpoint.rs
│ │ │ ├── buf.gen.yaml
│ │ │ ├── buf.yaml
│ │ │ ├── gen/
│ │ │ │ ├── babylon.btccheckpoint.v1.rs
│ │ │ │ ├── babylon.btclightclient.v1.rs
│ │ │ │ ├── babylon.btcstaking.v1.rs
│ │ │ │ ├── babylon.checkpointing.v1.rs
│ │ │ │ ├── babylon.epoching.v1.rs
│ │ │ │ ├── babylon.finality.v1.rs
│ │ │ │ ├── babylon.incentive.rs
│ │ │ │ ├── babylon.monitor.v1.rs
│ │ │ │ └── babylon.zoneconcierge.v1.rs
│ │ │ └── mod.rs
│ │ └── relayer.rs
│ ├── bin/
│ │ ├── create-checkpoint.rs
│ │ ├── eth-bootstrap.rs
│ │ ├── get-reserve-scripts.rs
│ │ └── nomic.rs
│ ├── bitcoin/
│ │ ├── adapter.rs
│ │ ├── checkpoint.json
│ │ ├── checkpoint.rs
│ │ ├── deposit_index.rs
│ │ ├── header_queue.rs
│ │ ├── mod.rs
│ │ ├── outpoint_set.rs
│ │ ├── recovery.rs
│ │ ├── relayer.rs
│ │ ├── signatory.rs
│ │ ├── signer.rs
│ │ ├── signet_checkpoint.json
│ │ ├── testnet_checkpoint.json
│ │ └── threshold_sig.rs
│ ├── cosmos.rs
│ ├── error.rs
│ ├── ethereum/
│ │ ├── bootstrap/
│ │ │ └── sepolia.json
│ │ ├── consensus/
│ │ │ ├── mod.rs
│ │ │ ├── relayer.rs
│ │ │ └── test_fixtures.json
│ │ ├── contracts/
│ │ │ ├── Babylon.json
│ │ │ ├── Babylon.sol
│ │ │ ├── CosmosERC20.json
│ │ │ ├── CosmosToken.sol
│ │ │ ├── Nomic.json
│ │ │ └── Nomic.sol
│ │ ├── mod.rs
│ │ ├── proofs.rs
│ │ ├── relayer.rs
│ │ └── signer.rs
│ ├── frost/
│ │ ├── dkg.rs
│ │ ├── encoding.rs
│ │ ├── mod.rs
│ │ ├── signer.rs
│ │ └── signing.rs
│ ├── incentives.rs
│ ├── lib.rs
│ ├── network.rs
│ └── utils.rs
├── stakenet_reserve_scripts.csv
├── testnet_addresses.csv
├── tests/
│ ├── bitcoin.rs
│ ├── data/
│ │ └── block-data
│ ├── header_queue.rs
│ ├── ibc.rs
│ ├── node.rs
│ ├── node_spawn.rs
│ └── relayer.rs
└── wasm/
├── Cargo.toml
├── index.html
└── src/
├── error.rs
├── lib.rs
├── types.rs
└── web_client.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
push:
branches: [master, develop]
pull_request:
branches: [master, develop]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
NOMIC_CLEANUP_LEGACY_BUILD: 1
jobs:
test-base:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2024-07-21
override: true
- name: Cache
uses: actions/cache@v4
with:
path: |
~/.cargo
./target
key: ${{ runner.os }}-test-base-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-test-base-
- name: Test
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose --no-default-features --features=full
test-testnet:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2024-07-21
override: true
- name: Cache
uses: actions/cache@v4
with:
path: |
~/.cargo
./target
key: ${{ runner.os }}-test-testnet-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-test-testnet-
- name: Test
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose --no-default-features --features=full,testnet
test-bitcoin:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2024-07-21
override: true
- name: Cache
uses: actions/cache@v4
with:
path: |
~/.cargo
./target
key: ${{ runner.os }}-test-testnet-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-test-testnet-
- name: Test
env:
RUST_LOG: info
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose --features=devnet bitcoin -- --ignored
check-rest:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2024-07-21
override: true
- name: Check Rest
uses: actions-rs/cargo@v1
with:
command: check
args: --manifest-path rest/Cargo.toml --verbose
build-wasm:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2024-07-21
override: true
- name: Install
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Build Wasm
working-directory: ./wasm
run: wasm-pack -v build --target web
coverage:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2024-07-21
components: llvm-tools-preview
override: true
- name: Cache
id: cache
uses: actions/cache@v4
with:
path: |
~/.cargo
./target
key: ${{ runner.os }}-coverage-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-coverage-
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
name: Install Coverage Tooling
uses: actions-rs/cargo@v1
with:
command: install
args: cargo-llvm-cov --force
- name: Run Coverage
uses: actions-rs/cargo@v1
with:
command: llvm-cov
args: --no-cfg-coverage-nightly --workspace --lcov --output-path lcov.info
- name: Upload to codecov.io
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
fail_ci_if_error: true
format:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2024-07-21
components: rustfmt
override: true
- name: Check
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
clippy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2024-07-21
components: clippy
override: true
- name: Cache
uses: actions/cache@v4
with:
path: |
~/.cargo
./target
key: ${{ runner.os }}-clippy-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-clippy-
- name: Check
uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: -- -D warnings
================================================
FILE: .gitignore
================================================
target
**/target/
merk.db/
.vscode/
.DS_Store
# Added by cargo
/target
wasm/Cargo.lock
================================================
FILE: Cargo.toml
================================================
[package]
name = "nomic"
version = "9.2.0"
authors = ["Nomic DAO Foundation <foundation@nomic.io>"]
edition = "2021"
default-run = "nomic"
[dependencies]
bitcoin = { version = "0.29.2", features = ["serde", "rand"] }
orga = { git = "https://github.com/nomic-io/orga.git", rev = "3b3d25ade40d81cb64f19335535e3a47bb47778f", features = [
"merk-verify",
"feat-ibc",
] }
thiserror = "1.0.30"
ed = { git = "https://github.com/nomic-io/ed", rev = "a657be856792039ff60c2f67e7920e38cd3acffc" }
clap = { version = "3.2.16", features = ["derive"], optional = true }
tokio = { version = "1.39.2", features = ["full"], optional = true }
base64 = "0.13.0"
js-sys = { version = "0.3.55" }
serde = "1.0.208"
serde_json = "1.0.125"
csv = { version = "1.1.6", optional = true }
bech32 = { version = "0.9.1" }
futures = "0.3.21"
toml_edit = "0.13.4"
tendermint-rpc = { version = "0.38.0", features = [
"http-client",
], optional = true }
bitcoincore-rpc-async = { package = "bitcoincore-rpc-async2", version = "4.0.2", optional = true }
bitcoin-script = "0.1.1"
warp = { version = "0.3.2", optional = true }
derive_more = "0.99.17"
pretty_env_logger = { git = "https://github.com/seanmonstar/pretty-env-logger", rev = "f9e35b6dbbf06de55222c944c9e1e176ce73b3a7" }
reqwest = { version = "0.11.16", optional = true, features = ["json"] }
rand = { version = "0.8.5", optional = true }
sha2 = "0.10.6"
bytes = "1.2.1"
serde-big-array = "0.4.1"
log = "0.4.17"
hex = "0.4.3"
toml = { version = "0.7.2", features = ["parse"] }
split-iter = "0.1.0"
chrono = "0.4.19"
tempfile = "3"
home = { version = "0.5.5", optional = true }
semver = "1.0.18"
ics23 = "0.12.0"
cosmos-sdk-proto = { version = "0.23.0", optional = true }
prometheus_exporter = "0.8.5"
lazy_static = "1.4.0"
prost = "0.13.3"
cosmrs = "0.14.0"
ripemd = "0.1.3"
frost-secp256k1-tr = { git = "https://github.com/ZcashFoundation/frost", rev = "51fa7d09f3742563a35d065afcff6ad486430dac", features = [
"nightly",
], optional = true }
serde-hex = "0.1.0"
alloy-core = { version = "0.8.5", optional = true }
alloy-sol-types = { version = "0.8.5", optional = true }
alloy-contract = { version = "0.3.6", optional = true }
alloy-provider = { version = "0.3.6", optional = true }
alloy-signer-local = { version = "0.3.6", optional = true }
helios-consensus-core = { package = "consensus-core", git = "https://github.com/a16z/helios.git", rev = "0.7.0", optional = true }
ethereum_ssz = { version = "0.6.0", optional = true }
ssz_types = { version = "0.7.0", optional = true }
alloy-trie = { version = "0.6.0", optional = true }
alloy-primitives = { version = "0.8.5", optional = true }
alloy-rlp = { version = "0.3.8", optional = true }
tree_hash = { version = "0.7.0", optional = true }
rlp = { version = "0.5.1", optional = true }
ethereum-triedb = { version = "0.1.1", optional = true }
trie-db = { version = "0.28", optional = true }
rlp-derive = { version = "0.2.0", optional = true }
primitive-types = { version = "0.12", features = ["rlp"], optional = true }
hex-literal = { version = "0.4.1", optional = true }
alloy-rpc-types = { version = "0.3.6", optional = true }
alloy-transport = { version = "0.3.6", optional = true }
alloy-rpc-types-eth = { version = "0.3.6", optional = true }
ruint = { version = "1.12.3", optional = true }
[dev-dependencies]
bitcoind = { version = "0.27.0", features = ["22_0"] }
bitcoin_hashes = "0.11.0"
serde_json = "1.0.68"
serde = "1.0.130"
mutagen = "0.1.2"
curl = "0.4.44"
urlencoding = "2.1.2"
crossbeam-channel = "0.5.8"
chrono = "0.4.19"
serial_test = "2.0.0"
tempfile = "3.12.0"
alloy-node-bindings = "0.3.6"
[build-dependencies]
toml = { version = "0.7.2", features = ["parse"] }
semver = "1.0.18"
glob = "0.3.1"
[features]
default = ["full", "testnet"]
full = [
"bitcoincore-rpc-async",
"clap",
"tokio",
"orga/merk-full",
"orga/abci",
"orga/state-sync",
"csv",
"warp",
"rand",
"reqwest",
"tendermint-rpc",
"cosmos-sdk-proto",
"home",
]
testnet = []
devnet = []
legacy-bin = []
signet = []
ethereum = [
"alloy-core",
"alloy-core/dyn-abi",
"alloy-core/json-abi",
"alloy-sol-types",
"alloy-primitives",
"alloy-trie",
"ethereum-triedb",
"alloy-rlp",
"primitive-types",
"ethereum_ssz",
"ssz_types",
"tree_hash",
"rlp",
"rlp-derive",
"trie-db",
"ruint",
"helios-consensus-core",
"alloy-rpc-types-eth",
]
ethereum-full = [
"ethereum",
"alloy-contract",
"alloy-provider",
"alloy-rpc-types",
"alloy-transport",
"alloy-provider/anvil-node",
"alloy-provider/rpc-api",
"alloy-signer-local",
]
frost = ["frost-secp256k1-tr"]
babylon = ["frost"]
[profile.release]
overflow-checks = true
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] }
[[bin]]
name = "nomic"
[[bin]]
name = "create-checkpoint"
[[bin]]
name = "eth-bootstrap"
required-features = ["ethereum-full"]
[[test]]
name = "bitcoin"
required-features = ["devnet"]
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
<h1 align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./nomic-logo-dark-100.png">
<source media="(prefers-color-scheme: light)" srcset="./nomic-logo-100.png">
<img alt="Nomic" src="./nomic-logo-100.png">
</picture>
</h1>
<p align="center">
<i>Decentralized Custody Engine for Bitcoin</i>
</p>

Nomic is a blockchain that offers a decentralized custody solution for Bitcoin. Built on Turbofish’s [Orga](https://github.com/turbofish-org/orga), a custom high-performance blockchain application framework. Nomic mints nBTC, a token backed 1:1 with BTC, using [IBC](https://www.ibcprotocol.dev/) for secure and efficient bridging.
## Running a Node
Running a node increases the health of the network by decentralizing ledger validation and data, even for non-validator nodes. Community members are encouraged to run a node, especially when regularly interacting with the network via transactions and queries.
[Nomic Network Docs](https://docs.nomic.io/)
## Integrating with Nomic
Integrating with nBTC enables accepting Bitcoin deposits with Interchain Deposits to any IBC-enabled blockchain.
[nBTC Docs](https://github.com/nomic-io/nomic-bitcoin-js/blob/main/README.md)
## Contributing
Nomic is an open-source project spearheaded by contributors. Anyone is able to contribute to Nomic via GitHub.
[Contribute to Nomic](https://github.com/nomic-io/nomic/contribute)
## Security
Nomic is currently undergoing security audits.
Vulnerabilities should not be reported through public channels, including GitHub Issues. You can report a vulnerability via GitHub's Private Vulnerability Reporting or via the Nomic DAO Foundation at `foundation@nomic.io`.
[Report a Vulnerability](https://github.com/nomic-io/nomic/security/advisories/new)
## License
Licensed under the Apache License, Version 2.0 (the "License"); you may not use the files in this repository except in compliance with the License. You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
---
Copyright © 2024 Nomic DAO Foundation.
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Introduction
Security researchers are essential in identifying vulnerabilities that may impact the Nomic ecosystem. If you have discovered a security vulnerability in the Nomic network or any repository managed by the Nomic DAO Foundation, we encourage you to notify using one of the methods outlined below.
### Guidelines for Responsible Vulnerability Testing and Reporting
1. **Refrain from testing vulnerabilities on publicly accessible environments**, including but not limited to:
- Nomic mainnet.
- Nomic frontend.
- Nomic public testnets.
- Nomic testnet frontend.
2. **Avoid reporting security vulnerabilities through public channels, including GitHub issues.**
## Security Audits
| Date | Auditor | Scope | Report |
| ---: | :---: | :--- | :---: |
| October 2024 | Trail of Bits | `nomic` <br> `nomic-bitcoin-js` | [📄](https://github.com/trailofbits/publications/blob/master/reviews/2024-11-nomic-securityreview.pdf) |
### Dependency Security Audits
| Date | Auditor | Scope | Report |
| ---: | :---: | :--- | :---: |
| October 2024 | Trail of Bits | `orga` `merk` `ed` `abci2` | [📄](https://github.com/trailofbits/publications/blob/master/reviews/2024-11-orgaandmerk-securityreview.pdf) |
## Reporting a Vulnerability
To privately report a security vulnerability, please choose one of the following options:
### 1. Email
Send your detailed vulnerability report to `security@nomic.io`.
### 2. GitHub Private Vulnerability Reporting
Utilize [GitHub's Private Vulnerability Reporting](https://github.com/nomic-io/nomic/security/advisories/new) for confidential disclosure.
## Submit Vulnerability Report
When reporting a vulnerability through either method, please include the following details to aid in assessment:
- Type of vulnerability.
- Description of the vulnerability.
- Steps to reproduce the issue.
- Impact of the issue.
- Explanation of how an attacker could exploit it.
## Vulnerability Disclosure Process
1. **Initial Report**: Submit the vulnerability via one of the above channels.
2. **Confirmation**: We will confirm receipt of your report within 48 hours.
3. **Assessment**: Our security team will evaluate the vulnerability and inform you of its severity and the estimated time frame for resolution.
4. **Resolution**: Once fixed, you will be contacted to verify the solution.
5. **Public Disclosure**: Details of the vulnerability may be publicly disclosed after ensuring it poses no further risk.
During the vulnerability disclosure process, we ask security researchers to keep vulnerabilities and communications around vulnerability submissions private and confidential until a patch is developed. Should a security issue require a network upgrade, additional time may be needed to raise a governance proposal and complete the upgrade.
During this time:
- Avoid exploiting any vulnerabilities you discover.
- Demonstrate good faith by not disrupting or degrading Nomic's services.
## Severity Characterization
| Severity | Description |
|--------------|--------------------------------------------------------------------------|
| **CRITICAL** | Immediate threat to critical systems (e.g., chain halts, funds at risk). |
| **HIGH** | Significant impact on major functionality. |
| **MEDIUM** | Impacts minor features or exposes non-sensitive data. |
| **LOW** | Minimal impact. |
## Bug Bounty
Though Nomic does not yet have an official bug bounty program, the Nomic DAO Foundation generally offers rewards to security researchers who responsibly disclose vulnerabilities. Bounties are generally awarded for vulnerabilities classified as **high** or **critical** severity. Bounty amounts will be determined during the disclosure process, after the severity has been assessed.
> [!WARNING]
> Targeting production environments will disqualify you from receiving any bounty.
## Feedback on this Policy
For recommendations on how to improve this policy, either submit a pull request or email `security@nomic.io`.
================================================
FILE: build.rs
================================================
fn main() {
let branch_name = std::process::Command::new("git")
.args(["symbolic-ref", "--short", "HEAD"])
.output()
.unwrap();
let branch_name = String::from_utf8(branch_name.stdout)
.unwrap()
.trim()
.to_string();
println!("cargo:rustc-env=GIT_BRANCH={}", branch_name);
#[cfg(feature = "legacy-bin")]
{
println!("cargo:rerun-if-changed=build.sh");
println!("cargo:rerun-if-env-changed=NOMIC_LEGACY_VERSION");
println!("cargo:rerun-if-env-changed=NOMIC_LEGACY_REV");
let version = std::env::var("NOMIC_LEGACY_VERSION");
let rev = std::env::var("NOMIC_LEGACY_REV");
let rev = if let Ok(rev) = rev {
rev
} else {
let mut version_req_str = if let Ok(version_req_str) = version {
version_req_str
} else {
#[cfg(feature = "testnet")]
let toml = {
println!("cargo:rerun-if-changed=networks/testnet.toml");
include_str!("networks/testnet.toml")
};
#[cfg(not(feature = "testnet"))]
let toml = {
println!("cargo:rerun-if-changed=networks/stakenet.toml");
include_str!("networks/stakenet.toml")
};
let config: toml::Value = toml::from_str(toml).unwrap();
if let Some(legacy_version) = config.as_table().unwrap().get("legacy_version") {
legacy_version.as_str().unwrap().to_string()
} else {
println!("No legacy_version set in network config");
println!("cargo:rustc-env=NOMIC_LEGACY_BUILD_PATH=/dev/null");
println!("cargo:rustc-env=NOMIC_LEGACY_BUILD_VERSION=");
return;
}
};
if version_req_str.chars().next().unwrap().is_numeric() {
version_req_str = format!("={}", version_req_str);
}
let version_req = semver::VersionReq::parse(&version_req_str).unwrap();
assert!(std::process::Command::new("git")
.args(["fetch", "--tags", "--force"])
.spawn()
.unwrap()
.wait_with_output()
.unwrap()
.status
.success());
let version = std::process::Command::new("git")
.args(["tag"])
.output()
.unwrap()
.stdout
.split(|&b| b == b'\n')
.map(|b| String::from_utf8(b.to_vec()).unwrap())
.filter(|s| s.starts_with('v'))
.filter_map(|s| semver::Version::parse(&s[1..]).ok())
.filter(|v| version_req.matches(v))
.max()
.unwrap();
println!(
"Highest matching git tag for version requirement '{}': v{}",
version_req_str, version,
);
format!("v{}", version)
};
println!("Using rev: {}", rev);
let shell = std::env::var("SHELL").unwrap_or("/bin/bash".to_string());
println!("Using shell: {}", shell);
#[cfg(feature = "testnet")]
let default_features = "full,feat-ibc,testnet";
#[cfg(not(feature = "testnet"))]
let default_features = "full,feat-ibc";
let cargo_features =
std::env::var("NOMIC_LEGACY_FEATURES").unwrap_or(default_features.to_string());
let forwarded_envvars = [
"OUT_DIR",
"PATH",
"NOMIC_CLEANUP_LEGACY_BUILD",
"ROCKSDB_LIB_DIR",
"ROCKSDB_STATIC",
];
let mut cmd = std::process::Command::new(shell);
cmd.env_clear();
for var in forwarded_envvars {
if let Ok(val) = std::env::var(var) {
cmd.env(var, val);
}
}
let res = cmd
.env("NOMIC_LEGACY_REV", rev)
.env("CARGO_FEATURES", cargo_features)
.args(["build.sh"])
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(res.status.success());
}
}
================================================
FILE: build.sh
================================================
#!/bin/bash
set -e
BUILD_DIR=$OUT_DIR/nomic
NOMIC_LEGACY_PATH=$OUT_DIR/nomic-$NOMIC_LEGACY_REV
if [ ! -f "$NOMIC_LEGACY_PATH" ]; then
echo "Building legacy nomic at $NOMIC_LEGACY_PATH..."
if [ ! -d "$BUILD_DIR" ]; then
git clone https://github.com/nomic-io/nomic.git $BUILD_DIR
fi
cd $BUILD_DIR
git checkout .
git checkout main
git pull
git checkout $NOMIC_LEGACY_REV
git fetch
rustc --version
echo "Building with features: $CARGO_FEATURES"
cargo build --release --no-default-features --features $CARGO_FEATURES
cp $BUILD_DIR/target/release/nomic $NOMIC_LEGACY_PATH
else
echo "Skipping legacy nomic binary build (already exists at $NOMIC_LEGACY_PATH)"
fi
if [[ ! -z "${NOMIC_CLEANUP_LEGACY_BUILD}" ]]; then
rm -rf $BUILD_DIR
fi
echo "cargo:rustc-env=NOMIC_LEGACY_BUILD_PATH=$NOMIC_LEGACY_PATH"
echo "cargo:rustc-env=NOMIC_LEGACY_BUILD_VERSION=$($NOMIC_LEGACY_PATH --version)"
================================================
FILE: genesis/stakenet-2.json
================================================
{
"genesis_time": "2022-03-31T16:00:00Z",
"chain_id": "nomic-stakenet-2",
"initial_height": "0",
"consensus_params": {
"block": {
"max_bytes": "22020096",
"max_gas": "-1",
"time_iota_ms": "1000"
},
"evidence": {
"max_age_num_blocks": "100000",
"max_age_duration": "172800000000000",
"max_bytes": "1048576"
},
"validator": {
"pub_key_types": ["ed25519"]
},
"version": {}
},
"validators": [],
"app_hash": ""
}
================================================
FILE: genesis/stakenet-3.json
================================================
{
"genesis_time": "2022-07-04T00:00:00Z",
"chain_id": "nomic-stakenet-3",
"initial_height": "0",
"consensus_params": {
"block": {
"max_bytes": "22020096",
"max_gas": "-1",
"time_iota_ms": "1000"
},
"evidence": {
"max_age_num_blocks": "100000",
"max_age_duration": "172800000000000",
"max_bytes": "1048576"
},
"validator": {
"pub_key_types": ["ed25519"]
},
"version": {}
},
"validators": [],
"app_hash": ""
}
================================================
FILE: genesis/testnet-4.json
================================================
{
"genesis_time": "2022-06-22T00:00:00Z",
"chain_id": "nomic-testnet-4",
"initial_height": "1",
"consensus_params": {
"block": {
"max_bytes": "22020096",
"max_gas": "-1",
"time_iota_ms": "1000"
},
"evidence": {
"max_age_num_blocks": "100000",
"max_age_duration": "172800000000000",
"max_bytes": "1048576"
},
"validator": {
"pub_key_types": [
"ed25519"
]
},
"version": {}
},
"app_hash": ""
}
================================================
FILE: genesis/testnet-4d.json
================================================
{
"genesis_time": "2022-10-05T00:00:00Z",
"chain_id": "nomic-testnet-4d",
"initial_height": "0",
"consensus_params": {
"block": {
"max_bytes": "22020096",
"max_gas": "-1",
"time_iota_ms": "1000"
},
"evidence": {
"max_age_num_blocks": "100000",
"max_age_duration": "172800000000000",
"max_bytes": "1048576"
},
"validator": {
"pub_key_types": ["ed25519"]
},
"version": {}
},
"validators": [],
"app_hash": ""
}
================================================
FILE: networks/stakenet.toml
================================================
state_sync_rpc = [
"http://161.35.51.124:26667",
"http://161.35.51.124:26667"
]
tendermint_flags = [
"--p2p.seeds",
"""
238120dfe716082754048057c1fdc3d6f09609b5@161.35.51.124:26656
""",
]
btc_relayer = [
"https://relayer.nomic.mappum.io:8443"
]
legacy_version = "8.0.x"
genesis = """
{
"genesis_time": "2022-07-04T00:00:00Z",
"chain_id": "nomic-stakenet-3",
"initial_height": "0",
"consensus_params": {
"block": {
"max_bytes": "22020096",
"max_gas": "-1",
"time_iota_ms": "1000"
},
"evidence": {
"max_age_num_blocks": "100000",
"max_age_duration": "172800000000000",
"max_bytes": "1048576"
},
"validator": {
"pub_key_types": ["ed25519"]
},
"version": {}
},
"validators": [],
"app_hash": ""
}
"""
================================================
FILE: networks/testnet.toml
================================================
state_sync_rpc = [
"http://147.182.171.216:26657",
"http://147.182.171.216:26657",
]
tendermint_flags = ["--p2p.seeds", """
a07d56aa65e395c332a7bf226ec4e2f844519ffa@147.182.171.216:26656,\
"""]
btc_relayer = ["https://relayer.nomic-testnet.mappum.io:8443"]
legacy_version = "9.1.x"
genesis = """
{
"app_hash": "",
"chain_id": "nomic-testnet-6",
"consensus_params": {
"block": {
"max_bytes": "22020096",
"max_gas": "-1",
"time_iota_ms": "1000"
},
"evidence": {
"max_age_duration": "172800000000000",
"max_age_num_blocks": "100000",
"max_bytes": "1048576"
},
"validator": {
"pub_key_types": [
"ed25519"
]
},
"version": {}
},
"genesis_time": "2024-09-12T01:27:04.17850332Z",
"initial_height": "0",
"validators": [
{
"address": "563EAA34B8A607C49F0F89008A9542CD0F06D91C",
"name": "",
"power": "10",
"pub_key": {
"type": "tendermint/PubKeyEd25519",
"value": "H/uHaF1ZUTHzLRSmOY8g87Sgpmuh/Hz6Wdxpn09WFjo="
}
}
]
}
"""
================================================
FILE: rest/Cargo.toml
================================================
[package]
name = "nomic-rest"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rocket = { version = "0.5.0-rc.1", features = ["json", "tls"] }
nomic = { path = "..", default-features = true, features = [
"full",
"testnet",
] }
hex = "0.4.3"
tendermint-rpc = { version = "=0.23.7", features = ["http-client"] }
tendermint = "=0.23.7"
tendermint-proto = "=0.23.9"
ibc = { version = "0.54.0", features = ["borsh"] }
ibc-proto = { version = "0.47.0", default-features = false, features = [
"std",
"borsh",
"serde",
] }
base64 = "0.13.0"
serde = "1.0.136"
serde_json = "1.0.78"
lazy_static = "1.4.0"
tokio = "1.19.2"
chrono = { version = "0.4.31", features = ["serde"] }
sha2 = "0.10.6"
bech32 = { version = "0.9.1" }
================================================
FILE: rest/src/main.rs
================================================
#[macro_use]
extern crate rocket;
use chrono::{TimeZone, Utc};
use nomic::{
app::{InnerApp, Nom},
bitcoin::Nbtc,
orga::{
client::{wallet::Unsigned, AppClient},
coins::{Address, Amount, Decimal, DelegationInfo, Symbol, ValidatorQueryInfo},
encoding::EofTerminatedString,
tendermint::client::HttpClient,
},
utils::DeclareInfo,
};
use rocket::response::status::BadRequest;
use rocket::serde::json::{json, Value};
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::Arc;
use tokio::sync::RwLock;
use ibc::clients::tendermint::types::ClientState;
use ibc::core::host::types::identifiers::ConnectionId as IbcConnectionId;
use ibc_proto::google::protobuf::Any;
use ibc_proto::ibc::core::client::v1::IdentifiedClientState;
use ibc_proto::ibc::core::connection::v1::ConnectionEnd as RawConnectionEnd;
use ibc_proto::ibc::lightclients::tendermint::v1::ClientState as RawTmClientState;
use bech32::ToBase32;
use sha2::Digest;
use tendermint_proto::types::CommitSig as RawCommitSig;
use tendermint_rpc as tm;
use tm::Client as _;
lazy_static::lazy_static! {
static ref QUERY_CACHE: Arc<RwLock<HashMap<String, (u64, String)>>> = Arc::new(RwLock::new(HashMap::new()));
}
fn app_host() -> &'static str {
"http://localhost:26657"
}
fn app_client() -> AppClient<InnerApp, InnerApp, HttpClient, Nom, Unsigned> {
nomic::app_client(app_host())
}
// DONE /cosmos/bank/v1beta1/balances/{address}
// DONE /cosmos/distribution/v1beta1/delegators/{address}/rewards
// TODO /cosmos/staking/v1beta1/delegations/{address}
// DONE /cosmos/staking/v1beta1/validators
// DONE /cosmos/staking/v1beta1/delegators/{address}/unbonding_delegations
// /cosmos/staking/v1beta1/validators/{address}
// /cosmos/gov/v1beta1/proposals
// /cosmos/gov/v1beta1/proposals/{proposalId}
// /cosmos/gov/v1beta1/proposals/{proposalId}/votes/{address}
// /cosmos/gov/v1beta1/proposals/{proposalId}/tally
// /ibc/apps/transfer/v1/denom_traces/{hash}
// /ibc/core/channel/v1/channels/{channelId}/ports/{portId}/client_state
#[get("/cosmos/staking/v1beta1/validators?<status>")]
async fn validators(status: Option<String>) -> Value {
let all_validators: Vec<ValidatorQueryInfo> = app_client()
.query(|app: InnerApp| app.staking.all_validators())
.await
.unwrap();
let all_keys: Vec<_> = app_client()
.query(|app: InnerApp| app.staking.consensus_keys())
.await
.unwrap();
let mut validators = vec![];
for validator in all_validators {
let validator_status = if validator.unbonding {
"BOND_STATUS_UNBONDING"
} else if validator.in_active_set {
"BOND_STATUS_BONDED"
} else {
"BOND_STATUS_UNBONDED"
};
if !status.is_none() && status != Some(validator_status.to_owned()) {
continue;
}
let cons_key = all_keys
.iter()
.find(|entry| (**entry).0 == validator.address.into())
.map(|entry| (*entry).1)
.unwrap();
let info: DeclareInfo =
serde_json::from_str(String::from_utf8(validator.info.to_vec()).unwrap().as_str())
.unwrap_or(DeclareInfo {
details: "".to_string(),
identity: "".to_string(),
moniker: "".to_string(),
website: "".to_string(),
});
validators.push(json!(
{
"operator_address": validator.address.to_string(),
"consensus_pubkey": {
"@type": "/cosmos.crypto.ed25519.PubKey",
"key": base64::encode(cons_key)
},
"jailed": validator.jailed,
"status": validator_status,
"tokens": validator.amount_staked.to_string(),
"delegator_shares": validator.amount_staked.to_string(),
"description": {
"moniker": info.moniker,
"identity": info.identity,
"website": info.website,
"security_contact": "",
"details": info.details
},
"unbonding_height": "0", // TODO
"unbonding_time": "1970-01-01T00:00:00Z", // TODO
"commission": {
"commission_rates": {
"rate": validator.commission.rate,
"max_rate": validator.commission.max,
"max_change_rate": validator.commission.max_change
},
"update_time": "2023-08-04T06:00:00.000000000Z" // TODO
},
"min_self_delegation": validator.min_self_delegation.to_string()
}));
}
json!({
"validators": validators,
"pagination": {
"next_key": null,
"total": validators.len().to_string()
}
})
}
#[get("/cosmos/staking/v1beta1/validators/<address>")]
async fn validator(address: &str) -> Value {
let address: Address = address.parse().unwrap();
// TODO: cache
let all_validators: Vec<ValidatorQueryInfo> = app_client()
.query(|app: InnerApp| app.staking.all_validators())
.await
.unwrap();
let mut validators = vec![];
for validator in all_validators {
if validator.address != address.into() {
continue;
}
let cons_key = app_client()
.query(|app: InnerApp| app.staking.consensus_key(validator.address.into()))
.await
.unwrap();
let status = if validator.unbonding {
"BOND_STATUS_UNBONDING"
} else if validator.in_active_set {
"BOND_STATUS_BONDED"
} else {
"BOND_STATUS_UNBONDED"
};
let info: DeclareInfo =
serde_json::from_str(String::from_utf8(validator.info.to_vec()).unwrap().as_str())
.unwrap_or(DeclareInfo {
details: "".to_string(),
identity: "".to_string(),
moniker: "".to_string(),
website: "".to_string(),
});
validators.push(json!(
{
"operator_address": validator.address.to_string(),
"consensus_pubkey": {
"@type": "/cosmos.crypto.ed25519.PubKey",
"key": base64::encode(cons_key)
},
"jailed": validator.jailed,
"status": status,
"tokens": validator.amount_staked.to_string(),
"delegator_shares": validator.amount_staked.to_string(),
"description": {
"moniker": info.moniker,
"identity": info.identity,
"website": info.website,
"security_contact": "",
"details": info.details
},
"unbonding_height": "0", // TODO
"unbonding_time": "1970-01-01T00:00:00Z", // TODO
"commission": {
"commission_rates": {
"rate": validator.commission.rate,
"max_rate": validator.commission.max,
"max_change_rate": validator.commission.max_change
},
"update_time": "2023-08-04T06:00:00.000000000Z" // TODO
},
"min_self_delegation": validator.min_self_delegation.to_string()
}));
}
let validator = validators.first().unwrap();
json!({
"validator": validator,
})
}
#[get("/cosmos/bank/v1beta1/balances/<address>")]
async fn bank_balances(address: &str) -> Result<Value, BadRequest<String>> {
let address: Address = address.parse().unwrap();
let nom_balance: u64 = app_client()
.query(|app| app.accounts.balance(address))
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?
.into();
let nbtc_balance: u64 = app_client()
.query(|app| app.bitcoin.accounts.balance(address))
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?
.into();
Ok(json!({
"balances": [
{
"denom": "unom",
"amount": nom_balance.to_string(),
},
{
"denom": "usat",
"amount": nbtc_balance.to_string(),
}
],
"pagination": {
"next_key": null,
"total": "2"
}
}))
}
#[get("/bank/balances/<address>")]
async fn bank_balances_2(address: &str) -> Result<Value, BadRequest<String>> {
let address: Address = address.parse().unwrap();
let balance: u64 = app_client()
.query(|app| app.accounts.balance(address))
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?
.into();
Ok(json!({
"height": "0",
"result": [
{
"denom": "unom",
"amount": balance.to_string(),
}
]
}))
}
#[get("/auth/accounts/<addr_str>")]
async fn auth_accounts(addr_str: &str) -> Result<Value, BadRequest<String>> {
let address: Address = addr_str.parse().unwrap();
let balance: u64 = app_client()
.query(|app| app.accounts.balance(address))
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?
.into();
let mut nonce: u64 = app_client()
.query_root(|app| app.inner.inner.borrow().inner.inner.inner.nonce(address))
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?;
nonce += 1;
Ok(json!({
"height": "0",
"result": {
"type": "cosmos-sdk/BaseAccount",
"value": {
"address": addr_str,
"coins": [
{
"denom": "unom",
"amount": balance.to_string(),
}
],
"sequence": nonce.to_string()
}
}
}))
}
#[get("/cosmos/auth/v1beta1/accounts/<addr_str>")]
async fn auth_accounts2(addr_str: &str) -> Result<Value, BadRequest<String>> {
let address: Address = addr_str.parse().unwrap();
let _balance: u64 = app_client()
.query(|app| app.accounts.balance(address))
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?
.into();
let mut nonce: u64 = app_client()
.query_root(|app| app.inner.inner.borrow().inner.inner.inner.nonce(address))
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?;
nonce += 1;
Ok(json!({
"account": {
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": addr_str,
"pub_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "Atl2HeBoLMorGAUPTH0hXk2Sx72reuw8x2V1puqwV+jN"
},
"account_number": "0",
"sequence": nonce.to_string()
}
}))
}
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
struct TxRequest {
tx: serde_json::Value,
mode: String,
}
#[post("/txs", data = "<tx>")]
async fn txs(tx: &str) -> Result<Value, BadRequest<String>> {
dbg!(tx);
let client = tm::HttpClient::new(app_host()).unwrap();
let tx_bytes = if let Some('{') = tx.chars().next() {
let tx: TxRequest = serde_json::from_str(tx).unwrap();
serde_json::to_vec(&tx.tx).unwrap()
} else {
base64::decode(tx).map_err(|e| BadRequest(format!("{:?}", e)))?
};
let res = client
.broadcast_tx_commit(tx_bytes.into())
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?;
let tx_response = if res.check_tx.code.is_err() {
&res.check_tx
} else {
&res.deliver_tx
};
Ok(json!({
"height": "0",
"txhash": res.hash,
"codespace": tx_response.codespace,
"code": tx_response.code,
"data": "",
"raw_log": "[]",
"logs": [ tx_response.log ],
"info": tx_response.info,
"gas_wanted": tx_response.gas_wanted,
"gas_used": tx_response.gas_used,
"tx": null,
"timestamp": ""
}))
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
struct TxRequest2 {
tx_bytes: String,
mode: String,
}
#[post("/cosmos/tx/v1beta1/txs", data = "<tx>")]
async fn txs2(tx: &str) -> Result<Value, BadRequest<String>> {
dbg!(tx);
let client = tm::HttpClient::new(app_host()).unwrap();
let tx_bytes = if let Some('{') = tx.chars().next() {
let tx: TxRequest2 = serde_json::from_str(tx).unwrap();
base64::decode(tx.tx_bytes.as_str()).map_err(|e| BadRequest(format!("{:?}", e)))?
} else {
base64::decode(tx).map_err(|e| BadRequest(format!("{:?}", e)))?
};
let res = client
.broadcast_tx_commit(tx_bytes.into())
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?;
let tx_response = if res.check_tx.code.is_err() {
&res.check_tx
} else {
&res.deliver_tx
};
Ok(json!({
"height": "0",
"txhash": res.hash,
"codespace": tx_response.codespace,
"code": tx_response.code,
"data": "",
"raw_log": "[]",
"logs": [ tx_response.log ],
"info": tx_response.info,
"gas_wanted": tx_response.gas_wanted,
"gas_used": tx_response.gas_used,
"tx": null,
"timestamp": ""
}))
}
fn time_now() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs()
}
#[get("/query/<query>?<height>")]
async fn query(query: &str, height: Option<u32>) -> Result<String, BadRequest<String>> {
let cache = QUERY_CACHE.clone();
let lock = cache.read_owned().await;
let cached_res = lock.get(query).cloned();
let cache_hit = cached_res.is_some();
drop(lock);
dbg!((&query, cache_hit));
let now = time_now();
// if let Some((time, res)) = cached_res {
// if now - time < 15 {
// return Ok(res.clone())
// }
// }
let client = tm::HttpClient::new(app_host()).unwrap();
let query_bytes = hex::decode(query).map_err(|e| BadRequest(format!("{:?}", e)))?;
let res = client
.abci_query(None, query_bytes, height.map(Into::into), true)
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?;
let res_height: u64 = res.height.into();
let res_height: u32 = res_height.try_into().unwrap();
if let tendermint::abci::Code::Err(code) = res.code {
let msg = format!("code {}: {}", code, res.log);
return Err(BadRequest(msg));
}
let res_b64 = base64::encode([res_height.to_be_bytes().to_vec(), res.value].concat());
let cache = QUERY_CACHE.clone();
let mut lock = cache.write_owned().await;
lock.insert(query.to_string(), (now, res_b64.clone()));
drop(lock);
Ok(res_b64)
}
#[get("/cosmos/staking/v1beta1/delegations/<address>")]
async fn staking_delegators_delegations(address: &str) -> Value {
let address: Address = address.parse().unwrap();
let delegations = app_client()
.query(|app| app.staking.delegations(address))
.await
.unwrap();
let mut entries = vec![];
for (validator_address, delegation) in delegations {
if delegation.staked == 0 {
continue;
}
entries.push(json!({
"delegation": {
"delegator_address": address.to_string(),
"validator_address": validator_address.to_string(),
"shares": delegation.staked.to_string(),
},
"balance": {
"denom": "unom",
"amount": delegation.staked.to_string(),
},
}))
}
json!({
"delegation_responses": entries,
"pagination": { "next_key": null, "total": entries.len().to_string() }
})
}
#[get("/staking/delegators/<address>/delegations")]
async fn staking_delegators_delegations_2(address: &str) -> Result<Value, BadRequest<String>> {
let address: Address = address.parse().unwrap();
let delegations = app_client()
.query(|app| app.staking.delegations(address))
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?;
let total_staked: u64 = delegations
.iter()
.map(|(_, d)| -> u64 { d.staked.into() })
.sum();
Ok(json!({ "height": "0", "result": [
{
"delegator_address": "",
"validator_address": "",
"shares": "0",
"balance": {
"denom": "NOM",
"amount": total_staked.to_string(),
}
}
] }))
}
#[get("/cosmos/staking/v1beta1/delegators/<address>/unbonding_delegations")]
async fn staking_delegators_unbonding_delegations(address: &str) -> Value {
use chrono::{TimeZone, Utc};
let address: Address = address.parse().unwrap();
let delegations: Vec<(Address, DelegationInfo)> = app_client()
.query(|app: InnerApp| app.staking.delegations(address))
.await
.unwrap();
let mut unbonds = vec![];
for (val_address, delegation) in delegations {
if delegation.unbonding.len() == 0 {
continue;
}
let mut entries = vec![];
for unbond in delegation.unbonding {
let t = Utc.timestamp_opt(unbond.start_seconds, 0).unwrap();
entries.push(json!({
"creation_height": "0", // TODO
"completion_time": t, // TODO
"initial_balance": unbond.amount.to_string(),
"balance": unbond.amount.to_string()
}))
}
unbonds.push(json!({
"delegator_address": address,
"validator_address": val_address,
"entries": entries
}))
}
json!({
"unbonding_responses": unbonds,
"pagination": { "next_key": null, "total": unbonds.len().to_string() }
})
}
#[get("/staking/delegators/<_address>/unbonding_delegations")]
fn staking_delegators_unbonding_delegations_2(_address: &str) -> Value {
json!({ "height": "0", "result": [] })
}
#[get("/cosmos/staking/v1beta1/validators/<address>/delegations")]
async fn staking_validators_delegations(address: &str) -> Value {
let validator_address: Address = address.parse().unwrap();
let delegations: Vec<(Address, DelegationInfo)> = app_client()
.query(|app: InnerApp| app.staking.validator_delegations(validator_address))
.await
.unwrap();
let mut entries = vec![];
for (delegator_address, delegation) in delegations {
if delegation.staked == 0 {
continue;
}
entries.push(json!({
"delegation": {
"delegator_address": delegator_address.to_string(),
"validator_address": validator_address.to_string(),
"shares": delegation.staked.to_string(),
},
"balance": {
"denom": "unom",
"amount": delegation.staked.to_string(),
},
}))
}
json!({
"delegation_responses": entries,
"pagination": { "next_key": null, "total": entries.len().to_string() }
})
}
#[get("/cosmos/staking/v1beta1/validators/<validator_address>/delegations/<delegator_address>")]
async fn staking_validator_single_delegation(
validator_address: &str,
delegator_address: &str,
) -> Value {
let delegator_address: Address = delegator_address.parse().unwrap();
let validator_address: Address = validator_address.parse().unwrap();
let delegations: Vec<(Address, DelegationInfo)> = app_client()
.query(|app: InnerApp| app.staking.delegations(delegator_address))
.await
.unwrap();
let delegation: &DelegationInfo = delegations
.iter()
.find(|(validator, _delegation)| *validator == validator_address)
.map(|(_validator, delegation)| delegation)
.unwrap();
json!({
"delegation_response": {
"delegation": {
"delegator_address": delegator_address,
"validator_address": validator_address,
"shares": delegation.staked.to_string(),
},
"balance": {
"denom": "unom",
"amount": delegation.staked.to_string(),
}
}
})
}
#[get("/cosmos/staking/v1beta1/validators/<address>/unbonding_delegations")]
async fn staking_validators_unbonding_delegations(address: &str) -> Value {
let validator_address: Address = address.parse().unwrap();
let delegations: Vec<(Address, DelegationInfo)> = app_client()
.query(|app: InnerApp| app.staking.validator_delegations(validator_address))
.await
.unwrap();
let mut unbonds = vec![];
for (delegator_address, delegation) in delegations {
if delegation.unbonding.len() == 0 {
continue;
}
let mut entries = vec![];
for unbond in delegation.unbonding {
let t = Utc.timestamp_opt(unbond.start_seconds, 0).unwrap();
entries.push(json!({
"creation_height": "0", // TODO
"completion_time": t, // TODO
"initial_balance": unbond.amount.to_string(),
"balance": unbond.amount.to_string()
}))
}
unbonds.push(json!({
"delegator_address": delegator_address,
"validator_address": validator_address,
"entries": entries
}))
}
json!({
"unbonding_responses": unbonds,
"pagination": { "next_key": null, "total": unbonds.len().to_string()
} })
}
#[get("/cosmos/distribution/v1beta1/delegators/<address>/rewards")]
async fn distribution_delegators_rewards(address: &str) -> Value {
let address: Address = address.parse().unwrap();
let delegations: Vec<(Address, DelegationInfo)> = app_client()
.query(|app: InnerApp| app.staking.delegations(address))
.await
.unwrap();
let mut rewards = vec![];
let mut total_nom = 0;
let mut total_nbtc = 0;
for (validator, delegation) in delegations {
let mut reward = vec![];
let liquid: u64 = delegation
.liquid
.iter()
.map(|(_, amount)| -> u64 { (*amount).into() })
.sum();
if liquid == 0 {
continue;
}
let liquid_nom: u64 = delegation
.liquid
.iter()
.find(|(denom, _)| *denom == Nom::INDEX)
.unwrap_or(&(0, 0.into()))
.1
.into();
total_nom += liquid_nom;
reward.push(json!({
"denom": "unom",
"amount": liquid_nom.to_string(),
}));
let liquid_nbtc: u64 = delegation
.liquid
.iter()
.find(|(denom, _)| *denom == Nbtc::INDEX)
.unwrap_or(&(0, 0.into()))
.1
.into();
reward.push(json!({
"denom": "usat",
"amount": liquid_nbtc.to_string(),
}));
total_nbtc += liquid_nbtc;
rewards.push(json!({
"validator_address": validator.to_string(),
"reward": reward,
}));
}
json!({
"rewards": rewards,
"total": [
{
"denom": "unom",
"amount": total_nom.to_string(),
},
{
"denom": "usat",
"amount": total_nbtc.to_string(),
}
]
})
}
#[get("/cosmos/distribution/v1beta1/validators/<address>/commission")]
async fn distribution_validator_commission(address: &str) -> Value {
json!({
"commission": {
"commission": []
}
})
}
#[get("/cosmos/distribution/v1beta1/delegators/<address>/rewards/<validator_address>")]
async fn distribution_delegators_rewards_for_validator(
address: &str,
validator_address: &str,
) -> Value {
let address: Address = address.parse().unwrap();
let validator_address: Address = validator_address.parse().unwrap();
let delegations: Vec<(Address, DelegationInfo)> = app_client()
.query(|app: InnerApp| app.staking.delegations(address))
.await
.unwrap();
let delegation: &DelegationInfo = delegations
.iter()
.find(|(validator, _delegation)| *validator == validator_address)
.map(|(_validator, delegation)| delegation)
.unwrap();
let mut rewards = vec![];
let liquid_nom: u64 = delegation
.liquid
.iter()
.find(|(denom, _)| *denom == Nom::INDEX)
.unwrap_or(&(0, 0.into()))
.1
.into();
rewards.push(json!({
"denom": "unom",
"amount": liquid_nom.to_string(),
}));
let liquid_nbtc: u64 = delegation
.liquid
.iter()
.find(|(denom, _)| *denom == Nbtc::INDEX)
.unwrap_or(&(0, 0.into()))
.1
.into();
rewards.push(json!({
"denom": "usat",
"amount": liquid_nbtc.to_string(),
}));
json!({
"rewards": rewards
})
}
#[get("/cosmos/mint/v1beta1/inflation")]
async fn minting_inflation() -> Result<Value, BadRequest<String>> {
let validators = app_client()
.query(|app| app.staking.all_validators())
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?;
let total_staked: u64 = validators
.iter()
.map(|v| -> u64 { v.amount_staked.into() })
.sum();
let total_staked = Amount::from(total_staked + 1);
let yearly_inflation = Decimal::from(64_682_541_340_000);
let apr = (yearly_inflation / Decimal::from(4) / Decimal::from(total_staked))
.result()
.map_err(|e| BadRequest(format!("{:?}", e)))?;
Ok(json!({ "inflation": apr.to_string() }))
}
#[get("/minting/inflation")]
async fn minting_inflation_2() -> Result<Value, BadRequest<String>> {
let validators = app_client()
.query(|app| app.staking.all_validators())
.await
.map_err(|e| BadRequest(format!("{:?}", e)))?;
let total_staked: u64 = validators
.iter()
.map(|v| -> u64 { v.amount_staked.into() })
.sum();
let total_staked = Amount::from(total_staked + 1);
let yearly_inflation = Decimal::from(64_682_541_340_000);
let apr = (yearly_inflation / Decimal::from(4) / Decimal::from(total_staked))
.result()
.map_err(|e| BadRequest(format!("{:?}", e)))?;
Ok(json!({ "height": "0", "result": apr.to_string() }))
}
#[get("/bank/total/<denom>")]
fn bank_total(denom: &str) -> Value {
json!({ "height": "0", "result": "0" })
}
#[get("/cosmos/staking/v1beta1/pool")]
async fn staking_pool() -> Value {
let validators = app_client()
.query(|app| app.staking.all_validators())
.await
.unwrap();
let total_bonded: u64 = validators
.iter()
.filter(|v| v.in_active_set)
.map(|v| -> u64 { v.amount_staked.into() })
.sum();
let total_not_bonded: u64 = validators
.iter()
.filter(|v| !v.in_active_set)
.map(|v| -> u64 { v.amount_staked.into() })
.sum();
json!({
"pool": {
"bonded_tokens": total_bonded.to_string(),
"not_bonded_tokens": total_not_bonded.to_string()
}
})
}
#[get("/cosmos/bank/v1beta1/supply/unom")]
async fn bank_supply_unom() -> Value {
let supply = app_client().query(|app| app.total_supply()).await.unwrap();
json!({
"amount": {
"denom": "unom",
"amount": supply.to_string(),
}
})
}
#[get("/cosmos/bank/v1beta1/supply")]
async fn bank_supply() -> Value {
let supply = app_client().query(|app| app.total_supply()).await.unwrap();
json!({
"supply": [
{
"denom": "unom",
"amount": supply.to_string()
}
],
"pagination": {
"next_key": null,
"total": "1",
}
})
}
#[get("/staking/pool")]
fn staking_pool_2() -> Value {
json!({ "height": "0", "result": {
"loose_tokens": "0",
"bonded_tokens": "0",
"inflation_last_time": "0",
"inflation": "1",
"date_last_commission_reset": "0",
"prev_bonded_shares": "0"
} })
}
#[get("/ibc/apps/transfer/v1/params")]
fn ibc_apps_transfer_params() -> Value {
json!({
"params": {
"send_enabled": false,
"receive_enabled": false
}
})
}
#[get("/ibc/applications/transfer/v1/params")]
fn ibc_applications_transfer_params() -> Value {
json!({
"params": {
"send_enabled": false,
"receive_enabled": false
}
})
}
#[get("/cosmos/staking/v1beta1/params")]
async fn staking_params() -> Value {
let (unbonding_seconds, max_validators) = app_client()
.query(|app| Ok((app.staking.unbonding_seconds, app.staking.max_validators)))
.await
.unwrap();
json!({
"params": {
"unbonding_time": unbonding_seconds.to_string() + "s",
"max_validators": max_validators,
"max_entries": 7,
"historical_entries": 10000,
"bond_denom": "unom"
}
})
}
#[get("/cosmos/slashing/v1beta1/params")]
async fn slashing_params() -> Value {
let (
max_offline_blocks,
slash_fraction_double_sign,
slash_fraction_downtime,
downtime_jail_seconds,
) = app_client()
.query(|app| {
Ok((
app.staking.max_offline_blocks,
app.staking.slash_fraction_double_sign,
app.staking.slash_fraction_downtime,
app.staking.downtime_jail_seconds,
))
})
.await
.unwrap();
json!({
"params": {
"signed_blocks_window": max_offline_blocks.to_string(),
"min_signed_per_window": "0.0",
"downtime_jail_duration": downtime_jail_seconds.to_string() + "s",
"slash_fraction_double_sign": slash_fraction_double_sign.to_string(),
"slash_fraction_downtime": slash_fraction_downtime.to_string()
}
})
}
async fn get_signing_infos() -> Vec<Value> {
let client = tm::HttpClient::new(app_host()).unwrap();
let all_validators: Vec<ValidatorQueryInfo> = app_client()
.query(|app: InnerApp| app.staking.all_validators())
.await
.unwrap();
let all_keys: Vec<_> = app_client()
.query(|app: InnerApp| app.staking.consensus_keys())
.await
.unwrap();
let last_signed_blocks = app_client()
.query(|app: InnerApp| app.staking.last_signed_blocks())
.await
.unwrap();
let latest_block_response = client.latest_block().await.unwrap();
let latest_block: u64 = latest_block_response.block.header.height.value();
let mut signing_infos = vec![];
for validator in all_validators {
let cons_key = all_keys
.iter()
.find(|entry| (**entry).0 == validator.address.into())
.map(|entry| (*entry).1)
.unwrap();
let mut hasher = sha2::Sha256::new();
hasher.update(cons_key);
let hash = hasher.finalize().to_vec()[..20].to_vec();
let address = bech32::encode(
"nomicvalcons",
hash.to_vec().to_base32(),
bech32::Variant::Bech32,
)
.unwrap();
let last_signed_block: u64 = last_signed_blocks
.iter()
.find(|entry| (**entry).0 == validator.address.into())
.map(|entry| (*entry).1)
.unwrap()
.unwrap_or(latest_block);
let skipped_blocks: u64 = latest_block - last_signed_block;
signing_infos.push(json!({
"address": address,
"start_height": "0", // TODO: fix,
"index_offset": "0", // TODO: fix,
"jailed_until": Utc.timestamp_opt(validator.jailed_until.unwrap_or(0), 0)
.unwrap()
.format("%Y-%m-%dT%H:%M:%SZ")
.to_string(),
"tombstoned": validator.tombstoned,
"missed_blocks_counter": skipped_blocks.to_string(),
}))
}
signing_infos
}
#[get("/cosmos/slashing/v1beta1/signing_infos")]
async fn signing_infos() -> Value {
let signing_infos: Vec<_> = get_signing_infos().await;
json!({
"info": signing_infos,
"pagination": {
"next_key": null,
"total": signing_infos.len().to_string(),
}
})
}
#[get("/cosmos/slashing/v1beta1/signing_infos/<cons_addr>")]
async fn signing_info(cons_addr: &str) -> Value {
let signing_infos: Vec<_> = get_signing_infos().await;
let signing_info = signing_infos
.iter()
.find(|value| (**value).get("address").unwrap() == cons_addr)
.unwrap();
json!({
"val_signing_info": signing_info
})
}
fn parse_block(res: tendermint_rpc::endpoint::block::Response) -> Value {
let last_commit = res.block.last_commit.unwrap();
let signatures: Vec<_> = last_commit
.signatures
.iter()
.map(|signature| -> Value {
let signature_raw = RawCommitSig::from(signature.clone());
json!({
"validator_address": base64::encode(signature_raw.validator_address),
"block_id_flag": match signature_raw.block_id_flag {
1 => "BLOCK_ID_FLAG_ABSENT",
2 => "BLOCK_ID_FLAG_COMMIT",
3 => "BLOCK_ID_FLAG_NIL",
i32::MIN..=0_i32 | 4_i32..=i32::MAX => "BLOCK_ID_FLAG_UNKNOWN"
},
"timestamp": signature_raw.timestamp,
"signature": base64::encode(signature_raw.signature),
})
})
.collect();
json!({
"block_id": res.block_id,
"block": {
"header": {
"version": {
"block": res.block.header.version.block,
"app": res.block.header.version.block,
},
"chain_id": res.block.header.chain_id,
"height": res.block.header.height,
"time": res.block.header.time,
"last_block_id": res.block.header.last_block_id,
"last_commit_hash": res.block.header.last_commit_hash.map(|hash| base64::encode(hash.as_bytes())),
"data_hash": res.block.header.data_hash.map(|hash| base64::encode(hash.as_bytes())),
"validators_hash": base64::encode(res.block.header.validators_hash.as_bytes()),
"next_validators_hash": base64::encode(res.block.header.next_validators_hash.as_bytes()),
"consensus_hash": base64::encode(res.block.header.consensus_hash.as_bytes()),
"app_hash": base64::encode(res.block.header.app_hash.value()),
"last_results_hash": res.block.header.last_results_hash.map(|hash| base64::encode(hash.as_bytes())),
"evidence_hash": res.block.header.evidence_hash.map(|hash| base64::encode(hash.as_bytes())),
"proposer_address": base64::encode(res.block.header.proposer_address),
},
"data": res.block.data,
"evidence": res.block.evidence,
"last_commit": {
"block_id": last_commit.block_id,
"signatures": signatures
}
}
})
}
#[get("/cosmos/base/tendermint/v1beta1/blocks/latest")]
async fn latest_block() -> Value {
let client = tm::HttpClient::new(app_host()).unwrap();
let res = client.latest_block().await.unwrap();
parse_block(res)
}
#[get("/cosmos/base/tendermint/v1beta1/blocks/<height>")]
async fn block(height: u32) -> Value {
let client = tm::HttpClient::new(app_host()).unwrap();
let res = client
.block(tendermint::block::Height::from(height))
.await
.unwrap();
parse_block(res)
}
fn parse_validator_set(res: tendermint_rpc::endpoint::validators::Response) -> Value {
let validators: Vec<_> = res
.validators
.iter()
.map(|validator| -> Value {
json!({
"address": validator.address,
"voting_power": i64::from(validator.power).to_string(),
"proposer_priority": i64::from(validator.proposer_priority).to_string(),
"pub_key": {
"@type": "/cosmos.crypto.ed25519.PubKey",
"key": base64::encode(validator.pub_key.ed25519().unwrap().to_bytes()),
}
})
})
.collect();
json!({
"block_height": res.block_height,
"validators": validators,
"pagination": {
"next_key": null,
"total": res.validators.len(),
}
})
}
#[get("/cosmos/base/tendermint/v1beta1/validatorsets/latest")]
async fn latest_validator_set() -> Value {
let client = tm::HttpClient::new(app_host()).unwrap();
let block = client.latest_block().await.unwrap();
let res = client
.validators(block.block.header.height, tendermint_rpc::Paging::All)
.await
.unwrap();
parse_validator_set(res)
}
#[get("/cosmos/base/tendermint/v1beta1/validatorsets/<height>")]
async fn validator_set(height: u32) -> Value {
let client = tm::HttpClient::new(app_host()).unwrap();
let res = client
.validators(height, tendermint_rpc::Paging::All)
.await
.unwrap();
parse_validator_set(res)
}
#[get("/cosmos/distribution/v1beta1/community_pool")]
async fn community_pool() -> Value {
let community_pool = app_client()
.query(|app| Ok(app.community_pool.amount))
.await
.unwrap();
json!({
"pool": [
{
"denom": "unom",
"amount": community_pool.to_string()
}
]
})
}
#[get("/cosmos/gov/v1beta1/proposals")]
fn proposals() -> Value {
json!({
"proposals": [],
"pagination": {
"next_key": null,
"total": 0
}
})
}
#[get("/ibc/core/connection/v1/connections/<connection>/client_state")]
#[allow(deprecated)]
async fn ibc_connection_client_state(connection: &str) -> Value {
let connection = app_client()
.query(|app| {
app.ibc.ctx.query_connection(EofTerminatedString(
IbcConnectionId::from_str(connection).unwrap(),
))
})
.await
.unwrap()
.unwrap();
let states: Vec<IdentifiedClientState> = app_client()
.query(|app| app.ibc.ctx.query_client_states())
.await
.unwrap();
let state: &IdentifiedClientState = states
.iter()
.find(|state| state.client_id == connection.client_id().to_string())
.unwrap();
let state_as_any: Any = state.client_state.clone().unwrap();
let client_state_tmp: ClientState = ClientState::try_from(state_as_any).unwrap().to_owned();
let client_state = client_state_tmp.clone();
let raw_client_state: RawTmClientState = RawTmClientState::from(client_state_tmp);
let proof_specs: Vec<_> = raw_client_state
.proof_specs
.iter()
.map(|spec| {
json!({
"inner_spec": spec.inner_spec.clone().map(|inner_spec| json!({
"child_order": inner_spec.child_order,
"child_size": inner_spec.child_size,
"min_prefix_length": inner_spec.child_size,
"max_prefix_length": inner_spec.max_prefix_length,
"empty_child": inner_spec.empty_child,
"hash": inner_spec.hash
})),
"leaf_spec": spec.leaf_spec,
})
})
.collect();
json!({
"identified_client_state": {
"client_id": state.client_id,
"client_state": {
"@type": "/ibc.lightclients.tendermint.v1.ClientState",
"chain_id": raw_client_state.chain_id,
"trust_level": client_state.trust_level,
"trusting_period": raw_client_state.trusting_period.map(|v| format!("{}s", v.seconds)),
"unbonding_period": format!("{}s", client_state.unbonding_period.as_secs()),
"max_clock_drift": raw_client_state.max_clock_drift.map(|v| format!("{}s", v.seconds)),
"frozen_height": raw_client_state.frozen_height.map(|h| json!({
"revision_height": h.revision_height.to_string(),
"revision_number": h.revision_number.to_string(),
})),
"latest_height": raw_client_state.latest_height.map(|h| json!({
"revision_height": h.revision_height.to_string(),
"revision_number": h.revision_number.to_string(),
})),
"proof_specs": proof_specs,
"upgrade_path": client_state.upgrade_path,
"allow_update_after_expiry": raw_client_state.allow_update_after_expiry,
"allow_update_after_misbehaviour": raw_client_state.allow_update_after_misbehaviour,
}
},
"proof": null,
"proof_height": {
"revision_number": "0",
"revision_height": "0"
}
})
}
#[get("/ibc/core/channel/v1/connections/<connection>/channels")]
async fn ibc_connection_channels(connection: &str) -> Value {
let channels = app_client()
.query(|app| {
app.ibc.ctx.query_connection_channels(EofTerminatedString(
IbcConnectionId::from_str(connection).unwrap(),
))
})
.await
.unwrap();
let json_channels: Vec<_> = channels
.iter()
.map(|channel| {
json!({
"state": match channel.state {
0 => "STATE_UNINITIALIZED_UNSPECIFIED",
1 => "STATE_INIT",
2 => "STATE_TRYOPEN",
3 => "STATE_OPEN",
i32::MIN..=-1_i32 | 4_i32..=i32::MAX => "STATE_UNINITIALIZED_UNSPECIFIED"
},
"ordering": match channel.ordering {
0 => "ORDER_NONE_UNSPECIFIED",
1 => "ORDER_UNORDERED",
2 => "ORDER_ORDERED",
i32::MIN..=-1_i32 | 3_i32..=i32::MAX => "ORDER_NONE_UNSPECIFIED"
},
"counterparty": channel.counterparty,
"connection_hops": channel.connection_hops,
"version": channel.version,
"port_id": channel.port_id,
"channel_id": channel.channel_id,
})
})
.collect();
json!({
"channels": json_channels,
"proof_height": {
"revision_number": "0",
"revision_height": "0"
},
})
}
#[get("/ibc/core/connection/v1/connections/<connection>")]
async fn ibc_connection(connection: &str) -> Value {
let connection = app_client()
.query(|app| {
app.ibc.ctx.query_connection(EofTerminatedString(
IbcConnectionId::from_str(connection).unwrap(),
))
})
.await
.unwrap()
.unwrap();
let raw_connection = RawConnectionEnd::from(connection);
json!({
"connection": {
"client_id": raw_connection.client_id,
"versions": raw_connection.versions,
"state": match raw_connection.state {
0 => "STATE_UNINITIALIZED_UNSPECIFIED",
1 => "STATE_INIT",
2 => "STATE_TRYOPEN",
3 => "STATE_OPEN",
i32::MIN..=-1_i32 | 4_i32..=i32::MAX => "STATE_UNINITIALIZED_UNSPECIFIED"
},
"counterparty": raw_connection.counterparty,
"delay_period": raw_connection.delay_period,
},
"proof_height": {
"revision_number": "0",
"revision_height": "0"
},
})
}
#[get("/ibc/core/connection/v1/connections")]
async fn ibc_connections() -> Value {
let connections = app_client()
.query(|app| app.ibc.ctx.query_all_connections())
.await
.unwrap();
json!({
"connections": connections,
"pagination": {
"next_key": null,
"total": connections.len().to_string()
},
"proof_height": {
"revision_number": "0",
"revision_height": "0"
},
})
}
use rocket::fairing::{Fairing, Info, Kind};
use rocket::http::Header;
use rocket::{Request, Response};
pub struct CORS;
#[rocket::async_trait]
impl Fairing for CORS {
fn info(&self) -> Info {
Info {
name: "Add CORS headers to responses",
kind: Kind::Response,
}
}
async fn on_response<'r>(&self, _request: &'r Request<'_>, response: &mut Response<'r>) {
response.set_header(Header::new("Access-Control-Allow-Origin", "*"));
response.set_header(Header::new(
"Access-Control-Allow-Methods",
"POST, GET, PATCH, OPTIONS",
));
response.set_header(Header::new("Access-Control-Allow-Headers", "*"));
response.set_header(Header::new("Access-Control-Allow-Credentials", "true"));
}
}
#[launch]
fn rocket() -> _ {
rocket::build().attach(CORS).mount(
"/",
routes![
bank_balances,
bank_balances_2,
auth_accounts,
auth_accounts2,
txs,
txs2,
query,
staking_delegators_delegations,
staking_delegators_delegations_2,
staking_delegators_unbonding_delegations,
staking_delegators_unbonding_delegations_2,
staking_validators_delegations,
staking_validators_unbonding_delegations,
staking_validator_single_delegation,
distribution_delegators_rewards,
distribution_delegators_rewards_for_validator,
distribution_validator_commission,
minting_inflation,
minting_inflation_2,
staking_pool,
staking_pool_2,
bank_total,
ibc_apps_transfer_params,
ibc_applications_transfer_params,
bank_supply_unom,
bank_supply,
validators,
validator,
staking_params,
slashing_params,
signing_infos,
signing_info,
latest_block,
block,
latest_validator_set,
validator_set,
community_pool,
proposals,
ibc_connection,
ibc_connections,
ibc_connection_client_state,
ibc_connection_channels,
],
)
}
================================================
FILE: rust-toolchain
================================================
[toolchain]
channel = "nightly-2024-07-21"
================================================
FILE: rustfmt.toml
================================================
comment_width = 80
wrap_comments = true
================================================
FILE: src/airdrop.rs
================================================
//! State and logic for airdrop accounts which can be claimed by users.
use orga::coins::Address;
#[cfg(feature = "full")]
use orga::coins::{Amount, Decimal};
use orga::collections::{ChildMut, Map};
use orga::context::GetContext;
use orga::migrate::MigrateFrom;
use orga::orga;
use orga::plugins::{Paid, Signer};
use orga::{Error, Result};
#[cfg(feature = "full")]
use split_iter::Splittable;
use super::app::Nom;
/// The maximum units of stake counted when calculating airdrop II.
#[cfg(feature = "full")]
const MAX_STAKED: u64 = 1_000_000_000;
/// The total amount of token units claimable by users in airdrop II.
#[cfg(feature = "full")]
const AIRDROP_II_TOTAL: u64 = 3_500_000_000_000;
/// Airdrop account state.
#[orga(version = 1)]
pub struct Airdrop {
accounts: Map<Address, Account>,
}
impl MigrateFrom<AirdropV0> for AirdropV1 {
fn migrate_from(_value: AirdropV0) -> Result<Self> {
unreachable!()
}
}
type Recipients = Vec<(Address, Vec<(u64, u64)>, u64)>;
#[orga]
impl Airdrop {
/// Gets the account at the given address.
#[query]
pub fn get(&self, address: Address) -> Result<Option<Account>> {
Ok(self.accounts.get(address)?.map(|a| a.clone()))
}
/// Gets a mutable reference to the account at the given address.
pub fn get_mut(&mut self, address: Address) -> Result<Option<ChildMut<Address, Account>>> {
self.accounts.get_mut(address)
}
/// Gets a mutable reference to the account for the signer of the
/// transaction.
pub fn signer_acct_mut(&mut self) -> Result<ChildMut<Address, Account>> {
let signer = self
.context::<Signer>()
.ok_or_else(|| Error::Signer("No Signer context available".into()))?
.signer
.ok_or_else(|| Error::Coins("Unauthorized account action".into()))?;
self.accounts
.get_mut(signer)?
.ok_or_else(|| Error::App("No airdrop account for signer".into()))
}
/// Pays into the Paid context as funding.
fn pay_as_funding(&mut self, amount: u64) -> Result<()> {
let paid = self
.context::<Paid>()
.ok_or_else(|| Error::Coins("No Paid context found".into()))?;
paid.give::<Nom, _>(amount)
}
/// Claims the signer's airdrop I balance to the funding context.
#[call]
pub fn claim_airdrop1(&mut self) -> Result<()> {
let mut acct = self.signer_acct_mut()?;
let amount = acct.airdrop1.claim()?;
self.pay_as_funding(amount)?;
Ok(())
}
/// Claims the signer's airdrop II balance to the funding context.
#[call]
pub fn claim_airdrop2(&mut self) -> Result<()> {
let mut acct = self.signer_acct_mut()?;
let amount = acct.airdrop2.claim()?;
self.pay_as_funding(amount)?;
Ok(())
}
/// Joins the signer's account to a destination account (e.g. when the user
/// received the airdrop to multiple addresses but would like to consolidate
/// into one account).
pub fn join_accounts(&mut self, dest_addr: Address) -> Result<()> {
let mut acct = self.signer_acct_mut()?;
if acct.joined {
return Err(Error::App("Account already joined".to_string()));
}
if acct.is_empty() {
return Err(Error::App("Account has no airdrop balance".to_string()));
}
let src = acct.clone();
*acct = Account::default();
let mut dest = self.accounts.entry(dest_addr)?.or_default()?;
let add_part = |dest: &mut Part, src: Part| {
if dest.claimable > 0 || dest.claimed > 0 {
dest.claimable += src.locked;
} else {
dest.locked += src.locked;
}
dest.claimable += src.claimable;
dest.claimed += src.claimed;
};
add_part(&mut dest.airdrop1, src.airdrop1);
add_part(&mut dest.airdrop2, src.airdrop2);
dest.joined = true;
Ok(())
}
/// Initializes unclaimed airdrop accounts from a CSV file.
#[cfg(feature = "full")]
pub fn init_from_airdrop2_csv(&mut self, data: &[u8]) -> Result<()> {
log::info!("Initializing balances from airdrop 2 snapshot...");
let recipients = Self::get_recipients_from_csv(data);
let len = recipients[0].1.len();
let mut totals = vec![0u64; len];
for (_, networks, _) in recipients.iter() {
for (i, (staked, count)) in networks.iter().enumerate() {
let score = Self::score(*staked, *count);
totals[i] += score;
}
}
let precision = 1_000_000u128;
let unom_per_network = AIRDROP_II_TOTAL / (len as u64);
let unom_per_score: Vec<_> = totals
.iter()
.map(|n| unom_per_network as u128 * precision / *n as u128)
.collect();
let mut airdrop_total = 0;
let mut accounts = 0;
#[cfg(not(feature = "testnet"))]
let mut testnet_locked = 0;
#[cfg(not(feature = "testnet"))]
let mut testnet_claimable = 0;
#[allow(unused_variables)]
for (address, networks, testnet_completions) in recipients.iter() {
let unom: u64 = networks
.iter()
.zip(unom_per_score.iter())
.map(|((staked, count), unom_per_score)| {
let score = Self::score(*staked, *count) as u128;
(score * unom_per_score / precision) as u64
})
.sum();
let res = self.airdrop_to(*address, unom, *testnet_completions)?;
airdrop_total += unom;
accounts += 1;
#[cfg(not(feature = "testnet"))]
{
testnet_locked += res.0;
testnet_claimable += res.1;
}
}
log::info!(
"Total amount minted for airdrop 2: {} uNOM across {} accounts",
airdrop_total,
accounts,
);
#[cfg(not(feature = "testnet"))]
log::info!(
"Testnet participation allocation: {} uNOM locked, {} uNOM claimable",
testnet_locked,
testnet_claimable,
);
Ok(())
}
/// Initializes and pays into a new airdrop account.
#[allow(unused_variables)]
#[cfg(feature = "full")]
fn airdrop_to(
&mut self,
addr: Address,
unom: u64,
testnet_completions: u64,
) -> Result<(u64, u64)> {
let mut acct = self.accounts.entry(addr)?.or_insert_default()?;
acct.airdrop2.claimable = unom;
Ok((0, 0))
}
/// Returns the score for a given staked amount and delegation count. The
/// score is further used in the calculation of the amount of tokens to
/// receive.
#[cfg(feature = "full")]
fn score(staked: u64, _count: u64) -> u64 {
staked.min(MAX_STAKED)
}
/// Parses the CSV data into a list of recipients.
#[cfg(feature = "full")]
fn get_recipients_from_csv(data: &[u8]) -> Recipients {
let mut reader = csv::Reader::from_reader(data);
reader
.records()
.filter_map(|row| {
let row = row.unwrap();
if row[0].len() != 44 {
return None;
}
let addr: Address = row[0].parse().unwrap();
let (claims, values) = row
.into_iter()
.skip(1)
.split(|item| item.parse::<u64>().is_ok());
let values: Vec<_> = values.map(|s| -> u64 { s.parse().unwrap() }).collect();
let claims = claims
.map(|s| -> bool { s.parse().unwrap() })
.filter(|b| *b)
.count() as u64;
let pairs = values.chunks_exact(2).map(|arr| (arr[0], arr[1])).collect();
Some((addr, pairs, claims))
})
.collect()
}
/// Initializes the airdrop I balances for a given address.
#[cfg(feature = "full")]
fn init_airdrop1_amount(
&mut self,
addr: Address,
liquid: Amount,
staked: Amount,
) -> Result<Amount> {
let liquid_capped = Amount::min(liquid, 1_000_000_000.into());
let staked_capped = Amount::min(staked, 1_000_000_000.into());
let units = (liquid_capped + staked_capped * Amount::from(4))?;
let units_per_nom = Decimal::from(20_299325) / Decimal::from(1_000_000);
let nom_amount = (Decimal::from(units) / units_per_nom)?.amount()?;
let mut acct = self.accounts.entry(addr)?.or_insert_default()?;
acct.airdrop1.claimable = nom_amount.into();
Ok(nom_amount)
}
/// Initializes the airdrop I balances for all the accounts in the given
/// CSV.
#[cfg(feature = "full")]
pub fn init_from_airdrop1_csv(&mut self, data: &[u8]) -> Result<()> {
let mut rdr = csv::Reader::from_reader(data);
let snapshot = rdr.records();
println!("Initializing balances from airdrop 1 snapshot...");
let mut minted = Amount::from(0);
let mut accounts = 0;
for row in snapshot {
let row = row.map_err(|e| Error::App(e.to_string()))?;
let (_, address_b32, _) = bech32::decode(&row[0]).unwrap();
let address_vec: Vec<u8> = bech32::FromBase32::from_base32(&address_b32).unwrap();
let address_buf: [u8; 20] = address_vec.try_into().unwrap();
let liquid: u64 = row[1].parse().unwrap();
let staked: u64 = row[2].parse().unwrap();
let minted_for_account =
self.init_airdrop1_amount(address_buf.into(), liquid.into(), staked.into())?;
minted = (minted + minted_for_account)?;
accounts += 1;
}
println!(
"Total amount minted for airdrop 1: {} uNOM across {} accounts",
minted, accounts
);
Ok(())
}
}
/// An airdrop account.
#[orga(version = 1..=2)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Account {
/// The part of the airdrop received in airdrop I.
pub airdrop1: Part,
/// The part of the airdrop received in airdrop II.
pub airdrop2: Part,
/// Whether or not the account has been joined into from another account.
/// This is tracked to prevent a DoS vector where an attacker could spam
/// transactions by repeatedly joining into different accounts without
/// paying a fee.
pub joined: bool,
}
impl Account {
/// Returns `true` if the account is empty.
pub fn is_empty(&self) -> bool {
self == &Self::default()
}
}
impl MigrateFrom<AccountV1> for AccountV2 {
fn migrate_from(_value: AccountV1) -> Result<Self> {
unreachable!()
}
}
/// A part of an airdrop account, e.g. the balances from either airdrop I or
/// airdrop II.
#[orga]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Part {
/// A balance for the user which is locked and cannot be claimed. This will
/// typically be unlocked after some external event occurs.
pub locked: u64,
/// A balance for the user which can be claimed by the user.
pub claimable: u64,
/// The amount of balance which has already been claimed. This is not a
/// balance, since upon claiming the balance was moved elsewhere, e.g. the
/// user's normal balance.
pub claimed: u64,
}
impl Part {
/// Unlocks the locked balance, making it claimable.
pub fn unlock(&mut self) {
self.claimable += self.locked;
self.locked = 0;
}
/// Claims the claimable balance, marking the amount as claimed and
/// returning the amount to be paid to the account's normal balance.
pub fn claim(&mut self) -> Result<u64> {
let amount = self.claimable;
if amount == 0 {
return Err(Error::Coins("No balance to claim".to_string()));
}
self.claimed += amount;
self.claimable = 0;
Ok(amount)
}
/// Returns `true` if the part has no locked or claimable balances and has
/// not been claimed.
pub fn is_empty(&self) -> bool {
self == &Self::default()
}
/// Returns the total balance across all states.
pub fn total(&self) -> u64 {
self.locked + self.claimable + self.claimed
}
}
#[cfg(feature = "full")]
#[cfg(test)]
mod test {
use super::*;
#[cfg(not(feature = "testnet"))]
use orga::coins::Amount;
use std::str::FromStr;
fn assert_approx_eq(a: u64, b: u64) {
assert!((a as i64 - b as i64).abs() <= 2, "{} !~= {}", a, b);
}
#[cfg(not(feature = "testnet"))]
fn amount_airdropped(acct: &Account) -> u64 {
acct.airdrop2.claimable
}
#[cfg(feature = "testnet")]
#[test]
fn airdrop_allocation_no_testnet() {
let mut airdrop = Airdrop::default();
let csv = "address,evmos_9000-1_staked,evmos_9000-1_count,kaiyo-1_staked,kaiyo-1_count,cosmoshub-4_staked,cosmoshub-4_count,juno-1_staked,juno-1_count,osmosis-1_staked,osmosis-1_count,btc_deposit_claimed,btc_withdraw_claimed,ibc_transfer_claimed
nomic100000aeu2lh0jrrnmn2npc88typ25u7t3aa64x,1,1,1,1,1,1,1,1,1,1,true,true,true".as_bytes();
airdrop.init_from_airdrop2_csv(csv).unwrap();
let account = airdrop
.get_mut(Address::from_str("nomic100000aeu2lh0jrrnmn2npc88typ25u7t3aa64x").unwrap())
.unwrap()
.unwrap();
let airdrop2_total = account.airdrop2.total();
assert_approx_eq(airdrop2_total, AIRDROP_II_TOTAL);
}
#[cfg(not(feature = "testnet"))]
#[test]
fn airdrop_allocation() {
let mut airdrop = Airdrop::default();
let csv = "address,evmos_9000-1_staked,evmos_9000-1_count,kaiyo-1_staked,kaiyo-1_count,cosmoshub-4_staked,cosmoshub-4_count,juno-1_staked,juno-1_count,osmosis-1_staked,osmosis-1_count,btc_deposit_claimed,btc_withdraw_claimed,ibc_transfer_claimed
nomic100000aeu2lh0jrrnmn2npc88typ25u7t3aa64x,1,1,1,1,1,1,1,1,1,1,true,true,true".as_bytes();
airdrop.init_from_airdrop2_csv(csv).unwrap();
let account = airdrop
.get_mut(Address::from_str("nomic100000aeu2lh0jrrnmn2npc88typ25u7t3aa64x").unwrap())
.unwrap()
.unwrap();
let airdrop2_total = amount_airdropped(&*account);
assert_approx_eq(airdrop2_total, AIRDROP_II_TOTAL);
}
#[cfg(not(feature = "testnet"))]
#[test]
fn airdrop_allocation_multiple() {
let mut airdrop = Airdrop::default();
let csv = "address,evmos_9000-1_staked,evmos_9000-1_count,kaiyo-1_staked,kaiyo-1_count,cosmoshub-4_staked,cosmoshub-4_count,juno-1_staked,juno-1_count,osmosis-1_staked,osmosis-1_count,btc_deposit_claimed,btc_withdraw_claimed,ibc_transfer_claimed
nomic100000aeu2lh0jrrnmn2npc88typ25u7t3aa64x,1,1,1,1,1,1,1,1,1,1,true,true,true
nomic10005vr6w230rer02rgwsvmhh0vdpk9hvxkv8zs,1,1,1,1,1,1,1,1,1,1,true,true,true".as_bytes();
airdrop.init_from_airdrop2_csv(csv).unwrap();
let account = airdrop
.get_mut(Address::from_str("nomic100000aeu2lh0jrrnmn2npc88typ25u7t3aa64x").unwrap())
.unwrap()
.unwrap();
let airdrop2_total = amount_airdropped(&*account);
let expected: u64 = (Amount::from(AIRDROP_II_TOTAL) / Amount::from(2))
.result()
.unwrap()
.amount()
.unwrap()
.into();
assert_approx_eq(airdrop2_total, expected);
let account = airdrop
.get_mut(Address::from_str("nomic10005vr6w230rer02rgwsvmhh0vdpk9hvxkv8zs").unwrap())
.unwrap()
.unwrap();
let airdrop2_total = amount_airdropped(&*account);
assert_approx_eq(airdrop2_total, expected);
}
}
================================================
FILE: src/app/migrations.rs
================================================
#[cfg(feature = "babylon")]
use crate::babylon::Babylon;
#[cfg(feature = "ethereum")]
use crate::ethereum::{bytes32, Connection, Ethereum, Network};
use crate::{
bitcoin::{
adapter::Adapter,
header_queue::{WorkHeader, WrappedHeader},
},
incentives::Incentives,
};
use super::{InnerAppV5, InnerAppV6, InnerAppV7};
use bitcoin::{
util::{uint::Uint256, BitArray},
BlockHeader,
};
use orga::{
coins::Take,
collections::Map,
ibc::Ibc,
migrate::{Migrate, MigrateFrom},
state::State,
store::Store,
upgrade::Upgrade,
Result,
};
impl MigrateFrom<InnerAppV5> for InnerAppV6 {
#[allow(unused_mut)]
fn migrate_from(mut other: InnerAppV5) -> Result<Self> {
#[cfg(not(feature = "testnet"))]
{
other.bitcoin.checkpoints.config.max_age = 60 * 60 * 24 * 30 * 12;
other.bitcoin.headers.config.max_length = 52_560;
// remove headers and revert to checkpoint so we can regain history which was
// pruned
other
.bitcoin
.headers
.deque
.retain_unordered(|_| Ok(false))?;
let checkpoint_json = include_str!("../bitcoin/checkpoint.json");
let header: (u32, BlockHeader) = serde_json::from_str(checkpoint_json)?;
let wrapped_header = WrappedHeader::new(Adapter::new(header.1), header.0);
let work_header = WorkHeader::new(wrapped_header.clone(), wrapped_header.work());
other.bitcoin.headers.current_work = Adapter::new(work_header.work());
other.bitcoin.headers.deque.push_back(work_header)?;
// backfill checkpoint history
use bitcoin::hashes::hex::FromHex;
let scripts = include_str!("../../stakenet_reserve_scripts.csv")
.lines()
.map(|line| {
let mut parts = line.split(',');
parts.next().unwrap();
parts.next().unwrap()
})
.map(|script_hex| bitcoin::Script::from_hex(script_hex).unwrap());
other.bitcoin.checkpoints.backfill(
5276,
scripts,
other.bitcoin.checkpoints.config.sigset_threshold,
)?;
}
Ok(Self {
accounts: other.accounts,
staking: other.staking,
airdrop: other.airdrop,
community_pool: other.community_pool,
incentive_pool: other.incentive_pool,
staking_rewards: other.staking_rewards,
dev_rewards: other.dev_rewards,
community_pool_rewards: other.community_pool_rewards,
incentive_pool_rewards: other.incentive_pool_rewards,
bitcoin: other.bitcoin,
reward_timer: other.reward_timer,
upgrade: other.upgrade,
incentives: other.incentives,
ibc: other.ibc,
cosmos: other.cosmos,
#[cfg(feature = "ethereum")]
ethereum: Default::default(), // TODO
})
}
}
impl MigrateFrom<InnerAppV6> for InnerAppV7 {
fn migrate_from(other: InnerAppV6) -> Result<Self> {
// #[cfg(all(feature = "testnet", feature = "ethereum"))]
// let mut ethereum = Ethereum::default();
todo!();
}
}
================================================
FILE: src/app.rs
================================================
//! The top-level application state and logic of the Nomic protocol. The main
//! state type is the [InnerApp] struct.
#![allow(clippy::too_many_arguments)]
// TODO: remove after switching from "testnet" feature flag to orga channels
#![allow(unused_variables)]
#![allow(unused_imports)]
use crate::airdrop::Airdrop;
#[cfg(feature = "babylon")]
use crate::babylon::{self, Babylon, Params};
use crate::bitcoin::adapter::Adapter;
use crate::bitcoin::threshold_sig::Signature;
use crate::bitcoin::{exempt_from_fee, Bitcoin, Nbtc};
use crate::bitcoin::{matches_bitcoin_network, NETWORK};
use crate::cosmos::{Chain, Cosmos, Proof};
#[cfg(feature = "ethereum")]
use crate::ethereum::Ethereum;
#[cfg(feature = "frost")]
use crate::frost::{Config as FrostConfig, Frost, FrostGroup};
#[cfg(feature = "ethereum")]
use crate::ethereum::Connection;
use crate::incentives::Incentives;
use bitcoin::util::merkleblock::PartialMerkleTree;
use bitcoin::{PublicKey, Script, Transaction, TxOut};
use orga::coins::{
Accounts, Address, Amount, Coin, Faucet, FaucetOptions, Give, Staking, Symbol, Take,
};
use orga::context::{Context, GetContext};
use orga::cosmrs::bank::MsgSend;
use orga::describe::{Describe, Descriptor};
use orga::encoding::{Decode, Encode, LengthString, LengthVec};
use orga::ibc::ibc_rs::apps::transfer::types::Memo;
use orga::ibc::ClientIdKey as ClientId;
use sha2::{Digest, Sha256};
use std::io::Read;
use std::str::FromStr;
use std::time::Duration;
use orga::ibc::ibc_rs::apps::transfer::context::TokenTransferExecutionContext;
use orga::ibc::ibc_rs::apps::transfer::types::msgs::transfer::MsgTransfer;
use orga::ibc::ibc_rs::apps::transfer::types::packet::PacketData;
use orga::ibc::ibc_rs::core::channel::types::timeout::{TimeoutHeight, TimeoutTimestamp};
use orga::ibc::ibc_rs::core::host::types::identifiers::{ChannelId, PortId};
use orga::ibc::ibc_rs::core::primitives::Timestamp;
use orga::ibc::{Ibc, IbcTx};
use orga::ibc::ibc_rs::core::primitives::Signer as IbcSigner;
use orga::coins::Declaration;
use orga::encoding::Adapter as EdAdapter;
use orga::macros::build_call;
use orga::migrate::Migrate;
use orga::orga;
use orga::plugins::sdk_compat::{sdk, sdk::Tx as SdkTx, ConvertSdkTx};
use orga::plugins::{disable_fee, DefaultPlugins, Events, Paid, PaidCall, Signer, Time, MIN_FEE};
use orga::prelude::*;
use orga::upgrade::Version;
use orga::upgrade::{Upgrade, UpgradeV0};
use orga::Error;
use serde::{Deserialize, Serialize};
use serde_hex::{SerHex, Strict, StrictPfx};
use std::convert::TryInto;
use std::fmt::Debug;
mod migrations;
/// The top-level application state type, wrapped with the Orga default plugins.
pub type App = DefaultPlugins<Nom, InnerApp>;
/// The symbol for the NOM token.
#[derive(State, Debug, Clone, Encode, Decode, Default, Migrate, Serialize)]
pub struct Nom(());
impl Symbol for Nom {
const INDEX: u8 = 69;
const NAME: &'static str = "unom";
}
/// The recipient address for the NOM developer rewards faucet on Nomic
/// Stakenet.
#[cfg(feature = "full")]
const DEV_ADDRESS: &str = "nomic14z79y3yrghqx493mwgcj0qd2udy6lm26lmduah";
/// The recipient address for the NOM strategic reserve tokens on Nomic
/// Stakenet.
#[cfg(feature = "full")]
const STRATEGIC_RESERVE_ADDRESS: &str = "nomic1d5n325zrf4elfu0heqd59gna5j6xyunhev23cj";
/// An address to receive a small portion of the strategic reserve tokens in
/// order to send a small portion of tokens to validators for declaration fees
/// on Nomic Stakenet.
#[cfg(feature = "full")]
const VALIDATOR_BOOTSTRAP_ADDRESS: &str = "nomic1fd9mxxt84lw3jdcsmjh6jy8m6luafhqd8dcqeq";
/// The fixed amount of nBTC fee required to relay IBC messages, in
/// micro-satoshis.
const IBC_FEE_USATS: u64 = 1_000_000;
/// The fixed amount of nBTC fee required to make any application call, in
/// micro-satoshis.
const CALL_FEE_USATS: u64 = 100_000_000;
/// The fixed amount of nBTC fee required to create a new Ethereum connection,
/// in micro-satoshis.
#[cfg(feature = "ethereum")]
const ETH_CREATE_CONNECTION_FEE_USATS: u64 = 10_000_000_000;
pub const OSMOSIS_CHANNEL_ID: &str = "channel-1";
#[cfg(feature = "frost")]
const FROST_GROUP_INTERVAL: i64 = 10 * 60;
#[cfg(feature = "frost")]
const FROST_TOP_N: u16 = 5;
#[cfg(feature = "frost")]
const FROST_THRESHOLD: u16 = 3;
/// The top-level application state type and logic. This contains the major
/// state types for the various subsystems of the Nomic protocol.
#[orga(version = 5..=7)]
pub struct InnerApp {
/// Account state for the NOM token.
#[call]
pub accounts: Accounts<Nom>,
/// Staking and validator state, including the validator set and staking
/// rewards. This ultimately sets the voting power of Tendermint consensus
/// based on the amount staked to each validator.
#[call]
pub staking: Staking<Nom>,
/// Airdrop state, which can be claimed by eligible accounts.
#[call]
pub airdrop: Airdrop,
/// A balance of NOM tokens that are reserved for the protocol community
/// pool.
pub community_pool: Coin<Nom>,
/// A balance of NOM tokens that are reserved for the protocol incentive
/// pool.
incentive_pool: Coin<Nom>,
/// A stream of tokens that pays out over time to NOM stakers, based on a
/// defined inflation schedule.
staking_rewards: Faucet<Nom>,
/// A stream of tokens that pays out over time to the NOM developer wallet,
/// based on a defined inflation schedule.
dev_rewards: Faucet<Nom>,
/// A stream of tokens that pays out over time to the NOM community pool,
/// based on a defined inflation schedule.
community_pool_rewards: Faucet<Nom>,
/// A stream of tokens that pays out over time to the NOM incentive pool,
/// based on a defined inflation schedule.
incentive_pool_rewards: Faucet<Nom>,
/// The Bitcoin state, including a chain of verified Bitcoin headers and
/// logic for processing Bitcoin transactions.
#[call]
pub bitcoin: Bitcoin,
/// A timer to support paying out accumulated Bitcoin rewards periodically.
pub reward_timer: RewardTimer,
/// The IBC state, including the IBC client, connection, and channel
/// states. This is used to relay messages between Nomic and other IBC
/// enabled blockchains.
#[call]
pub ibc: Ibc,
/// The upgrade state, including the current version of the application and
/// logic for upgrading to a new version of the protocol once sufficient
/// network voting power has signaled readiness.
pub upgrade: Upgrade,
/// Incentive state, allowing eligible users to claim tokens based on
/// participation in the Nomic ecosystem.
#[call]
pub incentives: Incentives,
/// The Cosmos state, allowing for relaying data about remote Cosmos chains
/// which is not available in the IBC module.
pub cosmos: Cosmos,
#[cfg(all(feature = "ethereum", feature = "testnet"))]
#[orga(version(V5, V6))]
#[call]
pub ethereum: Connection,
#[cfg(all(feature = "ethereum", feature = "testnet"))]
#[orga(version(V7))]
#[call]
pub ethereum: Ethereum,
#[cfg(all(feature = "babylon", feature = "testnet"))]
#[orga(version(V7))]
#[call]
pub babylon: Babylon,
#[cfg(all(feature = "frost", feature = "testnet"))]
#[orga(version(V7))]
#[call]
pub frost: Frost,
}
#[orga]
impl InnerApp {
/// The current version of the Nomic protocol. This is incremented when
/// breaking changes are made to either the state encoding or logic of the
/// protocol, and requires a network upgrade to be coordinated via the
/// upgrade module.
pub const CONSENSUS_VERSION: u8 = 14;
#[cfg(feature = "full")]
fn configure_faucets(&mut self) -> Result<()> {
let day = 60 * 60 * 24;
let year = Duration::from_secs(60 * 60 * 24 * 365);
let two_thirds = (Amount::new(2) / Amount::new(3))?;
let genesis_time = self
.context::<Time>()
.ok_or_else(|| Error::App("No Time context available".into()))?
.seconds;
self.staking_rewards.configure(FaucetOptions {
num_periods: 9,
period_length: year,
total_coins: 49_875_000_000_000.into(),
period_decay: two_thirds,
start_seconds: genesis_time + day,
})?;
self.dev_rewards.configure(FaucetOptions {
num_periods: 9,
period_length: year,
total_coins: 49_875_000_000_000.into(),
period_decay: two_thirds,
start_seconds: genesis_time + day,
})?;
self.community_pool_rewards.configure(FaucetOptions {
num_periods: 9,
period_length: year,
total_coins: 9_975_000_000_000.into(),
period_decay: two_thirds,
start_seconds: genesis_time + day,
})?;
self.incentive_pool_rewards.configure(FaucetOptions {
num_periods: 9,
period_length: year,
total_coins: 89_775_000_000_000.into(),
period_decay: two_thirds,
start_seconds: genesis_time + day,
})?;
Ok(())
}
#[call]
pub fn deposit_rewards(&mut self) -> Result<()> {
self.accounts.give_from_funding_all()?;
self.bitcoin.accounts.give_from_funding_all()?;
Ok(())
}
#[call]
pub fn ibc_transfer_nbtc(&mut self, dest: IbcDest, amount: Amount) -> Result<()> {
crate::bitcoin::exempt_from_fee()?;
dest.validate()?;
let signer = self.signer()?;
let mut coins = self.bitcoin.accounts.withdraw(signer, amount)?;
let fee = if dest.is_fee_exempt() {
IBC_FEE_USATS.into()
} else {
ibc_fee(amount)?
};
let fee = coins.take(fee)?;
self.bitcoin.give_rewards(fee)?;
let dest = Dest::Ibc { data: dest };
let sender = Identity::from_signer()?;
self.bitcoin.insert_pending(dest, coins, sender)?;
Ok(())
}
#[call]
pub fn ibc_withdraw_nbtc(&mut self, amount: Amount) -> Result<()> {
crate::bitcoin::exempt_from_fee()?;
let signer = self.signer()?;
let coins: Coin<Nbtc> = amount.into();
self.ibc
.transfer_mut()
.burn_coins_execute(&signer, &coins.into(), &"".parse().unwrap())?;
self.bitcoin.accounts.deposit(signer, amount.into())?;
Ok(())
}
#[call]
pub fn eth_transfer_nbtc(
&mut self,
network: u32,
connection: Address,
address: Address,
amount: Amount,
) -> Result<()> {
#[cfg(feature = "ethereum")]
{
disable_fee();
let signer = self.signer()?;
let mut coins = self.bitcoin.accounts.withdraw(signer, amount)?;
let fee = coins.take(20_000_000)?;
self.bitcoin.give_rewards(fee)?;
let dest = Dest::EthAccount {
network,
connection: connection.into(),
address: address.into(),
};
let sender = Identity::from_signer()?;
self.bitcoin.insert_pending(dest, coins, sender)?;
Ok(())
}
#[cfg(not(feature = "ethereum"))]
{
Err(Error::App("Ethereum feature not enabled".into()))
}
}
#[query]
pub fn total_supply(&self) -> Result<Amount> {
let initial_supply: u64 = 17_500_000_000_000;
let staking_rewards_minted: u64 = self.staking_rewards.amount_minted.into();
let dev_rewards_minted: u64 = self.dev_rewards.amount_minted.into();
let community_pool_rewards_minted: u64 = self.community_pool_rewards.amount_minted.into();
let incentive_pool_rewards_minted: u64 = self.incentive_pool_rewards.amount_minted.into();
Ok(Amount::new(
initial_supply
+ staking_rewards_minted
+ dev_rewards_minted
+ community_pool_rewards_minted
+ incentive_pool_rewards_minted,
))
}
#[query]
pub fn escrowed_nbtc(&self, address: Address) -> Result<Amount> {
self.ibc.transfer().symbol_balance::<Nbtc>(address)
}
#[call]
pub fn claim_escrowed_nbtc(&mut self) -> Result<()> {
let signer = self.signer()?;
let balance = self.escrowed_nbtc(signer)?;
self.ibc_withdraw_nbtc(balance)
}
#[call]
pub fn relay_deposit(
&mut self,
btc_tx: Adapter<Transaction>,
btc_height: u32,
btc_proof: Adapter<PartialMerkleTree>,
btc_vout: u32,
sigset_index: u32,
dest: Dest,
) -> Result<()> {
let amount_after_fee =
self.bitcoin
.amount_after_deposit_fee(&btc_tx, btc_vout, sigset_index, &dest)?;
self.validate_dest(&dest, amount_after_fee.into(), Identity::None)?;
Ok(self.bitcoin.relay_deposit(
btc_tx,
btc_height,
btc_proof,
btc_vout,
sigset_index,
dest,
)?)
}
#[call]
pub fn relay_op_key(
&mut self,
client_id: ClientId,
height: (u64, u64),
cons_key: LengthVec<u8, u8>,
op_addr: Proof,
acc: Proof,
) -> Result<()> {
self.deduct_nbtc_fee(IBC_FEE_USATS.into())?;
Ok(self
.cosmos
.relay_op_key(&self.ibc, client_id, height, cons_key, op_addr, acc)?)
}
pub fn validate_dest(&self, dest: &Dest, amount: Amount, sender: Identity) -> Result<()> {
match dest {
Dest::NativeAccount { address } => {}
Dest::Ibc { data } => data.validate()?,
Dest::RewardPool => {}
#[cfg(feature = "ethereum")]
Dest::EthAccount {
network,
connection,
address,
} => {
self.ethereum
.network(*network)?
.connection((*connection).into())?
.validate_transfer((*address).into(), amount.into())?;
}
#[cfg(feature = "ethereum")]
Dest::EthCall {
network,
connection,
fallback_address,
max_gas,
..
} => {
self.ethereum
.network(*network)?
.connection((*connection).into())?
.validate_contract_call(*max_gas, (*fallback_address).into(), amount.into())?;
}
Dest::Bitcoin { data } => self.bitcoin.validate_withdrawal(data, amount)?,
#[cfg(feature = "babylon")]
Dest::Stake {
return_dest,
finality_provider,
staking_period,
} => {
// TODO: move into babylon
let params = &self.babylon.params;
let amount: u64 = amount.into();
if amount < params.min_staking_amount || amount > params.max_staking_amount {
return Err(Error::App("Invalid stake amount".to_string()));
}
if *staking_period < params.min_staking_time
|| *staking_period > params.max_staking_time
{
return Err(Error::App("Invalid staking period".to_string()));
}
let _: Dest = return_dest.parse()?;
if self.frost.most_recent_with_key()?.is_none() {
return Err(Error::App("No Frost DKG groups".to_string()));
}
}
#[cfg(feature = "babylon")]
Dest::Unstake { index } => {
// TODO: move into babylon
let owner_dels = self
.babylon
.delegations
.get(sender)?
.ok_or_else(|| Error::App("No delegations found for owner".to_string()))?;
let del = owner_dels
.get(*index)?
.ok_or_else(|| Error::App("Delegation not found".to_string()))?;
if del.status() == babylon::DelegationStatus::Withdrawn {
return Err(Error::App("Delegation already withdrawn".to_string()));
}
}
Dest::AdjustEmergencyDisbursalBalance { data, difference } => {
// TODO
}
}
Ok(())
}
fn try_credit_dest(
&mut self,
dest: Dest,
mut coins: Coin<Nbtc>,
sender: Identity,
) -> Result<()> {
let mut succeeded = false;
let amount = coins.amount;
if let Err(e) = self.validate_dest(&dest, amount, sender) {
log::debug!("Error validating transfer: {}", e);
} else if let Err(e) = self.credit_dest(dest.clone(), coins.take(amount)?, sender) {
log::debug!("Error crediting transfer: {:?}", e);
// TODO: ensure no errors can happen after mutating
// state in credit_dest since state won't be reverted
// Assume coins passed into credit_dest are burnt,
// replace them in `coins`
coins.give(Coin::mint(amount))?;
} else {
succeeded = true;
}
// Handle failures
if !succeeded {
log::debug!(
"Failed to credit transfer to {} (amount: {}, sender: {})",
dest,
amount,
sender,
);
match sender {
Identity::NativeAccount { address } => {
log::debug!("Returning funds to NativeAccount sender");
self.bitcoin.accounts.deposit(address, coins)?;
}
#[cfg(feature = "ethereum")]
Identity::EthAccount {
network,
connection,
address,
} => {
let res = self
.ethereum
.network_mut(network)?
.connection_mut(connection.into())?
.transfer(address.into(), coins);
if let Err(e) = res {
log::debug!("Error returning funds to EthAccount sender: {:?}", e);
// TODO: place funds in rewards pool?
} else {
log::debug!("Returning funds to EthAccount sender");
}
}
_ => {}
}
}
Ok(())
}
fn credit_dest(&mut self, dest: Dest, nbtc: Coin<Nbtc>, sender: Identity) -> Result<()> {
log::debug!(
"Crediting dest: {} (amount: {}, sender: {})",
&dest,
nbtc.amount,
&sender
);
match dest {
Dest::NativeAccount { address } => self.bitcoin.accounts.deposit(address, nbtc)?,
Dest::Ibc { data: dest } => dest.transfer(nbtc, &mut self.bitcoin, &mut self.ibc)?,
Dest::RewardPool => self.bitcoin.give_rewards(nbtc)?,
#[cfg(feature = "ethereum")]
Dest::EthAccount {
network,
connection,
address,
} => self
.ethereum
.network_mut(network)?
.connection_mut(connection.into())?
.transfer(address.into(), nbtc)?,
#[cfg(feature = "ethereum")]
Dest::EthCall {
network,
connection,
contract_address,
data,
max_gas,
fallback_address,
} => self
.ethereum
.network_mut(network)?
.connection_mut(connection.into())?
.call_contract(contract_address, data, max_gas, fallback_address, nbtc)?,
Dest::Bitcoin { data } => self.bitcoin.add_withdrawal(data, nbtc)?,
#[cfg(feature = "babylon")]
Dest::Stake {
return_dest,
finality_provider,
staking_period,
} => {
let return_dest = return_dest.parse()?;
self.babylon.stake(
&mut self.bitcoin,
&mut self.frost,
sender,
return_dest,
finality_provider,
staking_period,
nbtc,
)?;
}
#[cfg(feature = "babylon")]
Dest::Unstake { index } => {
self.babylon
.unstake(sender, index, &mut self.frost, &self.bitcoin)?;
nbtc.burn();
}
Dest::AdjustEmergencyDisbursalBalance { data, difference } => {
#[cfg(feature = "ethereum")]
if let Identity::EthAccount {
network,
connection,
..
} = sender
{
self.ethereum
.network_mut(network)?
.connection_mut(connection.into())?
.adjust_emergency_disbursal_balance(data, difference)?;
}
nbtc.burn();
}
};
Ok(())
}
#[call]
pub fn withdraw_nbtc(
&mut self,
script_pubkey: Adapter<bitcoin::Script>,
amount: Amount,
) -> Result<()> {
Ok(self.bitcoin.withdraw(script_pubkey, amount)?)
}
#[call]
fn join_accounts(&mut self, dest_addr: Address) -> Result<()> {
disable_fee();
self.airdrop.join_accounts(dest_addr)?;
self.incentives.join_accounts(dest_addr)?;
Ok(())
}
fn signer(&mut self) -> Result<Address> {
self.context::<Signer>()
.ok_or_else(|| Error::Signer("No Signer context available".into()))?
.signer
.ok_or_else(|| Error::Coins("Unauthorized account action".into()))
}
#[call]
pub fn signal(&mut self, version: Version) -> Result<()> {
self.upgrade.signal(version)
}
#[call]
pub fn ibc_deliver(&mut self, messages: RawIbcTx) -> Result<()> {
self.deduct_nbtc_fee(IBC_FEE_USATS.into())?;
let incoming_transfers = self.ibc.deliver(messages)?;
for transfer in incoming_transfers {
if transfer.denom.to_string() != "usat" || transfer.memo.is_empty() {
continue;
}
let receiver: Address = transfer
.receiver
.parse()
.map_err(|_| Error::Coins("Invalid address".to_string()))?;
let amount = transfer.amount;
let Ok(dest) = transfer.memo.parse::<Dest>() else {
continue;
};
let coins = Coin::<Nbtc>::mint(amount);
self.ibc.transfer_mut().burn_coins_execute(
&receiver,
&coins.into(),
&"".parse().unwrap(),
)?;
let coins = Coin::<Nbtc>::mint(amount);
let sender = Identity::None; // TODO
self.bitcoin.insert_pending(dest, coins, sender)?;
}
Ok(())
}
#[call]
pub fn declare_with_nbtc(&mut self, declaration: Declaration) -> Result<()> {
self.deduct_nbtc_fee(CALL_FEE_USATS.into())?;
let signer = self.signer()?;
self.staking.declare(signer, declaration, 0.into())
}
#[call]
pub fn pay_nbtc_fee(&mut self) -> Result<()> {
self.deduct_nbtc_fee(CALL_FEE_USATS.into())
}
fn deduct_nbtc_fee(&mut self, amount: Amount) -> Result<()> {
disable_fee();
let signer = self.signer()?;
let fee = self.bitcoin.accounts.withdraw(signer, amount)?;
self.bitcoin.give_rewards(fee)?;
Ok(())
}
// TODO: temporary workaround, will be exposed by client soon
pub fn height(&self) -> u64 {
self.ibc.ctx.query_height().unwrap()
}
#[call]
pub fn stake_nbtc(
&mut self,
amount: Amount,
finality_provider: [u8; 32],
staking_period: u16,
) -> Result<()> {
#[cfg(feature = "babylon")]
{
// TODO: validate staking/unbonding periods
// TODO: go through dest flow
let signer = self.signer()?;
let stake = self.bitcoin.accounts.withdraw(signer, amount)?;
self.babylon.stake(
&mut self.bitcoin,
&mut self.frost,
Identity::from_signer()?,
Dest::NativeAccount { address: signer },
finality_provider,
staking_period,
stake,
)?;
Ok(())
}
#[cfg(not(feature = "babylon"))]
{
Err(Error::App("Babylon feature not enabled".into()))
}
}
// TODO: move into babylon module, get HeaderQueue via context
#[call]
pub fn relay_btc_staking_tx(
&mut self,
del_owner: Identity,
del_index: u64,
height: u32,
proof: Adapter<PartialMerkleTree>,
tx: Adapter<Transaction>,
vout: u32,
) -> Result<()> {
#[cfg(feature = "babylon")]
{
exempt_from_fee()?;
self.babylon
.delegations
.get_mut(del_owner)?
.ok_or_else(|| Error::App("No delegations found with given owner".into()))?
.get_mut(del_index)?
.ok_or_else(|| Error::App("Delegation not found".into()))?
.relay_staking_tx(
&self.bitcoin.headers,
height,
proof.into_inner(),
tx.into_inner(),
vout,
&self.babylon.params,
&mut self.babylon.staked,
&mut self.frost,
&self.bitcoin,
)?;
Ok(())
}
#[cfg(not(feature = "babylon"))]
{
Err(Error::App("Babylon feature not enabled".into()))
}
}
// TODO: move into babylon module, get HeaderQueue via context
#[call]
pub fn relay_btc_unbonding_tx(
&mut self,
del_owner: Identity,
del_index: u64,
height: u32,
proof: Adapter<PartialMerkleTree>,
tx: Adapter<Transaction>,
) -> Result<()> {
#[cfg(feature = "babylon")]
{
exempt_from_fee()?;
self.babylon
.delegations
.get_mut(del_owner)?
.ok_or_else(|| Error::App("No delegations found with given owner".into()))?
.get_mut(del_index)?
.ok_or_else(|| Error::App("Delegation not found".into()))?
.relay_unbonding_tx(
&self.bitcoin.headers,
height,
proof.into_inner(),
tx.into_inner(),
&self.babylon.params,
&mut self.babylon.unbonding,
&mut self.babylon.staked,
)?;
Ok(())
}
#[cfg(not(feature = "babylon"))]
{
Err(Error::App("Babylon feature not enabled".into()))
}
}
#[call]
pub fn eth_create_connection(
&mut self,
chain_id: u32,
bridge_contract: Address,
token_contract: Address,
sigset_index: u32,
) -> Result<()> {
#[cfg(feature = "ethereum")]
{
self.deduct_nbtc_fee(ETH_CREATE_CONNECTION_FEE_USATS.into())?;
let valset = self.bitcoin.checkpoints.get(sigset_index)?.sigset.clone();
Ok(self.ethereum.create_connection(
chain_id,
bridge_contract,
token_contract,
valset,
)?)
}
#[cfg(not(feature = "ethereum"))]
{
Err(Error::App("Ethereum feature not enabled".into()))
}
}
#[call]
pub fn app_noop(&mut self) -> Result<()> {
Ok(())
}
#[query]
pub fn app_noop_query(&self) -> Result<()> {
Ok(())
}
#[cfg(all(feature = "frost", feature = "testnet"))]
fn step_frost(&mut self, now: i64) -> Result<()> {
let last_frost_group = self.frost.groups.back()?;
let last_frost_group_time = last_frost_group.as_ref().map(|g| g.created_at).unwrap_or(0);
let absent = last_frost_group
.map(|v| v.absent().unwrap_or_default())
.unwrap_or_default();
if now > last_frost_group_time + FROST_GROUP_INTERVAL {
let frost_config =
FrostConfig::from_staking(&self.staking, FROST_TOP_N, FROST_THRESHOLD, &absent)?;
if frost_config.participants.len() < 2 {
return Ok(());
}
let group = FrostGroup::with_config(frost_config, now)?;
self.frost.groups.push_back(group)?;
}
self.frost.advance_with_timeout(60 * 5)?;
Ok(())
}
}
#[cfg(feature = "full")]
mod abci {
use orga::{
abci::{messages, AbciQuery, BeginBlock, EndBlock, InitChain},
coins::{Give, Take},
collections::Map,
plugins::{BeginBlockCtx, EndBlockCtx, InitChainCtx, Validators},
};
#[cfg(feature = "ethereum")]
use crate::ethereum::bytes32;
#[cfg(feature = "frost")]
use crate::frost::FrostGroup;
use super::*;
impl InitChain for InnerApp {
fn init_chain(&mut self, _ctx: &InitChainCtx) -> Result<()> {
self.staking.max_validators = 30;
self.staking.max_offline_blocks = 20_000;
self.staking.downtime_jail_seconds = 60 * 30; // 30 minutes
self.staking.slash_fraction_downtime = (Amount::new(1) / Amount::new(1000))?;
self.staking.slash_fraction_double_sign = (Amount::new(1) / Amount::new(20))?;
self.staking.min_self_delegation_min = 0;
let sr_address = STRATEGIC_RESERVE_ADDRESS.parse().unwrap();
self.accounts.allow_transfers(true);
self.bitcoin.accounts.allow_transfers(true);
self.accounts.add_transfer_exception(sr_address)?;
let vb_address = VALIDATOR_BOOTSTRAP_ADDRESS.parse().unwrap();
self.accounts.add_transfer_exception(vb_address)?;
self.configure_faucets()?;
self.upgrade
.current_version
.insert((), vec![Self::CONSENSUS_VERSION].try_into().unwrap())?;
#[cfg(feature = "testnet")]
{
self.upgrade.activation_delay_seconds = 20 * 60;
self.bitcoin.config.min_confirmations = 0;
self.bitcoin.config.min_withdrawal_checkpoints = 0;
self.bitcoin.checkpoints.config.min_checkpoint_interval = 60;
include_str!("../testnet_addresses.csv")
.lines()
.try_for_each(|line| {
let address = line.parse().unwrap();
self.accounts.deposit(address, Coin::mint(10_000_000_000))
})?;
#[cfg(feature = "ethereum")]
{
// Add Ethereum Sepolia
let bootstrap =
serde_json::from_str(include_str!("./ethereum/bootstrap/sepolia.json"))
.unwrap();
self.ethereum.networks.insert(
11155111,
crate::ethereum::Network::new(
11155111,
bootstrap,
crate::ethereum::consensus::Network::ethereum_sepolia(),
)?,
)?;
}
}
Ok(())
}
}
impl BeginBlock for InnerApp {
fn begin_block(&mut self, ctx: &BeginBlockCtx) -> Result<()> {
let now = ctx.header.time.as_ref().unwrap().seconds;
self.upgrade.step(
&vec![Self::CONSENSUS_VERSION].try_into().unwrap(),
in_upgrade_window(now),
)?;
self.staking.begin_block(ctx)?;
self.ibc.begin_block(ctx)?;
let has_stake = self.staking.staked()? > 0;
if has_stake {
let reward = self.staking_rewards.mint()?;
self.staking.give(reward)?;
}
let dev_reward = self.dev_rewards.mint()?;
let dev_address = DEV_ADDRESS.parse().unwrap();
self.accounts.deposit(dev_address, dev_reward)?;
let cp_reward = self.community_pool_rewards.mint()?;
self.community_pool.give(cp_reward)?;
let ip_reward = self.incentive_pool_rewards.mint()?;
self.incentive_pool.give(ip_reward)?;
#[cfg(all(feature = "frost", feature = "testnet"))]
if !self.bitcoin.checkpoints.is_empty()? {
self.step_frost(now)?;
}
#[cfg(feature = "ethereum")]
{
if !self.bitcoin.checkpoints.is_empty()? {
self.ethereum
.step(&self.bitcoin.checkpoints.active_sigset()?)?;
let pending = &mut self.bitcoin.checkpoints.building_mut()?.pending;
for (dest, coins, sender) in self.ethereum.take_pending()? {
pending.insert((dest, sender), coins)?;
}
}
}
let pending_nbtc_transfers = self.bitcoin.take_pending()?;
for (dest, coins, sender) in pending_nbtc_transfers {
self.try_credit_dest(dest, coins, sender)?;
}
let external_outputs = if self.bitcoin.should_push_checkpoint()? {
self.cosmos
.build_outputs(&self.ibc, self.bitcoin.checkpoints.index)?
} else {
vec![]
};
let offline_signers = self
.bitcoin
.begin_block_step(external_outputs.into_iter().map(Ok), ctx.hash.clone())?;
for cons_key in offline_signers {
let address = self.staking.address_by_consensus_key(cons_key)?.unwrap();
self.staking.punish_downtime(address)?;
}
let has_nbtc_rewards = self.bitcoin.reward_pool.amount > 0;
if self.reward_timer.tick(now) && has_stake && has_nbtc_rewards {
let reward_rate = (Amount::new(1) / Amount::new(2377))?; // ~0.00042069
let reward_amount = (self.bitcoin.reward_pool.amount * reward_rate)?.amount()?;
let reward = self.bitcoin.reward_pool.take(reward_amount)?;
self.staking.give(reward)?;
}
#[cfg(feature = "babylon")]
self.babylon.step(&mut self.frost, &mut self.bitcoin)?;
Ok(())
}
}
impl EndBlock for InnerApp {
fn end_block(&mut self, ctx: &EndBlockCtx) -> Result<()> {
self.staking.end_block(ctx)
}
}
impl AbciQuery for InnerApp {
fn abci_query(&self, request: &messages::RequestQuery) -> Result<messages::ResponseQuery> {
self.ibc.abci_query(request)
}
}
}
impl ConvertSdkTx for InnerApp {
type Output = PaidCall<<Self as Call>::Call>;
fn convert(&self, sdk_tx: &SdkTx) -> Result<PaidCall<<Self as Call>::Call>> {
let sender_address = sdk_tx.sender_address()?;
match sdk_tx {
SdkTx::Protobuf(tx) => {
if IbcTx::try_from(tx.clone()).is_ok() {
let raw_ibc_tx = RawIbcTx(tx.clone());
let payer = build_call!(self.ibc_deliver(raw_ibc_tx));
let paid = build_call!(self.app_noop());
return Ok(PaidCall { payer, paid });
}
if tx.body.messages.len() != 1 {
return Err(Error::App(
"Only transactions with one message are supported".into(),
));
}
let msg = &tx.body.messages[0];
if msg.type_url.as_str() == "cosmos-sdk/MsgSend" {
use orga::cosmrs::tx::Msg;
let msg =
MsgSend::from_any(msg).map_err(|_| Error::App("Invalid MsgSend".into()))?;
let from_bytes: [u8; Address::LENGTH] = msg
.from_address
.to_bytes()
.try_into()
.map_err(|_| Error::App("Invalid sender address".into()))?;
let from: Address = from_bytes.into();
if from != sender_address {
return Err(Error::App(
"'from_address' must match sender address".to_string(),
));
}
let to_bytes: [u8; Address::LENGTH] = msg
.to_address
.to_bytes()
.try_into()
.map_err(|_| Error::App("Invalid receiver address".into()))?;
let to: Address = to_bytes.into();
if msg.amount.len() != 1 {
return Err(Error::App(
"'amount' must have exactly one element".to_string(),
));
}
match msg.amount[0].denom.to_string().as_str() {
"unom" => {
let amount: u64 = msg.amount[0]
.amount
.to_string()
.parse()
.map_err(|_| Error::App("Invalid amount".to_string()))?;
let payer = build_call!(self.accounts.take_as_funding(MIN_FEE.into()));
let paid = build_call!(self.accounts.transfer(to, amount.into()));
return Ok(PaidCall { payer, paid });
}
"usat" => {
let amount: u64 = msg.amount[0]
.amount
.to_string()
.parse()
.map_err(|_| Error::App("Invalid amount".to_string()))?;
let payer = build_call!(self.bitcoin.transfer(to, amount.into()));
let paid = build_call!(self.app_noop());
return Ok(PaidCall { payer, paid });
}
_ => return Err(Error::App("Unknown denom".to_string())),
}
}
Err(Error::App("Unsupported protobuf transaction".into()))
}
SdkTx::Amino(tx) => {
if tx.msg.len() != 1 {
return Err(Error::App("Invalid number of messages".into()));
}
let msg = &tx.msg[0];
let get_amount = |coin: Option<&sdk::Coin>, expected_denom| -> Result<Amount> {
let coin = coin.map_or_else(|| Err(Error::App("Empty amount".into())), Ok)?;
if coin.denom != expected_denom {
return Err(Error::App(format!(
"Invalid denom in amount: {}",
coin.denom,
)));
}
let amount: u64 = coin.amount.parse()?;
Ok(Amount::new(amount))
};
// TODO: move message validation/parsing into orga (e.g. with a message enum)
match msg.type_.as_str() {
"cosmos-sdk/MsgSend" => {
let msg: sdk::MsgSend = serde_json::value::from_value(msg.value.clone())
.map_err(|e| Error::App(e.to_string()))?;
let from: Address = msg
.from_address
.parse()
.map_err(|e: bech32::Error| Error::App(e.to_string()))?;
if from != sender_address {
return Err(Error::App(
"'from_address' must match sender address".to_string(),
));
}
let to: Address = msg
.to_address
.parse()
.map_err(|e: bech32::Error| Error::App(e.to_string()))?;
if msg.amount.len() != 1 {
return Err(Error::App(
"'amount' must have exactly one element".to_string(),
));
}
match msg.amount[0].denom.as_str() {
"unom" => {
let amount = get_amount(msg.amount.first(), "unom")?;
let payer =
build_call!(self.accounts.take_as_funding(MIN_FEE.into()));
let paid = build_call!(self.accounts.transfer(to, amount));
Ok(PaidCall { payer, paid })
}
"usat" => {
let amount = get_amount(msg.amount.first(), "usat")?;
let payer = build_call!(self.bitcoin.transfer(to, amount));
let paid = build_call!(self.app_noop());
Ok(PaidCall { payer, paid })
}
_ => Err(Error::App("Unknown denom".to_string())),
}
}
"cosmos-sdk/MsgDelegate" => {
let msg: sdk::MsgDelegate =
serde_json::value::from_value(msg.value.clone())
.map_err(|e| Error::App(e.to_string()))?;
let del_addr: Address = msg
.delegator_address
.parse()
.map_err(|e: bech32::Error| Error::App(e.to_string()))?;
if del_addr != sender_address {
return Err(Error::App(
"'delegator_address' must match sender address".to_string(),
));
}
let val_addr: Address = msg
.validator_address
.parse()
.map_err(|e: bech32::Error| Error::App(e.to_string()))?;
let amount: u64 = get_amount(msg.amount.as_ref(), "unom")?.into();
let funding_amt = MIN_FEE + amount;
let payer = build_call!(self.accounts.take_as_funding(funding_amt.into()));
let paid =
build_call!(self.staking.delegate_from_self(val_addr, amount.into()));
Ok(PaidCall { payer, paid })
}
"cosmos-sdk/MsgBeginRedelegate" => {
let msg: sdk::MsgBeginRedelegate =
serde_json::value::from_value(msg.value.clone())
.map_err(|e| Error::App(e.to_string()))?;
let del_addr: Address = msg
.delegator_address
.parse()
.map_err(|e: bech32::Error| Error::App(e.to_string()))?;
if del_addr != sender_address {
return Err(Error::App(
"'delegator_address' must match sender address".to_string(),
));
}
let val_src_addr: Address = msg
.validator_src_address
.parse()
.map_err(|e: bech32::Error| Error::App(e.to_string()))?;
let val_dst_addr: Address = msg
.validator_dst_address
.parse()
.map_err(|e: bech32::Error| Error::App(e.to_string()))?;
let amount = get_amount(msg.amount.as_ref(), "unom")?;
let funding_amt = MIN_FEE;
let payer = build_call!(self.accounts.take_as_funding(funding_amt.into()));
let paid = build_call!(self.staking.redelegate_self(
val_src_addr,
val_dst_addr,
amount
));
Ok(PaidCall { payer, paid })
}
"cosmos-sdk/MsgUndelegate" => {
let msg: sdk::MsgUndelegate =
serde_json::value::from_value(msg.value.clone())
.map_err(|e| Error::App(e.to_string()))?;
let del_addr: Address = msg
.delegator_address
.parse()
.map_err(|e: bech32::Error| Error::App(e.to_string()))?;
if del_addr != sender_address {
return Err(Error::App(
"'delegator_address' must match sender address".to_string(),
));
}
let val_addr: Address = msg
.validator_address
.parse()
.map_err(|e: bech32::Error| Error::App(e.to_string()))?;
let amount = get_amount(msg.amount.as_ref(), "unom")?;
let funding_amt = MIN_FEE;
let payer = build_call!(self.accounts.take_as_funding(funding_amt.into()));
let paid = build_call!(self.staking.unbond_self(val_addr, amount));
Ok(PaidCall { payer, paid })
}
"nomic/MsgClaimRewards" => {
let msg = msg
.value
.as_object()
.ok_or_else(|| Error::App("Invalid message value".to_string()))?;
if !msg.is_empty() {
return Err(Error::App("Message should be empty".to_string()));
}
let payer = build_call!(self.staking.claim_all());
let paid = build_call!(self.deposit_rewards());
Ok(PaidCall { payer, paid })
}
"nomic/MsgClaimAirdrop1" => {
let msg = msg
.value
.as_object()
.ok_or_else(|| Error::App("Invalid message value".to_string()))?;
if !msg.is_empty() {
return Err(Error::App("Message should be empty".to_string()));
}
let payer = build_call!(self.airdrop.claim_airdrop1());
let paid = build_call!(self.accounts.give_from_funding_all());
Ok(PaidCall { payer, paid })
}
"nomic/MsgClaimAirdrop2" => {
let msg = msg
.value
.as_object()
.ok_or_else(|| Error::App("Invalid message value".to_string()))?;
if !msg.is_empty() {
return Err(Error::App("Message should be empty".to_string()));
}
let payer = build_call!(self.airdrop.claim_airdrop2());
let paid = build_call!(self.accounts.give_from_funding_all());
Ok(PaidCall { payer, paid })
}
"nomic/MsgWithdraw" => {
let msg: MsgWithdraw = serde_json::value::from_value(msg.value.clone())
.map_err(|e| Error::App(e.to_string()))?;
let dest_addr: bitcoin::Address = msg.dst_address.parse().map_err(
|e: bitcoin::util::address::Error| Error::App(e.to_string()),
)?;
if !matches_bitcoin_network(&dest_addr.network) {
return Err(Error::App(format!(
"Invalid network for destination address. Got {}, Expected {}",
dest_addr.network,
crate::bitcoin::NETWORK
)));
}
let dest_script =
crate::bitcoin::adapter::Adapter::new(dest_addr.script_pubkey());
let amount: u64 = msg
.amount
.parse()
.map_err(|e: std::num::ParseIntError| Error::App(e.to_string()))?;
let payer = build_call!(self.withdraw_nbtc(dest_script, amount.into()));
let paid = build_call!(self.app_noop());
Ok(PaidCall { payer, paid })
}
"nomic/MsgClaimIbcBitcoin" => {
let msg = msg
.value
.as_object()
.ok_or_else(|| Error::App("Invalid message value".to_string()))?;
if !msg.is_empty() {
return Err(Error::App("Message should be empty".to_string()));
}
let payer = build_call!(self.claim_escrowed_nbtc());
let paid = build_call!(self.app_noop());
Ok(PaidCall { payer, paid })
}
"nomic/MsgIbcTransferOut" => {
let msg: MsgIbcTransfer = serde_json::value::from_value(msg.value.clone())
.map_err(|e| Error::App(e.to_string()))?;
let channel_id = msg
.channel_id
.parse::<ChannelId>()
.map_err(|_| Error::Ibc("Invalid channel id".into()))?;
let port_id = msg
.port_id
.parse::<PortId>()
.map_err(|_| Error::Ibc("Invalid port".into()))?;
let denom = msg.denom.as_str();
if denom != "usat" {
return Err(Error::App("Unsupported denom for IBC transfer".into()));
}
let amount: u64 = msg
.amount
.parse()
.map_err(|e: std::num::ParseIntError| Error::App(e.to_string()))?;
let ibc_sender_addr = msg
.sender
.parse::<Address>()
.map_err(|_| Error::Ibc("Invalid sender address".into()))?;
if ibc_sender_addr != sender_address {
return Err(Error::App(
"'sender' must match sender address".to_string(),
));
}
let timeout_timestamp = msg
.timeout_timestamp
.parse::<u64>()
.map_err(|_| Error::Ibc("Invalid timeout timestamp".into()))?;
let dest = IbcDest {
source_port: port_id.to_string().try_into()?,
source_channel: channel_id.to_string().try_into()?,
sender: msg.sender.try_into()?,
receiver: msg.receiver.try_into()?,
timeout_timestamp,
memo: msg.memo.try_into()?,
};
let payer = build_call!(self.ibc_transfer_nbtc(dest, amount.into()));
let paid = build_call!(self.app_noop());
Ok(PaidCall { payer, paid })
}
"nomic/MsgJoinRewardAccounts" => {
let msg = msg
.value
.as_object()
.ok_or_else(|| Error::App("Invalid message value".to_string()))?;
let dest_addr: Address = msg
.get("dest_address")
.ok_or_else(|| Error::App("Missing destination address".to_string()))?
.as_str()
.ok_or_else(|| Error::App("Invalid destination address".to_string()))?
.parse()
.map_err(|_| Error::App("Invalid destination address".to_string()))?;
let payer = build_call!(self.join_accounts(dest_addr));
let paid = build_call!(self.app_noop());
Ok(PaidCall { payer, paid })
}
"nomic/MsgClaimTestnetParticipationIncentives" => {
let msg = msg
.value
.as_object()
.ok_or_else(|| Error::App("Invalid message value".to_string()))?;
if !msg.is_empty() {
return Err(Error::App("Message should be empty".to_string()));
}
let payer =
build_call!(self.incentives.claim_testnet_participation_incentives());
let paid = build_call!(self.accounts.give_from_funding_all());
Ok(PaidCall { payer, paid })
}
"nomic/MsgSetRecoveryAddress" => {
let msg = msg
.value
.as_object()
.ok_or_else(|| Error::App("Invalid message value".to_string()))?;
let recovery_addr: bitcoin::Address = msg
.get("recovery_address")
.ok_or_else(|| Error::App("Missing reovery address".to_string()))?
.as_str()
.ok_or_else(|| Error::App("Invalid recovery address".to_string()))?
.parse()
.map_err(|_| Error::App("Invalid recovery address".to_string()))?;
if !matches_bitcoin_network(&recovery_addr.network) {
return Err(Error::App(format!(
"Invalid network for recovery address. Got {}, Expected {}",
recovery_addr.network,
crate::bitcoin::NETWORK
)));
}
let script =
crate::bitcoin::adapter::Adapter::new(recovery_addr.script_pubkey());
let funding_amt = MIN_FEE;
let payer = build_call!(self.pay_nbtc_fee());
let paid = build_call!(self.bitcoin.set_recovery_script(script.clone()));
Ok(PaidCall { payer, paid })
}
"nomic/MsgPayToFeePool" => {
let msg = msg
.value
.as_object()
.ok_or_else(|| Error::App("Invalid message value".to_string()))?;
let amount: u64 = msg
.get("amount")
.ok_or_else(|| Error::App("Missing amount".to_string()))?
.as_str()
.ok_or_else(|| Error::App("Invalid amount".to_string()))?
.parse()
.map_err(|e: std::num::ParseIntError| Error::App(e.to_string()))?;
let payer = build_call!(self.bitcoin.transfer_to_fee_pool(amount.into()));
let paid = build_call!(self.app_noop());
Ok(PaidCall { payer, paid })
}
"nomic/MsgStakeNbtc" => {
let msg = msg
.value
.as_object()
.ok_or_else(|| Error::App("Invalid message value".to_string()))?;
let amount: u64 = msg
.get("amount")
.ok_or_else(|| Error::App("Invalid amount".to_string()))?
.as_str()
.ok_or_else(|| Error::App("Invalid amount".to_string()))?
.parse()
.map_err(|e: std::num::ParseIntError| Error::App(e.to_string()))?;
let fp_vec = hex::decode(
msg.get("finality_provider")
.ok_or_else(|| Error::App("Invalid finality provider".to_string()))?
.as_str()
.ok_or_else(|| {
Error::App("Invalid finality provider".to_string())
})?,
)
.map_err(|e| Error::App(e.to_string()))?;
if fp_vec.len() != 32 {
return Err(Error::App("Invalid finality provider".to_string()));
}
let mut fp = [0; 32];
fp.copy_from_slice(&fp_vec);
let staking_period: u16 = msg
.get("staking_period")
.ok_or_else(|| Error::App("Invalid staking period".to_string()))?
.as_str()
.ok_or_else(|| Error::App("Invalid staking period".to_string()))?
.parse()
.map_err(|e: std::num::ParseIntError| Error::App(e.to_string()))?;
let unbonding_period: u16 = msg
.get("unbonding_period")
.ok_or_else(|| Error::App("Invalid unbonding period".to_string()))?
.as_str()
.ok_or_else(|| Error::App("Invalid unbonding period".to_string()))?
.parse()
.map_err(|e: std::num::ParseIntError| Error::App(e.to_string()))?;
let payer = build_call!(self.pay_nbtc_fee());
let paid = build_call!(self.stake_nbtc(amount.into(), fp, staking_period));
Ok(PaidCall { payer, paid })
}
_ => Err(Error::App("Unsupported message type".into())),
}
}
}
}
}
#[derive(Serialize, Deserialize)]
pub struct MsgWithdraw {
pub amount: String,
pub dst_address: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MsgIbcTransfer {
pub channel_id: String,
pub port_id: String,
pub amount: String,
pub denom: String,
pub receiver: String,
pub sender: String,
pub timeout_timestamp: String,
pub memo: String,
}
use orga::ibc::{IbcMessage, PortChannel, RawIbcTx};
#[derive(Clone, Debug, Encode, Decode, Serialize, Deserialize, State)]
pub struct IbcDest {
pub source_port: LengthString<u8>,
pub source_channel: LengthString<u8>,
pub receiver: LengthString<u8>,
pub sender: LengthString<u8>,
pub timeout_timestamp: u64,
pub memo: LengthString<u16>,
}
impl IbcDest {
pub fn transfer(
&self,
mut coins: Coin<Nbtc>,
bitcoin: &mut Bitcoin,
ibc: &mut Ibc,
) -> Result<()> {
use orga::ibc::ibc_rs::apps::transfer::types::msgs::transfer::MsgTransfer;
if !self.is_fee_exempt() {
let fee_amount = ibc_fee(coins.amount)?;
let fee = coins.take(fee_amount)?;
bitcoin.give_rewards(fee)?;
}
let nbtc_amount = coins.amount;
ibc.transfer_mut()
.mint_coins_execute(&self.sender_address()?, &coins.into())?;
let msg_transfer = MsgTransfer {
port_id_on_a: self.source_port()?,
chan_id_on_a: self.source_channel()?,
packet_data: PacketData {
token: Nbtc::mint(nbtc_amount).into(),
receiver: self.receiver_signer()?,
sender: self.sender_signer()?,
memo: self.memo()?,
},
timeout_height_on_b: TimeoutHeight::Never,
timeout_timestamp_on_b: TimeoutTimestamp::from_nanoseconds(self.timeout_timestamp),
};
if let Err(err) = ibc.deliver_message(IbcMessage::Ics20(msg_transfer)) {
log::debug!("Failed IBC transfer: {}", err);
}
Ok(())
}
pub fn sender_address(&self) -> Result<Address> {
self.sender
.to_string()
.parse()
.map_err(|e: bech32::Error| Error::Coins(e.to_string()))
}
pub fn sender_signer(&self) -> Result<IbcSigner> {
Ok(self.sender.to_string().into())
}
pub fn receiver_signer(&self) -> Result<IbcSigner> {
Ok(self.receiver.to_string().into())
}
pub fn source_channel(&self) -> Result<ChannelId> {
self.source_channel
.to_string()
.parse()
.map_err(|_| Error::Ibc("Invalid channel id".into()))
}
pub fn source_port(&self) -> Result<PortId> {
self.source_port
.to_string()
.parse()
.map_err(|_| Error::Ibc("Invalid port id".into()))
}
pub fn memo(&self) -> Result<Memo> {
Ok(self.memo.to_string().into())
}
pub fn is_fee_exempt(&self) -> bool {
self.source_channel()
.map_or(false, |channel| channel.to_string() == OSMOSIS_CHANNEL_ID)
}
pub fn validate(&self) -> Result<()> {
self.source_port()?;
self.source_channel()?;
self.sender_address()?;
Ok(())
}
pub fn legacy_encode(&self) -> Result<Vec<Vec<u8>>> {
let mut encodings = vec![];
let mut bytes = vec![];
self.source_port.encode_into(&mut bytes)?;
self.source_channel.encode_into(&mut bytes)?;
EdAdapter(self.receiver_signer()?).encode_into(&mut bytes)?;
EdAdapter(self.sender_signer()?).encode_into(&mut bytes)?;
self.timeout_timestamp.encode_into(&mut bytes)?;
self.memo.encode_into(&mut bytes)?;
encodings.push(Sha256::digest(bytes).to_vec());
if self.memo.len() < 256 {
let mut bytes = vec![];
self.source_port.encode_into(&mut bytes)?;
self.source_channel.encode_into(&mut bytes)?;
self.receiver.encode_into(&mut bytes)?;
self.sender.encode_into(&mut bytes)?;
self.timeout_timestamp.encode_into(&mut bytes)?;
LengthString::<u8>::new(self.memo.len() as u8, self.memo.to_string())
.encode_into(&mut bytes)?;
let hash = Sha256::digest(bytes);
let mut bytes = Vec::with_capacity(hash.len() + 1);
bytes.push(0); // version byte
bytes.extend_from_slice(&hash);
encodings.push(bytes);
}
Ok(encodings)
}
}
impl Migrate for IbcDest {
#[allow(clippy::needless_borrows_for_generic_args)]
fn migrate(_src: Store, _dest: Store, mut bytes: &mut &[u8]) -> Result<Self> {
let source_port = LengthString::<u8>::decode(&mut bytes)?;
let source_channel = LengthString::<u8>::decode(&mut bytes)?;
let receiver = LengthString::<u8>::decode(&mut bytes)?;
let sender = LengthString::<u8>::decode(&mut bytes)?;
let timeout_timestamp = u64::decode(&mut bytes)?;
let memo = LengthString::<u8>::decode(&mut bytes)?;
Ok(IbcDest {
source_port,
source_channel,
receiver,
sender,
timeout_timestamp,
memo: memo.to_string().try_into().unwrap(),
})
}
}
#[derive(Encode, Decode, Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum Dest {
NativeAccount {
address: Address,
},
Ibc {
data: IbcDest,
},
RewardPool,
Bitcoin {
#[serde(with = "address_or_script")]
data: Adapter<Script>,
},
#[cfg(feature = "ethereum")]
EthAccount {
network: u32,
// TODO: ethaddress type
#[serde(with = "SerHex::<StrictPfx>")]
connection: [u8; 20],
// TODO: ethaddress type
#[serde(with = "SerHex::<StrictPfx>")]
address: [u8; 20],
},
#[cfg(feature = "ethereum")]
EthCall {
network: u32,
// TODO: ethaddress type
#[serde(with = "SerHex::<StrictPfx>")]
connection: [u8; 20],
// TODO: ethaddress type
#[serde(with = "SerHex::<StrictPfx>")]
contract_address: [u8; 20],
data: LengthVec<u16, u8>,
max_gas: u64,
// TODO: ethaddress type
#[serde(with = "SerHex::<StrictPfx>")]
fallback_address: [u8; 20],
},
#[cfg(feature = "babylon")]
Stake {
// TODO: this should be a Dest, but the cycle prevents the macro-generated Terminated impl
// from applying
return_dest: LengthString<u16>,
#[serde(with = "SerHex::<Strict>")]
finality_provider: [u8; 32],
staking_period: u16,
},
#[cfg(feature = "babylon")]
Unstake {
index: u64,
},
AdjustEmergencyDisbursalBalance {
#[serde(with = "address_or_script")]
data: Adapter<Script>,
difference: i64,
},
}
mod address_or_script {
use serde::{Deserializer, Serializer};
use std::result::Result;
use super::*;
pub fn deserialize<'de, D>(deserializer: D) -> Result<Adapter<Script>, D::Error>
where
D: Deserializer<'de>,
{
let dest = String::deserialize(deserializer)?;
let script = if let Ok(addr) = bitcoin::Address::from_str(&dest) {
if !matches_bitcoin_network(&addr.network) {
return Err(serde::de::Error::custom(format!(
"Invalid network for Bitcoin dest. Got {}, Expected {}",
addr.network,
crate::bitcoin::NETWORK
)));
}
addr.script_pubkey()
} else {
bitcoin::Script::from_str(&dest)
.map_err(|e| serde::de::Error::custom("Invalid Bitcoin script"))?
};
Ok(script.into())
}
pub fn serialize<S>(script: &Adapter<Script>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Ok(addr) =
bitcoin::Address::from_script(&script.clone().into_inner(), crate::bitcoin::NETWORK)
{
addr.serialize(serializer)
} else {
script.serialize(serializer)
}
}
}
#[test]
fn dest_json() {
assert_eq!(
Dest::NativeAccount {
address: Address::NULL
}
.to_string(),
"{\"type\":\"nativeAccount\",\"address\":\"nomic1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0mn95h\"}"
);
assert_eq!(
Dest::Ibc { data: IbcDest{source_port:"transfer".try_into().unwrap(),source_channel:"channel-0".try_into().unwrap(),sender:"nomic1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0mn95h".try_into().unwrap(),receiver:"nomic1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0mn95h".try_into().unwrap(),timeout_timestamp:123_456_789,memo:"memo".try_into().unwrap(),} }
.to_string(),
"{\"type\":\"ibc\",\"data\":{\"source_port\":\"transfer\",\"source_channel\":\"channel-0\",\"receiver\":\"nomic1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0mn95h\",\"sender\":\"nomic1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0mn95h\",\"timeout_timestamp\":123456789,\"memo\":\"memo\"}}"
);
// TODO: use an eth address type
#[cfg(feature = "ethereum")]
assert_eq!(
Dest::EthAccount {
network: 123,
connection: [0; 20],
address: [0; 20],
}
.to_string(),
"{\"type\":\"ethAccount\",\"network\":123,\"connection\":\"0x0000000000000000000000000000000000000000\",\"address\":\"0x0000000000000000000000000000000000000000\"}"
);
assert_eq!(Dest::RewardPool.to_string(), "{\"type\":\"rewardPool\"}");
let out = "{\"type\":\"bitcoin\",\"data\":\"6a03010203\"}";
assert_eq!(
Dest::Bitcoin {
data: Adapter::new(Script::new_op_return(&[1, 2, 3]))
}
.to_string(),
out
);
let Dest::Bitcoin { data } = Dest::from_str(out).unwrap() else {
unreachable!();
};
assert_eq!(*data, Script::new_op_return(&[1, 2, 3]));
let addr = bitcoin::Address::p2wpkh(
&bitcoin::PublicKey::from_slice(&[2; 33]).unwrap(),
bitcoin::Network::Bitcoin,
)
.unwrap();
#[cfg(all(feature = "testnet", not(feature = "devnet")))]
let out = "{\"type\":\"bitcoin\",\"data\":\"tb1q2xq57yyxwzkw6tthcxq9mhtxxj7f63e3dgldfj\"}";
#[cfg(all(not(feature = "testnet"), not(feature = "devnet")))]
let out = "{\"type\":\"bitcoin\",\"data\":\"bc1q2xq57yyxwzkw6tthcxq9mhtxxj7f63e38wy7jp\"}";
#[cfg(all(feature = "devnet", feature = "testnet"))]
let out = "{\"type\":\"bitcoin\",\"data\":\"tb1q2xq57yyxwzkw6tthcxq9mhtxxj7f63e3dgldfj\"}";
assert_eq!(
Dest::Bitcoin {
data: Adapter::new(addr.script_pubkey())
}
.to_string(),
out
);
let Dest::Bitcoin { data } = Dest::from_str(out).unwrap() else {
unreachable!();
};
assert_eq!(*data, addr.script_pubkey());
// TODO: other Dest variants
}
impl Dest {
pub fn to_receiver_addr(&self) -> Option<String> {
Some(match self {
Dest::NativeAccount { address } => address.to_string(),
Dest::Ibc { data } => data.receiver.to_string(),
Dest::RewardPool => return None,
#[cfg(feature = "ethereum")]
Dest::EthAccount { address, .. } => hex::encode(address),
#[cfg(feature = "ethereum")]
Dest::EthCall {
contract_address, ..
} => hex::encode(contract_address),
Dest::Bitcoin { .. } => return None,
#[cfg(feature = "babylon")]
Dest::Stake { return_dest, .. } => {
let return_dest: Dest = return_dest.parse().ok()?;
return return_dest.to_receiver_addr();
}
#[cfg(feature = "babylon")]
Dest::Unstake { .. } => return None,
Dest::AdjustEmergencyDisbursalBalance { .. } => {
return None;
}
})
}
pub fn commitment_bytes(&self) -> Result<Vec<u8>> {
use sha2::{Digest, Sha256};
let bytes = self.encode()?;
let hash = Sha256::digest(bytes);
let mut bytes = Vec::with_capacity(hash.len() + 1);
bytes.push(0); // version byte
bytes.extend_from_slice(&hash);
Ok(bytes)
}
// TODO: remove once there are no legacy commitments in-flight
pub fn legacy_commitment_bytes(&self) -> Result<Vec<Vec<u8>>> {
use sha2::{Digest, Sha256};
let bytes = match self {
Dest::NativeAccount { address } => vec![address.bytes().into()],
Dest::Ibc { data } => data.legacy_encode()?,
_ => return Err(Error::App("Invalid dest for legacy commitment".to_string())),
};
Ok(bytes)
}
pub fn from_base64(s: &str) -> Result<Self> {
let bytes =
base64::decode(s).map_err(|_| Error::App("Failed to decode base64".to_string()))?;
Ok(Self::decode(&mut &bytes[..])?)
}
pub fn to_base64(&self) -> Result<String> {
let bytes = self.encode()?;
Ok(base64::encode(bytes))
}
pub fn to_output_script(
&self,
recovery_scripts: &orga::collections::Map<Address, Adapter<Script>>,
) -> Result<Option<Script>> {
match self {
Dest::NativeAccount { address: addr } => Ok(recovery_scripts
.get(*addr)?
.map(|script| script.clone().into_inner())),
// TODO
_ => Ok(None),
}
}
pub fn is_fee_exempt(&self) -> bool {
if let Dest::Ibc { data: dest } = self {
dest.is_fee_exempt()
} else {
false
}
}
}
impl std::fmt::Display for Dest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", serde_json::to_string(self).unwrap())
}
}
impl FromStr for Dest {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
serde_json::from_str(s).map_err(|e| Error::App(e.to_string()))
}
}
impl State for Dest {
fn attach(&mut self, store: Store) -> Result<()> {
Ok(())
}
fn load(_store: Store, bytes: &mut &[u8]) -> Result<Self> {
Ok(Self::decode(bytes)?)
}
fn flush<W: std::io::Write>(self, out: &mut W) -> Result<()> {
self.encode_into(out)?;
Ok(())
}
}
impl Query for Dest {
type Query = ();
fn query(&self, query: Self::Query) -> Result<()> {
Ok(())
}
}
impl Migrate for Dest {
#[allow(clippy::needless_borrows_for_generic_args)]
fn migrate(src: Store, dest: Store, bytes: &mut &[u8]) -> Result<Self> {
// TODO: !!!!!!!! remove from here once there are no legacy IBC dests
// Migrate IBC dests
let mut maybe_ibc_bytes = &mut &**bytes;
let variant = u8::decode(&mut maybe_ibc_bytes)?;
if variant == 1 {
let ibc_dest = IbcDest::migrate(src, dest, maybe_ibc_bytes)?;
return Ok(Self::Ibc { data: ibc_dest });
}
// TODO: !!!!!!!! remove to here once there are no legacy IBC dests
Self::load(src, bytes)
}
}
impl Describe for Dest {
fn describe() -> Descriptor {
::orga::describe::Builder::new::<Self>()
.meta::<()>()
.build()
}
}
impl Default for Dest {
fn default() -> Self {
Dest::NativeAccount {
address: Address::NULL,
}
}
}
#[derive(Encode, Decode, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum Identity {
#[default]
None,
NativeAccount {
address: Address,
},
#[cfg(feature = "ethereum")]
EthAccount {
network: u32,
// TODO: ethaddress type
#[serde(with = "SerHex::<StrictPfx>")]
connection: [u8; 20],
// TODO: ethaddress type
#[serde(with = "SerHex::<StrictPfx>")]
address: [u8; 20],
},
}
impl Identity {
pub fn from_signer() -> Result<Self> {
Ok(Context::resolve::<Signer>()
.ok_or_else(|| Error::Signer("No Signer context available".into()))?
.signer
.map(|address| Identity::NativeAccount { address })
.unwrap_or(Identity::None))
}
}
impl std::fmt::Display for Identity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", serde_json::to_string(self).unwrap())
}
}
impl FromStr for Identity {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
serde_json::from_str(s).map_err(|e| Error::App(e.to_string()))
}
}
impl State for Identity {
fn attach(&mut self, store: Store) -> Result<()> {
Ok(())
}
fn load(_store: Store, bytes: &mut &[u8]) -> Result<Self> {
Ok(Self::decode(bytes)?)
}
fn flush<W: std::io::Write>(self, out: &mut W) -> Result<()> {
self.encode_into(out)?;
Ok(())
}
}
impl Query for Identity {
type Query = ();
fn query(&self, query: Self::Query) -> Result<()> {
Ok(())
}
}
impl Migrate for Identity {
fn migrate(src: Store, dest: Store, bytes: &mut &[u8]) -> Result<Self> {
Self::load(src, bytes)
}
}
impl Describe for Identity {
fn describe() -> Descriptor {
::orga::describe::Builder::new::<Self>()
.meta::<()>()
.build()
}
}
pub fn ibc_fee(amount: Amount) -> Result<Amount> {
let fee_rate: orga::coins::Decimal = "0.005".parse().unwrap();
(amount * fee_rate)?.amount()
}
const REWARD_TIMER_PERIOD: i64 = 120;
#[orga]
pub struct RewardTimer {
last_period: i64,
}
impl RewardTimer {
pub fn tick(&mut self, now: i64) -> bool {
if now - self.last_period < REWARD_TIMER_PERIOD {
return false;
}
self.last_period = now;
true
}
}
pub fn in_upgrade_window(now_seconds: i64) -> bool {
#[cfg(not(feature = "testnet"))]
{
use chrono::prelude::*;
let now = Utc.timestamp_opt(now_seconds, 0).unwrap();
let valid_weekday = now.weekday().num_days_from_monday() < 5; // Monday - Friday
let valid_time = now.hour() == 17 && now.minute() < 10; // 17:00 - 17:10 UTC
valid_weekday && valid_time
}
#[cfg(feature = "testnet")]
true // No restrictions
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn upgrade_date() {
#[cfg(not(feature = "testnet"))]
{
assert!(in_upgrade_window(1690218300)); // Monday 17:05 UTC
assert!(in_upgrade_window(1690391100)); // Wednesday 17:05 UTC
assert!(!in_upgrade_window(1690392000)); // Wednesday 17:15 UTC
assert!(!in_upgrade_window(1690736700)); // Sunday 17:05 UTC
}
#[cfg(feature = "testnet")]
{
assert!(in_upgrade_window(1690218300)); // Monday 17:05 UTC
assert!(in_upgrade_window(1690391100)); // Wednesday 17:05 UTC
assert!(in_upgrade_window(1690392000)); // Wednesday 17:15 UTC
assert!(in_upgrade_window(1690736700)); // Sunday 17:05 UTC
}
}
}
================================================
FILE: src/babylon/mod.rs
================================================
use bitcoin::{
hashes::Hash,
psbt::Prevouts,
secp256k1::{schnorr, PublicKey, Secp256k1},
util::{
merkleblock::PartialMerkleTree,
sighash::SighashCache,
taproot::{TapLeafHash, TapSighashHash, TaprootBuilder, TaprootSpendInfo},
},
OutPoint, PackedLockTime, Script, Sequence, Transaction, TxIn, TxOut, Witness, XOnlyPublicKey,
};
use bitcoin_script::bitcoin_script as script;
use ed::{Decode, Encode};
use orga::{
coins::{Coin, Symbol, Take},
collections::{Deque, Map},
encoding::LengthVec,
macros::Migrate,
orga,
state::State,
};
use serde::Serialize;
use crate::{
app::{Dest, Identity},
bitcoin::{
checkpoint::{BatchType, BitcoinTx, Input},
header_queue::HeaderQueue,
Adapter, Bitcoin, Nbtc, SIGSET_THRESHOLD,
},
error::{Error, Result},
frost::Frost,
};
use crate::bitcoin::threshold_sig::Signature;
#[cfg(feature = "full")]
pub mod proto;
#[cfg(feature = "full")]
pub mod relayer;
/// The symbol for staked nBTC.
#[derive(State, Debug, Clone, Encode, Decode, Default, Migrate, Serialize)]
pub struct StakedNbtc(());
impl Symbol for StakedNbtc {
const INDEX: u8 = 22;
const NAME: &'static str = "stusat";
}
#[orga]
pub struct Babylon {
pub delegations: Map<Identity, Deque<Delegation>>,
pub staked: DelegationQueue,
pub unbonding: DelegationQueue,
pub params: Params,
}
pub type DelegationQueue = Map<(u32, Identity, u64), ()>;
#[orga]
impl Babylon {
pub fn step(&mut self, frost: &mut Frost, btc: &mut Bitcoin) -> Result<()> {
type QueueHandler = fn(&mut Delegation, &mut Frost, &mut Bitcoin, &Params) -> Result<()>;
let mut process_queue = |queue: &mut DelegationQueue,
condition: fn(u32, u32, &Params) -> bool,
handler: QueueHandler| {
let mut remove_keys = vec![];
let mut iter = queue.iter()?;
loop {
let Some(entry) = iter.next() else {
break;
};
let key = entry?.0;
let (height, owner, index) = *key;
if !condition(btc.headers.height()?, height, &self.params) {
break;
}
let mut owner_dels = self.delegations.get_mut(owner)?.ok_or_else(|| {
Error::Orga(orga::Error::App("Delegation not found".to_string()))
})?;
let mut del = owner_dels.get_mut(index)?.ok_or_else(|| {
Error::Orga(orga::Error::App("Delegation not found".to_string()))
})?;
handler(&mut del, frost, btc, &self.params)?;
remove_keys.push(*key);
}
for key in remove_keys {
queue.remove(key)?;
}
Ok::<_, crate::error::Error>(())
};
// Process unbonding queue (once timelock has passed, withdraw from unbonding
// transaction)
process_queue(
&mut self.unbonding,
|btc_height, maturity_height, _| btc_height >= maturity_height,
|del, _, btc, params| del.withdraw(btc, params),
)?;
// Process staked queue (once delegations are older than `max_age`, start
// unbonding)
process_queue(
&mut self.staked,
|btc_height, staking_height, params| btc_height >= staking_height + params.max_age,
|del, frost, btc, params| del.unbond(frost, btc, params),
)?;
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub fn stake(
&mut self,
btc: &mut crate::bitcoin::Bitcoin,
frost: &mut crate::frost::Frost,
owner: Identity,
return_dest: Dest,
finality_provider: [u8; 32],
staking_time: u16,
nbtc: Coin<Nbtc>,
) -> Result<u64> {
let Some(frost_index) = frost.most_recent_with_key()? else {
return Err(Error::Orga(orga::Error::App(
"Frost not initialized".to_string(),
)));
};
let group_pubkey = frost.group_pubkey(frost_index)?.unwrap();
let index = self.delegations.get(owner)?.unwrap_or_default().len();
let batch_index = btc
.checkpoints
.building()?
.batches
.get(BatchType::Checkpoint as u64)?
.unwrap()
.len();
let del = Delegation::new(
index,
owner,
return_dest,
PublicKey::from_slice(&group_pubkey.inner.verifying_key().serialize())?.into(),
frost_index,
vec![XOnlyPublicKey::from_slice(&finality_provider)?],
staking_time,
(btc.checkpoints.index, batch_index),
nbtc,
&self.params,
)?;
// Push staking tx to checkpoint.
let mut staking_tx = BitcoinTx::default();
staking_tx
.output
.push_back(Adapter::new(del.staking_output(&self.params)?))?;
staking_tx
.output
.push_back(Adapter::new(del.op_return_output()?))?;
btc.checkpoints
.building_mut()?
.batches
.get_mut(BatchType::Checkpoint as u64)?
.unwrap()
.push_back(staking_tx)?;
self.delegations
.entry(owner)?
.or_insert_default()?
.push_back(del)?;
Ok(index)
}
pub fn unstake(
&mut self,
owner: Identity,
index: u64,
frost: &mut Frost,
btc: &Bitcoin,
) -> Result<()> {
self.delegations
.get_mut(owner)?
.ok_or_else(|| Error::Orga(orga::Error::App("Delegation not found".to_string())))?
.get_mut(index)?
.ok_or_else(|| Error::Orga(orga::Error::App("Delegation not found".to_string())))?
.request_unbond(frost, btc, &self.params)
}
}
pub fn multisig_script(pks: &[XOnlyPublicKey], threshold: u32, verify: bool) -> Result<Script> {
if pks.is_empty() {
return Err(Error::Orga(orga::Error::App(
"No keys provided".to_string(),
)));
}
if threshold > pks.len() as u32 {
return Err(Error::Orga(orga::Error::App(
"Required number of valid signers is greater than number of provided keys".to_string(),
)));
}
if pks.len() == 1 {
return Ok(single_key_script(pks[0], verify));
}
let pks = sort_keys(pks)?;
let mut bytes = vec![];
for (i, pk) in pks.iter().enumerate() {
let pk = pk.serialize().to_vec();
bytes.extend(
if i == 0 {
// TODO: put this allow in the bitcoin_script crate
#[allow(clippy::redundant_closure_call)]
{
script! { <pk> OP_CHECKSIG }
}
} else {
// TODO: put this allow in the bitcoin_script crate
#[allow(clippy::redundant_closure_call)]
{
script! { <pk> OP_CHECKSIGADD }
}
}
.into_bytes(),
);
}
// TODO: put this allow in the bitcoin_script crate
#[allow(clippy::redundant_closure_call)]
{
bytes.extend(script! { <threshold as i64> }.into_bytes());
}
if verify {
// TODO: put this allow in the bitcoin_script crate
#[allow(clippy::redundant_closure_call)]
{
bytes.extend(script! { OP_NUMEQUALVERIFY }.into_bytes());
}
} else {
// TODO: put this allow in the bitcoin_script crate
#[allow(clippy::redundant_closure_call)]
{
bytes.extend(script! { OP_NUMEQUAL }.into_bytes());
}
}
Ok(bytes.into())
}
pub fn sort_keys(pks: &[XOnlyPublicKey]) -> Result<Vec<XOnlyPublicKey>> {
if pks.len() < 2 {
return Err(Error::Orga(orga::Error::App(
"Cannot sort less than two keys".to_string(),
)));
}
let mut pks = pks.to_vec();
pks.sort_by_key(|pk| pk.serialize());
for i in 0..pks.len() - 1 {
if pks[i] == pks[i + 1] {
return Err(Error::Orga(orga::Error::App(
"Duplicate key in list of keys".to_string(),
)));
}
}
Ok(pks)
}
pub fn single_key_script(pk: XOnlyPublicKey, verify: bool) -> Script {
let pk = pk.serialize().to_vec();
if verify {
// TODO: put this allow in the bitcoin_script crate
#[allow(clippy::redundant_closure_call)]
{
script! { <pk> OP_CHECKSIGVERIFY }
}
} else {
// TODO: put this allow in the bitcoin_script crate
#[allow(clippy::redundant_closure_call)]
{
script! { <pk> OP_CHECKSIG }
}
}
}
pub fn timelock_script(pk: XOnlyPublicKey, timelock: u64) -> Script {
let mut bytes = single_key_script(pk, true).into_bytes();
// TODO: put this allow in the bitcoin_script crate
#[allow(clippy::redundant_closure_call)]
bytes.extend(script! { <timelock as i64> OP_CSV }.into_bytes());
bytes.into()
}
pub fn aggregate_scripts(scripts: &[Script]) -> Script {
let mut bytes = vec![];
for script in scripts.iter() {
bytes.extend(script.clone().into_bytes());
}
bytes.into()
}
#[orga(skip(Default))]
#[derive(Debug, Clone)]
pub struct Params {
pub covenant_keys: LengthVec<u8, [u8; 32]>,
pub covenant_quorum: u32,
pub slashing_script: Adapter<Script>,
pub slashing_min_fee: u64,
pub op_return_tag: [u8; 4],
pub slashing_rate: (u32, u32),
pub max_age: u32,
pub min_staking_time: u16,
pub max_staking_time: u16,
pub unbonding_time: u16,
pub min_staking_amount: u64,
pub max_staking_amount: u64,
pub unbonding_fee: u64,
pub confirmation_depth: u32,
}
impl Params {
pub fn bbn_test_3() -> Self {
let covenant_keys = [
"ffeaec52a9b407b355ef6967a7ffc15fd6c3fe07de2844d61550475e7a5233e5",
"a5c60c2188e833d39d0fa798ab3f69aa12ed3dd2f3bad659effa252782de3c31",
"59d3532148a597a2d05c0395bf5f7176044b1cd312f37701a9b4d0aad70bc5a4",
"57349e985e742d5131e1e2b227b5170f6350ac2e2feb72254fcc25b3cee21a18",
"c8ccb03c379e452f10c81232b41a1ca8b63d0baf8387e57d302c987e5abb8527",
];
let covenant_quorum = 3;
let slashing_addr = "tb1qv03wm7hxhag6awldvwacy0z42edtt6kwljrhd9";
let slashing_min_fee = 1_000;
Self {
covenant_keys: covenant_keys
.iter()
.map(|k| {
let mut key = [0; 32];
let v = hex::decode(k).unwrap();
key.copy_from_slice(&v);
key
})
.collect::<Vec<_>>()
.try_into()
.unwrap(),
covenant_quorum,
slashing_script: slashing_addr
.parse::<bitcoin::Address>()
.unwrap()
.script_pubkey()
.into(),
slashing_min_fee,
op_return_tag: *b"bbb3",
slashing_rate: (11, 100),
max_age: 1_008,
min_staking_time: u16::MAX,
max_staking_time: 1,
unbonding_time: 5,
min_staking_amount: 50_000,
max_staking_amount: 5_000_000,
unbonding_fee: 1_000,
confirmation_depth: 10,
}
}
pub fn bbn_test_4() -> Self {
let covenant_keys = [
"a10a06bb3bae360db3aef0326413b55b9e46bf20b9a96fc8a806a99e644fe277",
"6f13a6d104446520d1757caec13eaf6fbcf29f488c31e0107e7351d4994cd068",
"a5e21514682b87e37fb5d3c9862055041d1e6f4cc4f3034ceaf3d90f86b230a6",
];
let covenant_quorum = 2;
let slashing_addr = "tb1qv03wm7hxhag6awldvwacy0z42edtt6kwljrhd9";
let slashing_min_fee = 2_000;
Self {
covenant_keys: covenant_keys
.iter()
.map(|k| {
let mut key = [0; 32];
let v = hex::decode(k).unwrap();
key.copy_from_slice(&v);
key
})
.collect::<Vec<_>>()
.try_into()
.unwrap(),
covenant_quorum,
slashing_script: slashing_addr
.parse::<bitcoin::Address>()
.unwrap()
.script_pubkey()
.into(),
slashing_min_fee,
op_return_tag: *b"bbb4",
slashing_rate: (11, 100),
max_age: 1_008,
min_staking_time: 64_000,
max_staking_time: 64_000,
unbonding_time: 1_008,
gitextract_c0qz_ec1/
├── .github/
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
├── SECURITY.md
├── build.rs
├── build.sh
├── genesis/
│ ├── stakenet-2.json
│ ├── stakenet-3.json
│ ├── testnet-4.json
│ └── testnet-4d.json
├── networks/
│ ├── stakenet.toml
│ └── testnet.toml
├── rest/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── rust-toolchain
├── rustfmt.toml
├── src/
│ ├── airdrop.rs
│ ├── app/
│ │ └── migrations.rs
│ ├── app.rs
│ ├── babylon/
│ │ ├── mod.rs
│ │ ├── proto/
│ │ │ ├── babylon/
│ │ │ │ ├── btccheckpoint/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── btccheckpoint.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── btclightclient/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── btclightclient.proto
│ │ │ │ │ ├── event.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── btcstaking/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── btcstaking.proto
│ │ │ │ │ ├── events.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── incentive.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── pop.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── checkpointing/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── bls_key.proto
│ │ │ │ │ ├── checkpoint.proto
│ │ │ │ │ ├── events.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── epoching/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── epoching.proto
│ │ │ │ │ ├── events.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── finality/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── events.proto
│ │ │ │ │ ├── finality.proto
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── incentive/
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ ├── incentive.proto
│ │ │ │ │ ├── params.proto
│ │ │ │ │ ├── query.proto
│ │ │ │ │ └── tx.proto
│ │ │ │ ├── monitor/
│ │ │ │ │ └── v1/
│ │ │ │ │ ├── genesis.proto
│ │ │ │ │ └── query.proto
│ │ │ │ └── zoneconcierge/
│ │ │ │ └── v1/
│ │ │ │ ├── genesis.proto
│ │ │ │ ├── packet.proto
│ │ │ │ ├── params.proto
│ │ │ │ ├── query.proto
│ │ │ │ ├── tx.proto
│ │ │ │ └── zoneconcierge.proto
│ │ │ ├── btccheckpoint.rs
│ │ │ ├── buf.gen.yaml
│ │ │ ├── buf.yaml
│ │ │ ├── gen/
│ │ │ │ ├── babylon.btccheckpoint.v1.rs
│ │ │ │ ├── babylon.btclightclient.v1.rs
│ │ │ │ ├── babylon.btcstaking.v1.rs
│ │ │ │ ├── babylon.checkpointing.v1.rs
│ │ │ │ ├── babylon.epoching.v1.rs
│ │ │ │ ├── babylon.finality.v1.rs
│ │ │ │ ├── babylon.incentive.rs
│ │ │ │ ├── babylon.monitor.v1.rs
│ │ │ │ └── babylon.zoneconcierge.v1.rs
│ │ │ └── mod.rs
│ │ └── relayer.rs
│ ├── bin/
│ │ ├── create-checkpoint.rs
│ │ ├── eth-bootstrap.rs
│ │ ├── get-reserve-scripts.rs
│ │ └── nomic.rs
│ ├── bitcoin/
│ │ ├── adapter.rs
│ │ ├── checkpoint.json
│ │ ├── checkpoint.rs
│ │ ├── deposit_index.rs
│ │ ├── header_queue.rs
│ │ ├── mod.rs
│ │ ├── outpoint_set.rs
│ │ ├── recovery.rs
│ │ ├── relayer.rs
│ │ ├── signatory.rs
│ │ ├── signer.rs
│ │ ├── signet_checkpoint.json
│ │ ├── testnet_checkpoint.json
│ │ └── threshold_sig.rs
│ ├── cosmos.rs
│ ├── error.rs
│ ├── ethereum/
│ │ ├── bootstrap/
│ │ │ └── sepolia.json
│ │ ├── consensus/
│ │ │ ├── mod.rs
│ │ │ ├── relayer.rs
│ │ │ └── test_fixtures.json
│ │ ├── contracts/
│ │ │ ├── Babylon.json
│ │ │ ├── Babylon.sol
│ │ │ ├── CosmosERC20.json
│ │ │ ├── CosmosToken.sol
│ │ │ ├── Nomic.json
│ │ │ └── Nomic.sol
│ │ ├── mod.rs
│ │ ├── proofs.rs
│ │ ├── relayer.rs
│ │ └── signer.rs
│ ├── frost/
│ │ ├── dkg.rs
│ │ ├── encoding.rs
│ │ ├── mod.rs
│ │ ├── signer.rs
│ │ └── signing.rs
│ ├── incentives.rs
│ ├── lib.rs
│ ├── network.rs
│ └── utils.rs
├── stakenet_reserve_scripts.csv
├── testnet_addresses.csv
├── tests/
│ ├── bitcoin.rs
│ ├── data/
│ │ └── block-data
│ ├── header_queue.rs
│ ├── ibc.rs
│ ├── node.rs
│ ├── node_spawn.rs
│ └── relayer.rs
└── wasm/
├── Cargo.toml
├── index.html
└── src/
├── error.rs
├── lib.rs
├── types.rs
└── web_client.rs
SYMBOL INDEX (1716 symbols across 60 files)
FILE: build.rs
function main (line 1) | fn main() {
FILE: rest/src/main.rs
function app_host (line 41) | fn app_host() -> &'static str {
function app_client (line 45) | fn app_client() -> AppClient<InnerApp, InnerApp, HttpClient, Nom, Unsign...
function validators (line 63) | async fn validators(status: Option<String>) -> Value {
function validator (line 145) | async fn validator(address: &str) -> Value {
function bank_balances (line 220) | async fn bank_balances(address: &str) -> Result<Value, BadRequest<String...
function bank_balances_2 (line 253) | async fn bank_balances_2(address: &str) -> Result<Value, BadRequest<Stri...
function auth_accounts (line 274) | async fn auth_accounts(addr_str: &str) -> Result<Value, BadRequest<Strin...
function auth_accounts2 (line 308) | async fn auth_accounts2(addr_str: &str) -> Result<Value, BadRequest<Stri...
type TxRequest (line 339) | struct TxRequest {
function txs (line 345) | async fn txs(tx: &str) -> Result<Value, BadRequest<String>> {
type TxRequest2 (line 385) | struct TxRequest2 {
function txs2 (line 391) | async fn txs2(tx: &str) -> Result<Value, BadRequest<String>> {
function time_now (line 430) | fn time_now() -> u64 {
function query (line 438) | async fn query(query: &str, height: Option<u32>) -> Result<String, BadRe...
function staking_delegators_delegations (line 482) | async fn staking_delegators_delegations(address: &str) -> Value {
function staking_delegators_delegations_2 (line 517) | async fn staking_delegators_delegations_2(address: &str) -> Result<Value...
function staking_delegators_unbonding_delegations (line 544) | async fn staking_delegators_unbonding_delegations(address: &str) -> Value {
function staking_delegators_unbonding_delegations_2 (line 583) | fn staking_delegators_unbonding_delegations_2(_address: &str) -> Value {
function staking_validators_delegations (line 588) | async fn staking_validators_delegations(address: &str) -> Value {
function staking_validator_single_delegation (line 622) | async fn staking_validator_single_delegation(
function staking_validators_unbonding_delegations (line 656) | async fn staking_validators_unbonding_delegations(address: &str) -> Value {
function distribution_delegators_rewards (line 694) | async fn distribution_delegators_rewards(address: &str) -> Value {
function distribution_validator_commission (line 761) | async fn distribution_validator_commission(address: &str) -> Value {
function distribution_delegators_rewards_for_validator (line 770) | async fn distribution_delegators_rewards_for_validator(
function minting_inflation (line 822) | async fn minting_inflation() -> Result<Value, BadRequest<String>> {
function minting_inflation_2 (line 842) | async fn minting_inflation_2() -> Result<Value, BadRequest<String>> {
function bank_total (line 862) | fn bank_total(denom: &str) -> Value {
function staking_pool (line 867) | async fn staking_pool() -> Value {
function bank_supply_unom (line 894) | async fn bank_supply_unom() -> Value {
function bank_supply (line 906) | async fn bank_supply() -> Value {
function staking_pool_2 (line 924) | fn staking_pool_2() -> Value {
function ibc_apps_transfer_params (line 936) | fn ibc_apps_transfer_params() -> Value {
function ibc_applications_transfer_params (line 946) | fn ibc_applications_transfer_params() -> Value {
function staking_params (line 956) | async fn staking_params() -> Value {
function slashing_params (line 974) | async fn slashing_params() -> Value {
function get_signing_infos (line 1003) | async fn get_signing_infos() -> Vec<Value> {
function signing_infos (line 1070) | async fn signing_infos() -> Value {
function signing_info (line 1083) | async fn signing_info(cons_addr: &str) -> Value {
function parse_block (line 1096) | fn parse_block(res: tendermint_rpc::endpoint::block::Response) -> Value {
function latest_block (line 1151) | async fn latest_block() -> Value {
function block (line 1159) | async fn block(height: u32) -> Value {
function parse_validator_set (line 1170) | fn parse_validator_set(res: tendermint_rpc::endpoint::validators::Respon...
function latest_validator_set (line 1198) | async fn latest_validator_set() -> Value {
function validator_set (line 1212) | async fn validator_set(height: u32) -> Value {
function community_pool (line 1224) | async fn community_pool() -> Value {
function proposals (line 1241) | fn proposals() -> Value {
function ibc_connection_client_state (line 1253) | async fn ibc_connection_client_state(connection: &str) -> Value {
function ibc_connection_channels (line 1331) | async fn ibc_connection_channels(connection: &str) -> Value {
function ibc_connection (line 1377) | async fn ibc_connection(connection: &str) -> Value {
function ibc_connections (line 1412) | async fn ibc_connections() -> Value {
type CORS (line 1435) | pub struct CORS;
method info (line 1439) | fn info(&self) -> Info {
method on_response (line 1446) | async fn on_response<'r>(&self, _request: &'r Request<'_>, response: &mu...
function rocket (line 1458) | fn rocket() -> _ {
FILE: src/airdrop.rs
constant MAX_STAKED (line 19) | const MAX_STAKED: u64 = 1_000_000_000;
constant AIRDROP_II_TOTAL (line 22) | const AIRDROP_II_TOTAL: u64 = 3_500_000_000_000;
type Airdrop (line 26) | pub struct Airdrop {
method get (line 42) | pub fn get(&self, address: Address) -> Result<Option<Account>> {
method get_mut (line 47) | pub fn get_mut(&mut self, address: Address) -> Result<Option<ChildMut<...
method signer_acct_mut (line 53) | pub fn signer_acct_mut(&mut self) -> Result<ChildMut<Address, Account>> {
method pay_as_funding (line 66) | fn pay_as_funding(&mut self, amount: u64) -> Result<()> {
method claim_airdrop1 (line 76) | pub fn claim_airdrop1(&mut self) -> Result<()> {
method claim_airdrop2 (line 85) | pub fn claim_airdrop2(&mut self) -> Result<()> {
method join_accounts (line 95) | pub fn join_accounts(&mut self, dest_addr: Address) -> Result<()> {
method init_from_airdrop2_csv (line 130) | pub fn init_from_airdrop2_csv(&mut self, data: &[u8]) -> Result<()> {
method airdrop_to (line 200) | fn airdrop_to(
method score (line 217) | fn score(staked: u64, _count: u64) -> u64 {
method get_recipients_from_csv (line 223) | fn get_recipients_from_csv(data: &[u8]) -> Recipients {
method init_airdrop1_amount (line 253) | fn init_airdrop1_amount(
method init_from_airdrop1_csv (line 275) | pub fn init_from_airdrop1_csv(&mut self, data: &[u8]) -> Result<()> {
method migrate_from (line 31) | fn migrate_from(_value: AirdropV0) -> Result<Self> {
type Recipients (line 36) | type Recipients = Vec<(Address, Vec<(u64, u64)>, u64)>;
type Account (line 312) | pub struct Account {
method is_empty (line 326) | pub fn is_empty(&self) -> bool {
method migrate_from (line 332) | fn migrate_from(_value: AccountV1) -> Result<Self> {
type Part (line 341) | pub struct Part {
method unlock (line 355) | pub fn unlock(&mut self) {
method claim (line 362) | pub fn claim(&mut self) -> Result<u64> {
method is_empty (line 375) | pub fn is_empty(&self) -> bool {
method total (line 380) | pub fn total(&self) -> u64 {
function assert_approx_eq (line 393) | fn assert_approx_eq(a: u64, b: u64) {
function amount_airdropped (line 398) | fn amount_airdropped(acct: &Account) -> u64 {
function airdrop_allocation_no_testnet (line 404) | fn airdrop_allocation_no_testnet() {
function airdrop_allocation (line 422) | fn airdrop_allocation() {
function airdrop_allocation_multiple (line 440) | fn airdrop_allocation_multiple() {
FILE: src/app.rs
type App (line 71) | pub type App = DefaultPlugins<Nom, InnerApp>;
type Nom (line 75) | pub struct Nom(());
constant INDEX (line 77) | const INDEX: u8 = 69;
constant NAME (line 78) | const NAME: &'static str = "unom";
constant DEV_ADDRESS (line 84) | const DEV_ADDRESS: &str = "nomic14z79y3yrghqx493mwgcj0qd2udy6lm26lmduah";
constant STRATEGIC_RESERVE_ADDRESS (line 88) | const STRATEGIC_RESERVE_ADDRESS: &str = "nomic1d5n325zrf4elfu0heqd59gna5...
constant VALIDATOR_BOOTSTRAP_ADDRESS (line 93) | const VALIDATOR_BOOTSTRAP_ADDRESS: &str = "nomic1fd9mxxt84lw3jdcsmjh6jy8...
constant IBC_FEE_USATS (line 97) | const IBC_FEE_USATS: u64 = 1_000_000;
constant CALL_FEE_USATS (line 100) | const CALL_FEE_USATS: u64 = 100_000_000;
constant ETH_CREATE_CONNECTION_FEE_USATS (line 105) | const ETH_CREATE_CONNECTION_FEE_USATS: u64 = 10_000_000_000;
constant OSMOSIS_CHANNEL_ID (line 107) | pub const OSMOSIS_CHANNEL_ID: &str = "channel-1";
constant FROST_GROUP_INTERVAL (line 110) | const FROST_GROUP_INTERVAL: i64 = 10 * 60;
constant FROST_TOP_N (line 112) | const FROST_TOP_N: u16 = 5;
constant FROST_THRESHOLD (line 114) | const FROST_THRESHOLD: u16 = 3;
type InnerApp (line 119) | pub struct InnerApp {
constant CONSENSUS_VERSION (line 205) | pub const CONSENSUS_VERSION: u8 = 14;
method configure_faucets (line 208) | fn configure_faucets(&mut self) -> Result<()> {
method deposit_rewards (line 254) | pub fn deposit_rewards(&mut self) -> Result<()> {
method ibc_transfer_nbtc (line 261) | pub fn ibc_transfer_nbtc(&mut self, dest: IbcDest, amount: Amount) -> ...
method ibc_withdraw_nbtc (line 285) | pub fn ibc_withdraw_nbtc(&mut self, amount: Amount) -> Result<()> {
method eth_transfer_nbtc (line 299) | pub fn eth_transfer_nbtc(
method total_supply (line 333) | pub fn total_supply(&self) -> Result<Amount> {
method escrowed_nbtc (line 351) | pub fn escrowed_nbtc(&self, address: Address) -> Result<Amount> {
method claim_escrowed_nbtc (line 356) | pub fn claim_escrowed_nbtc(&mut self) -> Result<()> {
method relay_deposit (line 363) | pub fn relay_deposit(
method relay_op_key (line 388) | pub fn relay_op_key(
method validate_dest (line 403) | pub fn validate_dest(&self, dest: &Dest, amount: Amount, sender: Ident...
method try_credit_dest (line 481) | fn try_credit_dest(
method credit_dest (line 542) | fn credit_dest(&mut self, dest: Dest, nbtc: Coin<Nbtc>, sender: Identi...
method withdraw_nbtc (line 621) | pub fn withdraw_nbtc(
method join_accounts (line 630) | fn join_accounts(&mut self, dest_addr: Address) -> Result<()> {
method signer (line 639) | fn signer(&mut self) -> Result<Address> {
method signal (line 647) | pub fn signal(&mut self, version: Version) -> Result<()> {
method ibc_deliver (line 652) | pub fn ibc_deliver(&mut self, messages: RawIbcTx) -> Result<()> {
method declare_with_nbtc (line 687) | pub fn declare_with_nbtc(&mut self, declaration: Declaration) -> Resul...
method pay_nbtc_fee (line 694) | pub fn pay_nbtc_fee(&mut self) -> Result<()> {
method deduct_nbtc_fee (line 698) | fn deduct_nbtc_fee(&mut self, amount: Amount) -> Result<()> {
method height (line 707) | pub fn height(&self) -> u64 {
method stake_nbtc (line 712) | pub fn stake_nbtc(
method relay_btc_staking_tx (line 745) | pub fn relay_btc_staking_tx(
method relay_btc_unbonding_tx (line 787) | pub fn relay_btc_unbonding_tx(
method eth_create_connection (line 825) | pub fn eth_create_connection(
method app_noop (line 853) | pub fn app_noop(&mut self) -> Result<()> {
method app_noop_query (line 858) | pub fn app_noop_query(&self) -> Result<()> {
method step_frost (line 863) | fn step_frost(&mut self, now: i64) -> Result<()> {
method init_chain (line 904) | fn init_chain(&mut self, _ctx: &InitChainCtx) -> Result<()> {
method begin_block (line 964) | fn begin_block(&mut self, ctx: &BeginBlockCtx) -> Result<()> {
method end_block (line 1043) | fn end_block(&mut self, ctx: &EndBlockCtx) -> Result<()> {
method abci_query (line 1049) | fn abci_query(&self, request: &messages::RequestQuery) -> Result<message...
type Output (line 1056) | type Output = PaidCall<<Self as Call>::Call>;
method convert (line 1058) | fn convert(&self, sdk_tx: &SdkTx) -> Result<PaidCall<<Self as Call>::Cal...
type MsgWithdraw (line 1595) | pub struct MsgWithdraw {
type MsgIbcTransfer (line 1601) | pub struct MsgIbcTransfer {
type IbcDest (line 1615) | pub struct IbcDest {
method transfer (line 1625) | pub fn transfer(
method sender_address (line 1662) | pub fn sender_address(&self) -> Result<Address> {
method sender_signer (line 1669) | pub fn sender_signer(&self) -> Result<IbcSigner> {
method receiver_signer (line 1673) | pub fn receiver_signer(&self) -> Result<IbcSigner> {
method source_channel (line 1677) | pub fn source_channel(&self) -> Result<ChannelId> {
method source_port (line 1684) | pub fn source_port(&self) -> Result<PortId> {
method memo (line 1691) | pub fn memo(&self) -> Result<Memo> {
method is_fee_exempt (line 1695) | pub fn is_fee_exempt(&self) -> bool {
method validate (line 1700) | pub fn validate(&self) -> Result<()> {
method legacy_encode (line 1708) | pub fn legacy_encode(&self) -> Result<Vec<Vec<u8>>> {
method migrate (line 1743) | fn migrate(_src: Store, _dest: Store, mut bytes: &mut &[u8]) -> Result<S...
type Dest (line 1764) | pub enum Dest {
method to_receiver_addr (line 1935) | pub fn to_receiver_addr(&self) -> Option<String> {
method commitment_bytes (line 1960) | pub fn commitment_bytes(&self) -> Result<Vec<u8>> {
method legacy_commitment_bytes (line 1973) | pub fn legacy_commitment_bytes(&self) -> Result<Vec<Vec<u8>>> {
method from_base64 (line 1984) | pub fn from_base64(s: &str) -> Result<Self> {
method to_base64 (line 1990) | pub fn to_base64(&self) -> Result<String> {
method to_output_script (line 1995) | pub fn to_output_script(
method is_fee_exempt (line 2008) | pub fn is_fee_exempt(&self) -> bool {
method fmt (line 2018) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
function deserialize (line 1827) | pub fn deserialize<'de, D>(deserializer: D) -> Result<Adapter<Script>, D...
function serialize (line 1849) | pub fn serialize<S>(script: &Adapter<Script>, serializer: S) -> Result<S...
function dest_json (line 1864) | fn dest_json() {
type Err (line 2024) | type Err = Error;
method from_str (line 2026) | fn from_str(s: &str) -> Result<Self> {
method attach (line 2032) | fn attach(&mut self, store: Store) -> Result<()> {
method load (line 2036) | fn load(_store: Store, bytes: &mut &[u8]) -> Result<Self> {
method flush (line 2040) | fn flush<W: std::io::Write>(self, out: &mut W) -> Result<()> {
type Query (line 2047) | type Query = ();
method query (line 2049) | fn query(&self, query: Self::Query) -> Result<()> {
method migrate (line 2056) | fn migrate(src: Store, dest: Store, bytes: &mut &[u8]) -> Result<Self> {
method describe (line 2072) | fn describe() -> Descriptor {
method default (line 2080) | fn default() -> Self {
type Identity (line 2089) | pub enum Identity {
method from_signer (line 2108) | pub fn from_signer() -> Result<Self> {
method fmt (line 2118) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type Err (line 2124) | type Err = Error;
method from_str (line 2126) | fn from_str(s: &str) -> Result<Self> {
method attach (line 2132) | fn attach(&mut self, store: Store) -> Result<()> {
method load (line 2136) | fn load(_store: Store, bytes: &mut &[u8]) -> Result<Self> {
method flush (line 2140) | fn flush<W: std::io::Write>(self, out: &mut W) -> Result<()> {
type Query (line 2147) | type Query = ();
method query (line 2149) | fn query(&self, query: Self::Query) -> Result<()> {
method migrate (line 2155) | fn migrate(src: Store, dest: Store, bytes: &mut &[u8]) -> Result<Self> {
method describe (line 2161) | fn describe() -> Descriptor {
function ibc_fee (line 2168) | pub fn ibc_fee(amount: Amount) -> Result<Amount> {
constant REWARD_TIMER_PERIOD (line 2173) | const REWARD_TIMER_PERIOD: i64 = 120;
type RewardTimer (line 2176) | pub struct RewardTimer {
method tick (line 2181) | pub fn tick(&mut self, now: i64) -> bool {
function in_upgrade_window (line 2191) | pub fn in_upgrade_window(now_seconds: i64) -> bool {
function upgrade_date (line 2210) | fn upgrade_date() {
FILE: src/app/migrations.rs
method migrate_from (line 31) | fn migrate_from(mut other: InnerAppV5) -> Result<Self> {
method migrate_from (line 91) | fn migrate_from(other: InnerAppV6) -> Result<Self> {
FILE: src/babylon/mod.rs
type StakedNbtc (line 44) | pub struct StakedNbtc(());
constant INDEX (line 46) | const INDEX: u8 = 22;
constant NAME (line 47) | const NAME: &'static str = "stusat";
type Babylon (line 51) | pub struct Babylon {
method step (line 62) | pub fn step(&mut self, frost: &mut Frost, btc: &mut Bitcoin) -> Result...
method stake (line 117) | pub fn stake(
method unstake (line 179) | pub fn unstake(
type DelegationQueue (line 58) | pub type DelegationQueue = Map<(u32, Identity, u64), ()>;
function multisig_script (line 195) | pub fn multisig_script(pks: &[XOnlyPublicKey], threshold: u32, verify: b...
function sort_keys (line 256) | pub fn sort_keys(pks: &[XOnlyPublicKey]) -> Result<Vec<XOnlyPublicKey>> {
function single_key_script (line 277) | pub fn single_key_script(pk: XOnlyPublicKey, verify: bool) -> Script {
function timelock_script (line 294) | pub fn timelock_script(pk: XOnlyPublicKey, timelock: u64) -> Script {
function aggregate_scripts (line 302) | pub fn aggregate_scripts(scripts: &[Script]) -> Script {
type Params (line 312) | pub struct Params {
method bbn_test_3 (line 330) | pub fn bbn_test_3() -> Self {
method bbn_test_4 (line 375) | pub fn bbn_test_4() -> Self {
method covenant_keys (line 418) | pub fn covenant_keys(&self) -> Vec<XOnlyPublicKey> {
method default (line 427) | fn default() -> Self {
function unbonding_script (line 432) | pub fn unbonding_script(staker_key: XOnlyPublicKey, params: &Params) -> ...
function slashing_script (line 439) | pub fn slashing_script(
constant UNSPENDABLE_KEY (line 451) | const UNSPENDABLE_KEY: &str = "50929b74c1a04954b78b4b6035e97a5e078a5a0f2...
function staking_taproot (line 453) | pub fn staking_taproot(
function slashing_tx (line 472) | pub fn slashing_tx(
function unbonding_taproot (line 511) | pub fn unbonding_taproot(
function unbonding_tx (line 527) | pub fn unbonding_tx(
type XOnlyPubkey (line 556) | pub type XOnlyPubkey = [u8; 32];
function bytes_to_pubkey (line 558) | fn bytes_to_pubkey(bytes: XOnlyPubkey) -> Result<XOnlyPublicKey> {
type DelegationStatus (line 563) | pub enum DelegationStatus {
type Delegation (line 574) | pub struct Delegation {
method new (line 605) | pub fn new(
method btc_key (line 644) | fn btc_key(&self) -> Result<XOnlyPublicKey> {
method fp_keys (line 648) | fn fp_keys(&self) -> Result<Vec<XOnlyPublicKey>> {
method stake_sats (line 652) | pub fn stake_sats(&self) -> u64 {
method relay_staking_tx (line 658) | pub fn relay_staking_tx(
method request_unbond (line 742) | pub fn request_unbond(
method unbond (line 779) | pub fn unbond(&mut self, frost: &mut Frost, btc: &Bitcoin, params: &Pa...
method sign_unbond (line 807) | pub fn sign_unbond(
method relay_unbonding_tx (line 845) | pub fn relay_unbonding_tx(
method can_withdraw (line 906) | pub fn can_withdraw(&self, btc: &Bitcoin) -> Result<bool> {
method withdraw (line 912) | pub fn withdraw(&mut self, btc: &mut Bitcoin, params: &Params) -> Resu...
method status (line 969) | pub fn status(&self) -> DelegationStatus {
method staking_output (line 990) | pub fn staking_output(&self, params: &Params) -> Result<TxOut> {
method op_return_output (line 997) | pub fn op_return_output(&self) -> Result<TxOut> {
method staking_taproot (line 1004) | pub fn staking_taproot(&self, params: &Params) -> Result<TaprootSpendI...
method staking_script (line 1013) | pub fn staking_script(&self, params: &Params) -> Result<Script> {
method unbonding_tx (line 1018) | pub fn unbonding_tx(&self, params: &Params) -> Result<Transaction> {
method slashing_tx (line 1030) | pub fn slashing_tx(&self) -> Result<Transaction> {
method unbonding_slashing_tx (line 1041) | pub fn unbonding_slashing_tx(&self, params: &Params) -> Result<Transac...
method staking_timelock_sighash (line 1054) | pub fn staking_timelock_sighash(
method staking_unbonding_sighash (line 1075) | pub fn staking_unbonding_sighash(&self, params: &Params) -> Result<Tap...
method staking_slashing_sighash (line 1092) | pub fn staking_slashing_sighash(&self, params: &Params) -> Result<TapS...
method unbonding_withdrawal_sighash (line 1109) | pub fn unbonding_withdrawal_sighash(&self, params: &Params) -> Result<...
method op_return_bytes (line 1124) | pub fn op_return_bytes(&self) -> Result<Vec<u8>> {
method unbonding_withdrawal_tx (line 1139) | pub fn unbonding_withdrawal_tx(&self, params: &Params) -> Result<Trans...
type OpReturnData (line 1173) | pub struct OpReturnData {
function staking_output_fixture (line 1195) | fn staking_output_fixture() {
function slashing_tx_fixture (line 1217) | fn slashing_tx_fixture() {
function unbonding_tx_fixture (line 1242) | fn unbonding_tx_fixture() {
function delegation (line 1282) | fn delegation() -> Result<()> {
function op_return_fixture (line 1399) | fn op_return_fixture() {
function delegation_fixture (line 1420) | fn delegation_fixture() {
FILE: src/babylon/proto/btccheckpoint.rs
type BtcSpvProof (line 19) | pub struct BtcSpvProof {
type TransactionKey (line 43) | pub struct TransactionKey {
type SubmissionKey (line 58) | pub struct SubmissionKey {
type TransactionInfo (line 69) | pub struct TransactionInfo {
type SubmissionData (line 93) | pub struct SubmissionData {
type EpochData (line 113) | pub struct EpochData {
type CheckpointAddresses (line 126) | pub struct CheckpointAddresses {
type BtcCheckpointInfo (line 141) | pub struct BtcCheckpointInfo {
type BtcStatus (line 162) | pub enum BtcStatus {
method as_str_name (line 179) | pub fn as_str_name(&self) -> &'static str {
method from_str_name (line 187) | pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
type Params (line 199) | pub struct Params {
type GenesisState (line 221) | pub struct GenesisState {
type QueryParamsRequest (line 228) | pub struct QueryParamsRequest {}
type QueryParamsResponse (line 232) | pub struct QueryParamsResponse {
type QueryBtcCheckpointInfoRequest (line 241) | pub struct QueryBtcCheckpointInfoRequest {
type QueryBtcCheckpointInfoResponse (line 251) | pub struct QueryBtcCheckpointInfoResponse {
type QueryBtcCheckpointsInfoRequest (line 259) | pub struct QueryBtcCheckpointsInfoRequest {
type QueryBtcCheckpointsInfoResponse (line 269) | pub struct QueryBtcCheckpointsInfoResponse {
type QueryEpochSubmissionsRequest (line 281) | pub struct QueryEpochSubmissionsRequest {
type QueryEpochSubmissionsResponse (line 290) | pub struct QueryEpochSubmissionsResponse {
type BtcCheckpointInfoResponse (line 300) | pub struct BtcCheckpointInfoResponse {
type TransactionInfoResponse (line 326) | pub struct TransactionInfoResponse {
type CheckpointAddressesResponse (line 345) | pub struct CheckpointAddressesResponse {
type SubmissionKeyResponse (line 364) | pub struct SubmissionKeyResponse {
type MsgInsertBtcSpvProof (line 380) | pub struct MsgInsertBtcSpvProof {
type MsgInsertBtcSpvProofResponse (line 390) | pub struct MsgInsertBtcSpvProofResponse {}
type MsgUpdateParams (line 394) | pub struct MsgUpdateParams {
type MsgUpdateParamsResponse (line 410) | pub struct MsgUpdateParamsResponse {}
FILE: src/babylon/proto/gen/babylon.btccheckpoint.v1.rs
type BtcSpvProof (line 19) | pub struct BtcSpvProof {
type TransactionKey (line 43) | pub struct TransactionKey {
type SubmissionKey (line 58) | pub struct SubmissionKey {
type TransactionInfo (line 69) | pub struct TransactionInfo {
type SubmissionData (line 93) | pub struct SubmissionData {
type EpochData (line 112) | pub struct EpochData {
type CheckpointAddresses (line 125) | pub struct CheckpointAddresses {
type BtcCheckpointInfo (line 140) | pub struct BtcCheckpointInfo {
type BtcStatus (line 161) | pub enum BtcStatus {
method as_str_name (line 177) | pub fn as_str_name(&self) -> &'static str {
method from_str_name (line 185) | pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
type Params (line 197) | pub struct Params {
type GenesisState (line 219) | pub struct GenesisState {
type QueryParamsRequest (line 226) | pub struct QueryParamsRequest {
type QueryParamsResponse (line 231) | pub struct QueryParamsResponse {
type QueryBtcCheckpointInfoRequest (line 240) | pub struct QueryBtcCheckpointInfoRequest {
type QueryBtcCheckpointInfoResponse (line 250) | pub struct QueryBtcCheckpointInfoResponse {
type QueryBtcCheckpointsInfoRequest (line 258) | pub struct QueryBtcCheckpointsInfoRequest {
type QueryBtcCheckpointsInfoResponse (line 267) | pub struct QueryBtcCheckpointsInfoResponse {
type QueryEpochSubmissionsRequest (line 278) | pub struct QueryEpochSubmissionsRequest {
type QueryEpochSubmissionsResponse (line 287) | pub struct QueryEpochSubmissionsResponse {
type BtcCheckpointInfoResponse (line 296) | pub struct BtcCheckpointInfoResponse {
type TransactionInfoResponse (line 321) | pub struct TransactionInfoResponse {
type CheckpointAddressesResponse (line 339) | pub struct CheckpointAddressesResponse {
type SubmissionKeyResponse (line 358) | pub struct SubmissionKeyResponse {
type MsgInsertBtcSpvProof (line 374) | pub struct MsgInsertBtcSpvProof {
type MsgInsertBtcSpvProofResponse (line 384) | pub struct MsgInsertBtcSpvProofResponse {
type MsgUpdateParams (line 389) | pub struct MsgUpdateParams {
type MsgUpdateParamsResponse (line 405) | pub struct MsgUpdateParamsResponse {
FILE: src/babylon/proto/gen/babylon.btclightclient.v1.rs
type BtcHeaderInfo (line 12) | pub struct BtcHeaderInfo {
type EventBtcRollBack (line 28) | pub struct EventBtcRollBack {
type EventBtcRollForward (line 38) | pub struct EventBtcRollForward {
type EventBtcHeaderInserted (line 47) | pub struct EventBtcHeaderInserted {
type Params (line 54) | pub struct Params {
type GenesisState (line 63) | pub struct GenesisState {
type QueryParamsRequest (line 72) | pub struct QueryParamsRequest {
type QueryParamsResponse (line 77) | pub struct QueryParamsResponse {
type QueryHashesRequest (line 86) | pub struct QueryHashesRequest {
type QueryHashesResponse (line 93) | pub struct QueryHashesResponse {
type QueryContainsRequest (line 103) | pub struct QueryContainsRequest {
type QueryContainsResponse (line 110) | pub struct QueryContainsResponse {
type QueryContainsBytesRequest (line 118) | pub struct QueryContainsBytesRequest {
type QueryContainsBytesResponse (line 126) | pub struct QueryContainsBytesResponse {
type QueryMainChainRequest (line 134) | pub struct QueryMainChainRequest {
type QueryMainChainResponse (line 141) | pub struct QueryMainChainResponse {
type QueryTipRequest (line 150) | pub struct QueryTipRequest {
type QueryTipResponse (line 155) | pub struct QueryTipResponse {
type QueryBaseHeaderRequest (line 163) | pub struct QueryBaseHeaderRequest {
type QueryBaseHeaderResponse (line 169) | pub struct QueryBaseHeaderResponse {
type QueryHeaderDepthRequest (line 177) | pub struct QueryHeaderDepthRequest {
type QueryHeaderDepthResponse (line 185) | pub struct QueryHeaderDepthResponse {
type BtcHeaderInfoResponse (line 199) | pub struct BtcHeaderInfoResponse {
type MsgInsertHeaders (line 213) | pub struct MsgInsertHeaders {
type MsgInsertHeadersResponse (line 222) | pub struct MsgInsertHeadersResponse {
type MsgUpdateParams (line 227) | pub struct MsgUpdateParams {
type MsgUpdateParamsResponse (line 243) | pub struct MsgUpdateParamsResponse {
FILE: src/babylon/proto/gen/babylon.btcstaking.v1.rs
type ProofOfPossession (line 7) | pub struct ProofOfPossession {
type Bip322Sig (line 23) | pub struct Bip322Sig {
type BtcSigType (line 34) | pub enum BtcSigType {
method as_str_name (line 48) | pub fn as_str_name(&self) -> &'static str {
method from_str_name (line 56) | pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
type FinalityProvider (line 68) | pub struct FinalityProvider {
type FinalityProviderWithMeta (line 99) | pub struct FinalityProviderWithMeta {
type BtcDelegation (line 124) | pub struct BtcDelegation {
type BtcUndelegation (line 185) | pub struct BtcUndelegation {
type BtcDelegatorDelegations (line 222) | pub struct BtcDelegatorDelegations {
type BtcDelegatorDelegationIndex (line 229) | pub struct BtcDelegatorDelegationIndex {
type SignatureInfo (line 236) | pub struct SignatureInfo {
type CovenantAdaptorSignatures (line 246) | pub struct CovenantAdaptorSignatures {
type SelectiveSlashingEvidence (line 262) | pub struct SelectiveSlashingEvidence {
type BtcDelegationStatus (line 283) | pub enum BtcDelegationStatus {
method as_str_name (line 300) | pub fn as_str_name(&self) -> &'static str {
method from_str_name (line 309) | pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
type EventNewFinalityProvider (line 322) | pub struct EventNewFinalityProvider {
type EventBtcDelegationStateUpdate (line 333) | pub struct EventBtcDelegationStateUpdate {
type EventSelectiveSlashing (line 347) | pub struct EventSelectiveSlashing {
type EventPowerDistUpdate (line 356) | pub struct EventPowerDistUpdate {
type EventSlashedFinalityProvider (line 368) | pub struct EventSlashedFinalityProvider {
type Ev (line 375) | pub enum Ev {
type Params (line 387) | pub struct Params {
type VotingPowerDistCache (line 430) | pub struct VotingPowerDistCache {
type FinalityProviderDistInfo (line 440) | pub struct FinalityProviderDistInfo {
type BtcDelDistInfo (line 461) | pub struct BtcDelDistInfo {
type GenesisState (line 479) | pub struct GenesisState {
type VotingPowerFp (line 509) | pub struct VotingPowerFp {
type VotingPowerDistCacheBlkHeight (line 523) | pub struct VotingPowerDistCacheBlkHeight {
type BlockHeightBbnToBtc (line 534) | pub struct BlockHeightBbnToBtc {
type BtcDelegator (line 545) | pub struct BtcDelegator {
type EventIndex (line 559) | pub struct EventIndex {
type QueryParamsRequest (line 573) | pub struct QueryParamsRequest {
type QueryParamsResponse (line 578) | pub struct QueryParamsResponse {
type QueryFinalityProvidersRequest (line 587) | pub struct QueryFinalityProvidersRequest {
type QueryFinalityProvidersResponse (line 596) | pub struct QueryFinalityProvidersResponse {
type QueryFinalityProviderRequest (line 607) | pub struct QueryFinalityProviderRequest {
type QueryFinalityProviderResponse (line 615) | pub struct QueryFinalityProviderResponse {
type QueryBtcDelegationsRequest (line 624) | pub struct QueryBtcDelegationsRequest {
type QueryBtcDelegationsResponse (line 636) | pub struct QueryBtcDelegationsResponse {
type QueryFinalityProviderPowerAtHeightRequest (line 648) | pub struct QueryFinalityProviderPowerAtHeightRequest {
type QueryFinalityProviderPowerAtHeightResponse (line 662) | pub struct QueryFinalityProviderPowerAtHeightResponse {
type QueryFinalityProviderCurrentPowerRequest (line 671) | pub struct QueryFinalityProviderCurrentPowerRequest {
type QueryFinalityProviderCurrentPowerResponse (line 682) | pub struct QueryFinalityProviderCurrentPowerResponse {
type QueryActiveFinalityProvidersAtHeightRequest (line 694) | pub struct QueryActiveFinalityProvidersAtHeightRequest {
type QueryActiveFinalityProvidersAtHeightResponse (line 706) | pub struct QueryActiveFinalityProvidersAtHeightResponse {
type QueryActivatedHeightRequest (line 717) | pub struct QueryActivatedHeightRequest {
type QueryActivatedHeightResponse (line 722) | pub struct QueryActivatedHeightResponse {
type QueryFinalityProviderDelegationsRequest (line 730) | pub struct QueryFinalityProviderDelegationsRequest {
type QueryFinalityProviderDelegationsResponse (line 744) | pub struct QueryFinalityProviderDelegationsResponse {
type QueryBtcDelegationRequest (line 756) | pub struct QueryBtcDelegationRequest {
type QueryBtcDelegationResponse (line 765) | pub struct QueryBtcDelegationResponse {
type BtcDelegationResponse (line 773) | pub struct BtcDelegationResponse {
type BtcUndelegationResponse (line 830) | pub struct BtcUndelegationResponse {
type BtcDelegatorDelegationsResponse (line 865) | pub struct BtcDelegatorDelegationsResponse {
type FinalityProviderResponse (line 872) | pub struct FinalityProviderResponse {
type MsgCreateFinalityProvider (line 909) | pub struct MsgCreateFinalityProvider {
type MsgCreateFinalityProviderResponse (line 932) | pub struct MsgCreateFinalityProviderResponse {
type MsgEditFinalityProvider (line 937) | pub struct MsgEditFinalityProvider {
type MsgEditFinalityProviderResponse (line 954) | pub struct MsgEditFinalityProviderResponse {
type MsgCreateBtcDelegation (line 959) | pub struct MsgCreateBtcDelegation {
type MsgCreateBtcDelegationResponse (line 1021) | pub struct MsgCreateBtcDelegationResponse {
type MsgAddCovenantSigs (line 1026) | pub struct MsgAddCovenantSigs {
type MsgAddCovenantSigsResponse (line 1055) | pub struct MsgAddCovenantSigsResponse {
type MsgBtcUndelegate (line 1062) | pub struct MsgBtcUndelegate {
type MsgBtcUndelegateResponse (line 1077) | pub struct MsgBtcUndelegateResponse {
type MsgSelectiveSlashingEvidence (line 1083) | pub struct MsgSelectiveSlashingEvidence {
type MsgSelectiveSlashingEvidenceResponse (line 1100) | pub struct MsgSelectiveSlashingEvidenceResponse {
type MsgUpdateParams (line 1105) | pub struct MsgUpdateParams {
type MsgUpdateParamsResponse (line 1121) | pub struct MsgUpdateParamsResponse {
FILE: src/babylon/proto/gen/babylon.checkpointing.v1.rs
type BlsKey (line 5) | pub struct BlsKey {
type ProofOfPossession (line 17) | pub struct ProofOfPossession {
type ValidatorWithBlsKeySet (line 30) | pub struct ValidatorWithBlsKeySet {
type ValidatorWithBlsKey (line 38) | pub struct ValidatorWithBlsKey {
type VoteExtension (line 52) | pub struct VoteExtension {
type RawCheckpoint (line 75) | pub struct RawCheckpoint {
type RawCheckpointWithMeta (line 94) | pub struct RawCheckpointWithMeta {
type InjectedCheckpoint (line 115) | pub struct InjectedCheckpoint {
type CheckpointStateUpdate (line 126) | pub struct CheckpointStateUpdate {
type BlsSig (line 142) | pub struct BlsSig {
type CheckpointStatus (line 166) | pub enum CheckpointStatus {
method as_str_name (line 183) | pub fn as_str_name(&self) -> &'static str {
method from_str_name (line 193) | pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
type EventCheckpointAccumulating (line 208) | pub struct EventCheckpointAccumulating {
type EventCheckpointSealed (line 216) | pub struct EventCheckpointSealed {
type EventCheckpointSubmitted (line 224) | pub struct EventCheckpointSubmitted {
type EventCheckpointConfirmed (line 232) | pub struct EventCheckpointConfirmed {
type EventCheckpointFinalized (line 240) | pub struct EventCheckpointFinalized {
type EventCheckpointForgotten (line 248) | pub struct EventCheckpointForgotten {
type EventConflictingCheckpoint (line 256) | pub struct EventConflictingCheckpoint {
type GenesisState (line 265) | pub struct GenesisState {
type GenesisKey (line 273) | pub struct GenesisKey {
type QueryRawCheckpointListRequest (line 288) | pub struct QueryRawCheckpointListRequest {
type QueryRawCheckpointListResponse (line 300) | pub struct QueryRawCheckpointListResponse {
type QueryRawCheckpointRequest (line 312) | pub struct QueryRawCheckpointRequest {
type QueryRawCheckpointResponse (line 321) | pub struct QueryRawCheckpointResponse {
type QueryRawCheckpointsRequest (line 329) | pub struct QueryRawCheckpointsRequest {
type QueryRawCheckpointsResponse (line 338) | pub struct QueryRawCheckpointsResponse {
type QueryBlsPublicKeyListRequest (line 350) | pub struct QueryBlsPublicKeyListRequest {
type QueryBlsPublicKeyListResponse (line 362) | pub struct QueryBlsPublicKeyListResponse {
type QueryEpochStatusRequest (line 373) | pub struct QueryEpochStatusRequest {
type QueryEpochStatusResponse (line 381) | pub struct QueryEpochStatusResponse {
type QueryRecentEpochStatusCountRequest (line 389) | pub struct QueryRecentEpochStatusCountRequest {
type QueryRecentEpochStatusCountResponse (line 399) | pub struct QueryRecentEpochStatusCountResponse {
type QueryLastCheckpointWithStatusRequest (line 411) | pub struct QueryLastCheckpointWithStatusRequest {
type QueryLastCheckpointWithStatusResponse (line 419) | pub struct QueryLastCheckpointWithStatusResponse {
type RawCheckpointResponse (line 426) | pub struct RawCheckpointResponse {
type CheckpointStateUpdateResponse (line 445) | pub struct CheckpointStateUpdateResponse {
type RawCheckpointWithMetaResponse (line 464) | pub struct RawCheckpointWithMetaResponse {
type MsgWrappedCreateValidator (line 488) | pub struct MsgWrappedCreateValidator {
type MsgWrappedCreateValidatorResponse (line 498) | pub struct MsgWrappedCreateValidatorResponse {
FILE: src/babylon/proto/gen/babylon.epoching.v1.rs
type Epoch (line 5) | pub struct Epoch {
type QueuedMessage (line 41) | pub struct QueuedMessage {
type Msg (line 65) | pub enum Msg {
type ValStateUpdate (line 81) | pub struct ValStateUpdate {
type ValidatorLifecycle (line 93) | pub struct ValidatorLifecycle {
type DelegationStateUpdate (line 103) | pub struct DelegationStateUpdate {
type DelegationLifecycle (line 119) | pub struct DelegationLifecycle {
type Validator (line 128) | pub struct Validator {
type BondState (line 139) | pub enum BondState {
method as_str_name (line 156) | pub fn as_str_name(&self) -> &'static str {
method from_str_name (line 166) | pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
type EventBeginEpoch (line 180) | pub struct EventBeginEpoch {
type EventEndEpoch (line 187) | pub struct EventEndEpoch {
type EventHandleQueuedMsg (line 195) | pub struct EventHandleQueuedMsg {
type EventSlashThreshold (line 215) | pub struct EventSlashThreshold {
type EventWrappedDelegate (line 227) | pub struct EventWrappedDelegate {
type EventWrappedUndelegate (line 243) | pub struct EventWrappedUndelegate {
type EventWrappedBeginRedelegate (line 259) | pub struct EventWrappedBeginRedelegate {
type EventWrappedCancelUnbondingDelegation (line 277) | pub struct EventWrappedCancelUnbondingDelegation {
type Params (line 292) | pub struct Params {
type GenesisState (line 300) | pub struct GenesisState {
type QueryParamsRequest (line 307) | pub struct QueryParamsRequest {
type QueryParamsResponse (line 312) | pub struct QueryParamsResponse {
type QueryEpochInfoRequest (line 320) | pub struct QueryEpochInfoRequest {
type QueryEpochInfoResponse (line 327) | pub struct QueryEpochInfoResponse {
type QueryEpochsInfoRequest (line 334) | pub struct QueryEpochsInfoRequest {
type QueryEpochsInfoResponse (line 342) | pub struct QueryEpochsInfoResponse {
type QueryCurrentEpochRequest (line 353) | pub struct QueryCurrentEpochRequest {
type QueryCurrentEpochResponse (line 359) | pub struct QueryCurrentEpochResponse {
type QueryEpochMsgsRequest (line 370) | pub struct QueryEpochMsgsRequest {
type QueryEpochMsgsResponse (line 382) | pub struct QueryEpochMsgsResponse {
type QueryLatestEpochMsgsRequest (line 395) | pub struct QueryLatestEpochMsgsRequest {
type QueryLatestEpochMsgsResponse (line 409) | pub struct QueryLatestEpochMsgsResponse {
type QueryValidatorLifecycleRequest (line 421) | pub struct QueryValidatorLifecycleRequest {
type QueryValidatorLifecycleResponse (line 429) | pub struct QueryValidatorLifecycleResponse {
type QueryDelegationLifecycleRequest (line 439) | pub struct QueryDelegationLifecycleRequest {
type QueryDelegationLifecycleResponse (line 447) | pub struct QueryDelegationLifecycleResponse {
type QueryEpochValSetRequest (line 455) | pub struct QueryEpochValSetRequest {
type QueryEpochValSetResponse (line 465) | pub struct QueryEpochValSetResponse {
type EpochResponse (line 476) | pub struct EpochResponse {
type QueuedMessageResponse (line 512) | pub struct QueuedMessageResponse {
type QueuedMessageList (line 534) | pub struct QueuedMessageList {
type ValStateUpdateResponse (line 543) | pub struct ValStateUpdateResponse {
type MsgWrappedDelegate (line 555) | pub struct MsgWrappedDelegate {
type MsgWrappedDelegateResponse (line 562) | pub struct MsgWrappedDelegateResponse {
type MsgWrappedUndelegate (line 567) | pub struct MsgWrappedUndelegate {
type MsgWrappedUndelegateResponse (line 575) | pub struct MsgWrappedUndelegateResponse {
type MsgWrappedBeginRedelegate (line 581) | pub struct MsgWrappedBeginRedelegate {
type MsgWrappedBeginRedelegateResponse (line 589) | pub struct MsgWrappedBeginRedelegateResponse {
type MsgWrappedCancelUnbondingDelegation (line 595) | pub struct MsgWrappedCancelUnbondingDelegation {
type MsgWrappedCancelUnbondingDelegationResponse (line 603) | pub struct MsgWrappedCancelUnbondingDelegationResponse {
type MsgUpdateParams (line 608) | pub struct MsgUpdateParams {
type MsgUpdateParamsResponse (line 624) | pub struct MsgUpdateParamsResponse {
FILE: src/babylon/proto/gen/babylon.finality.v1.rs
type IndexedBlock (line 5) | pub struct IndexedBlock {
type Evidence (line 21) | pub struct Evidence {
type EventSlashedFinalityProvider (line 52) | pub struct EventSlashedFinalityProvider {
type Params (line 60) | pub struct Params {
type GenesisState (line 69) | pub struct GenesisState {
type VoteSig (line 90) | pub struct VoteSig {
type PublicRandomness (line 105) | pub struct PublicRandomness {
type QueryParamsRequest (line 119) | pub struct QueryParamsRequest {
type QueryParamsResponse (line 124) | pub struct QueryParamsResponse {
type QueryListPublicRandomnessRequest (line 133) | pub struct QueryListPublicRandomnessRequest {
type QueryListPublicRandomnessResponse (line 145) | pub struct QueryListPublicRandomnessResponse {
type QueryBlockRequest (line 158) | pub struct QueryBlockRequest {
type QueryBlockResponse (line 167) | pub struct QueryBlockResponse {
type QueryListBlocksRequest (line 176) | pub struct QueryListBlocksRequest {
type QueryListBlocksResponse (line 188) | pub struct QueryListBlocksResponse {
type QueryVotesAtHeightRequest (line 200) | pub struct QueryVotesAtHeightRequest {
type QueryVotesAtHeightResponse (line 209) | pub struct QueryVotesAtHeightResponse {
type QueryEvidenceRequest (line 219) | pub struct QueryEvidenceRequest {
type QueryEvidenceResponse (line 229) | pub struct QueryEvidenceResponse {
type QueryListEvidencesRequest (line 237) | pub struct QueryListEvidencesRequest {
type QueryListEvidencesResponse (line 250) | pub struct QueryListEvidencesResponse {
type QueriedBlockStatus (line 261) | pub enum QueriedBlockStatus {
method as_str_name (line 274) | pub fn as_str_name(&self) -> &'static str {
method from_str_name (line 282) | pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
type MsgAddFinalitySig (line 294) | pub struct MsgAddFinalitySig {
type MsgAddFinalitySigResponse (line 316) | pub struct MsgAddFinalitySigResponse {
type MsgCommitPubRandList (line 321) | pub struct MsgCommitPubRandList {
type MsgCommitPubRandListResponse (line 344) | pub struct MsgCommitPubRandListResponse {
type MsgUpdateParams (line 349) | pub struct MsgUpdateParams {
type MsgUpdateParamsResponse (line 365) | pub struct MsgUpdateParamsResponse {
FILE: src/babylon/proto/gen/babylon.incentive.rs
type Params (line 8) | pub struct Params {
type GenesisState (line 24) | pub struct GenesisState {
type Gauge (line 32) | pub struct Gauge {
type RewardGauge (line 42) | pub struct RewardGauge {
type QueryParamsRequest (line 54) | pub struct QueryParamsRequest {
type QueryParamsResponse (line 59) | pub struct QueryParamsResponse {
type QueryRewardGaugesRequest (line 67) | pub struct QueryRewardGaugesRequest {
type QueryRewardGaugesResponse (line 75) | pub struct QueryRewardGaugesResponse {
type QueryBtcStakingGaugeRequest (line 84) | pub struct QueryBtcStakingGaugeRequest {
type QueryBtcStakingGaugeResponse (line 92) | pub struct QueryBtcStakingGaugeResponse {
type QueryBtcTimestampingGaugeRequest (line 100) | pub struct QueryBtcTimestampingGaugeRequest {
type QueryBtcTimestampingGaugeResponse (line 108) | pub struct QueryBtcTimestampingGaugeResponse {
type MsgWithdrawReward (line 116) | pub struct MsgWithdrawReward {
type MsgWithdrawRewardResponse (line 128) | pub struct MsgWithdrawRewardResponse {
type MsgUpdateParams (line 136) | pub struct MsgUpdateParams {
type MsgUpdateParamsResponse (line 152) | pub struct MsgUpdateParamsResponse {
FILE: src/babylon/proto/gen/babylon.monitor.v1.rs
type GenesisState (line 5) | pub struct GenesisState {
type QueryEndedEpochBtcHeightRequest (line 11) | pub struct QueryEndedEpochBtcHeightRequest {
type QueryEndedEpochBtcHeightResponse (line 19) | pub struct QueryEndedEpochBtcHeightResponse {
type QueryReportedCheckpointBtcHeightRequest (line 28) | pub struct QueryReportedCheckpointBtcHeightRequest {
type QueryReportedCheckpointBtcHeightResponse (line 37) | pub struct QueryReportedCheckpointBtcHeightResponse {
FILE: src/babylon/proto/gen/babylon.zoneconcierge.v1.rs
type Params (line 5) | pub struct Params {
type GenesisState (line 14) | pub struct GenesisState {
type IndexedHeader (line 23) | pub struct IndexedHeader {
type Forks (line 72) | pub struct Forks {
type ChainInfo (line 80) | pub struct ChainInfo {
type FinalizedChainInfo (line 99) | pub struct FinalizedChainInfo {
type ProofEpochSealed (line 132) | pub struct ProofEpochSealed {
type ProofFinalizedChainInfo (line 155) | pub struct ProofFinalizedChainInfo {
type BtcChainSegment (line 172) | pub struct BtcChainSegment {
type ZoneconciergePacketData (line 180) | pub struct ZoneconciergePacketData {
type Packet (line 190) | pub enum Packet {
type BtcTimestamp (line 202) | pub struct BtcTimestamp {
type QueryParamsRequest (line 235) | pub struct QueryParamsRequest {
type QueryParamsResponse (line 240) | pub struct QueryParamsResponse {
type QueryHeaderRequest (line 248) | pub struct QueryHeaderRequest {
type QueryHeaderResponse (line 257) | pub struct QueryHeaderResponse {
type QueryChainListRequest (line 266) | pub struct QueryChainListRequest {
type QueryChainListResponse (line 274) | pub struct QueryChainListResponse {
type QueryChainsInfoRequest (line 285) | pub struct QueryChainsInfoRequest {
type QueryChainsInfoResponse (line 292) | pub struct QueryChainsInfoResponse {
type QueryEpochChainsInfoRequest (line 300) | pub struct QueryEpochChainsInfoRequest {
type QueryEpochChainsInfoResponse (line 310) | pub struct QueryEpochChainsInfoResponse {
type QueryListHeadersRequest (line 318) | pub struct QueryListHeadersRequest {
type QueryListHeadersResponse (line 329) | pub struct QueryListHeadersResponse {
type QueryListEpochHeadersRequest (line 341) | pub struct QueryListEpochHeadersRequest {
type QueryListEpochHeadersResponse (line 351) | pub struct QueryListEpochHeadersResponse {
type QueryFinalizedChainsInfoRequest (line 360) | pub struct QueryFinalizedChainsInfoRequest {
type QueryFinalizedChainsInfoResponse (line 372) | pub struct QueryFinalizedChainsInfoResponse {
type QueryFinalizedChainInfoUntilHeightRequest (line 380) | pub struct QueryFinalizedChainInfoUntilHeightRequest {
type QueryFinalizedChainInfoUntilHeightResponse (line 397) | pub struct QueryFinalizedChainInfoUntilHeightResponse {
type MsgUpdateParams (line 418) | pub struct MsgUpdateParams {
type MsgUpdateParamsResponse (line 434) | pub struct MsgUpdateParamsResponse {
FILE: src/babylon/proto/mod.rs
type ProofOfPossession (line 11) | pub struct ProofOfPossession {
type Bip322Sig (line 27) | pub struct Bip322Sig {
type BtcSigType (line 38) | pub enum BtcSigType {
method as_str_name (line 53) | pub fn as_str_name(&self) -> &'static str {
method from_str_name (line 61) | pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
type FinalityProvider (line 73) | pub struct FinalityProvider {
type FinalityProviderWithMeta (line 105) | pub struct FinalityProviderWithMeta {
type BtcDelegation (line 131) | pub struct BtcDelegation {
type BtcUndelegation (line 194) | pub struct BtcUndelegation {
type BtcDelegatorDelegations (line 232) | pub struct BtcDelegatorDelegations {
type BtcDelegatorDelegationIndex (line 240) | pub struct BtcDelegatorDelegationIndex {
type SignatureInfo (line 247) | pub struct SignatureInfo {
type CovenantAdaptorSignatures (line 257) | pub struct CovenantAdaptorSignatures {
type SelectiveSlashingEvidence (line 275) | pub struct SelectiveSlashingEvidence {
type BtcDelegationStatus (line 297) | pub enum BtcDelegationStatus {
method as_str_name (line 317) | pub fn as_str_name(&self) -> &'static str {
method from_str_name (line 326) | pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
type EventNewFinalityProvider (line 340) | pub struct EventNewFinalityProvider {
type EventBtcDelegationStateUpdate (line 352) | pub struct EventBtcDelegationStateUpdate {
type EventSelectiveSlashing (line 366) | pub struct EventSelectiveSlashing {
type EventPowerDistUpdate (line 375) | pub struct EventPowerDistUpdate {
type EventSlashedFinalityProvider (line 387) | pub struct EventSlashedFinalityProvider {
type Ev (line 394) | pub enum Ev {
type Params (line 406) | pub struct Params {
type VotingPowerDistCache (line 452) | pub struct VotingPowerDistCache {
type FinalityProviderDistInfo (line 464) | pub struct FinalityProviderDistInfo {
type BtcDelDistInfo (line 487) | pub struct BtcDelDistInfo {
type GenesisState (line 505) | pub struct GenesisState {
type VotingPowerFp (line 538) | pub struct VotingPowerFp {
type VotingPowerDistCacheBlkHeight (line 554) | pub struct VotingPowerDistCacheBlkHeight {
type BlockHeightBbnToBtc (line 567) | pub struct BlockHeightBbnToBtc {
type BtcDelegator (line 579) | pub struct BtcDelegator {
type EventIndex (line 593) | pub struct EventIndex {
type QueryParamsRequest (line 607) | pub struct QueryParamsRequest {}
type QueryParamsResponse (line 611) | pub struct QueryParamsResponse {
type QueryFinalityProvidersRequest (line 620) | pub struct QueryFinalityProvidersRequest {
type QueryFinalityProvidersResponse (line 630) | pub struct QueryFinalityProvidersResponse {
type QueryFinalityProviderRequest (line 642) | pub struct QueryFinalityProviderRequest {
type QueryFinalityProviderResponse (line 651) | pub struct QueryFinalityProviderResponse {
type QueryBtcDelegationsRequest (line 660) | pub struct QueryBtcDelegationsRequest {
type QueryBtcDelegationsResponse (line 673) | pub struct QueryBtcDelegationsResponse {
type QueryFinalityProviderPowerAtHeightRequest (line 687) | pub struct QueryFinalityProviderPowerAtHeightRequest {
type QueryFinalityProviderPowerAtHeightResponse (line 702) | pub struct QueryFinalityProviderPowerAtHeightResponse {
type QueryFinalityProviderCurrentPowerRequest (line 711) | pub struct QueryFinalityProviderCurrentPowerRequest {
type QueryFinalityProviderCurrentPowerResponse (line 722) | pub struct QueryFinalityProviderCurrentPowerResponse {
type QueryActiveFinalityProvidersAtHeightRequest (line 734) | pub struct QueryActiveFinalityProvidersAtHeightRequest {
type QueryActiveFinalityProvidersAtHeightResponse (line 748) | pub struct QueryActiveFinalityProvidersAtHeightResponse {
type QueryActivatedHeightRequest (line 761) | pub struct QueryActivatedHeightRequest {}
type QueryActivatedHeightResponse (line 766) | pub struct QueryActivatedHeightResponse {
type QueryFinalityProviderDelegationsRequest (line 774) | pub struct QueryFinalityProviderDelegationsRequest {
type QueryFinalityProviderDelegationsResponse (line 789) | pub struct QueryFinalityProviderDelegationsResponse {
type QueryBtcDelegationRequest (line 802) | pub struct QueryBtcDelegationRequest {
type QueryBtcDelegationResponse (line 811) | pub struct QueryBtcDelegationResponse {
type BtcDelegationResponse (line 821) | pub struct BtcDelegationResponse {
type BtcUndelegationResponse (line 878) | pub struct BtcUndelegationResponse {
type BtcDelegatorDelegationsResponse (line 916) | pub struct BtcDelegatorDelegationsResponse {
type FinalityProviderResponse (line 924) | pub struct FinalityProviderResponse {
type MsgCreateFinalityProvider (line 963) | pub struct MsgCreateFinalityProvider {
type MsgCreateFinalityProviderResponse (line 988) | pub struct MsgCreateFinalityProviderResponse {}
type MsgEditFinalityProvider (line 993) | pub struct MsgEditFinalityProvider {
type MsgEditFinalityProviderResponse (line 1013) | pub struct MsgEditFinalityProviderResponse {}
type MsgCreateBtcDelegation (line 1017) | pub struct MsgCreateBtcDelegation {
type MsgCreateBtcDelegationResponse (line 1088) | pub struct MsgCreateBtcDelegationResponse {}
type MsgAddCovenantSigs (line 1093) | pub struct MsgAddCovenantSigs {
type MsgAddCovenantSigsResponse (line 1122) | pub struct MsgAddCovenantSigsResponse {}
type MsgBtcUndelegate (line 1128) | pub struct MsgBtcUndelegate {
type MsgBtcUndelegateResponse (line 1143) | pub struct MsgBtcUndelegateResponse {}
type MsgSelectiveSlashingEvidence (line 1148) | pub struct MsgSelectiveSlashingEvidence {
type MsgSelectiveSlashingEvidenceResponse (line 1166) | pub struct MsgSelectiveSlashingEvidenceResponse {}
type MsgUpdateParams (line 1170) | pub struct MsgUpdateParams {
type MsgUpdateParamsResponse (line 1186) | pub struct MsgUpdateParamsResponse {}
FILE: src/babylon/relayer.rs
function relay_staking_confs (line 30) | pub async fn relay_staking_confs(
function maybe_relay_staking_conf (line 75) | pub async fn maybe_relay_staking_conf(
function relay_unbonding_confs (line 145) | pub async fn relay_unbonding_confs(
function maybe_relay_unbonding_conf (line 190) | pub async fn maybe_relay_unbonding_conf(
function scan_for_txid (line 231) | async fn scan_for_txid(
function last_n_blocks (line 253) | pub async fn last_n_blocks(
FILE: src/bin/create-checkpoint.rs
type Opts (line 16) | pub struct Opts {
function main (line 39) | pub async fn main() {
FILE: src/bin/eth-bootstrap.rs
constant SYNC_PERIOD_LENGTH (line 5) | pub const SYNC_PERIOD_LENGTH: u64 = 32 * 256;
type Opts (line 8) | pub struct Opts {
function main (line 14) | pub async fn main() -> Result<()> {
FILE: src/bin/get-reserve-scripts.rs
type Opts (line 15) | pub struct Opts {
function main (line 36) | pub async fn main() {
function now (line 92) | fn now() -> u64 {
FILE: src/bin/nomic.rs
constant BANNER (line 64) | const BANNER: &str = r#"
function wallet (line 75) | fn wallet() -> SimpleWallet {
function my_address (line 89) | fn my_address() -> Address {
type Opts (line 99) | pub struct Opts {
type Command (line 111) | pub enum Command {
method run (line 201) | fn run(&self, config: &nomic::network::Config) -> Result<()> {
type StartCmd (line 280) | pub struct StartCmd {
method run (line 332) | async fn run(&self) -> orga::Result<()> {
function legacy_bin (line 521) | fn legacy_bin(config: &nomic::network::Config) -> Result<Option<PathBuf>> {
function relaunch_on_migrate (line 654) | async fn relaunch_on_migrate(config: &nomic::network::Config) -> Result<...
function configure_node (line 681) | fn configure_node<P, F>(cfg_path: &P, configure: F)
function edit_block_time (line 699) | fn edit_block_time(cfg_path: &PathBuf, timeout_commit: &str) {
function configure_for_statesync (line 706) | async fn configure_for_statesync(cfg_path: &PathBuf, rpc_servers: &[&str...
function get_bootstrap_state (line 732) | async fn get_bootstrap_state(rpc_servers: &[&str]) -> Result<(i64, Strin...
type SendCmd (line 786) | pub struct SendCmd {
method run (line 800) | async fn run(&self) -> Result<()> {
type SendNbtcCmd (line 815) | pub struct SendNbtcCmd {
method run (line 829) | async fn run(&self) -> Result<()> {
type BalanceCmd (line 845) | pub struct BalanceCmd {
method run (line 856) | async fn run(&self) -> Result<()> {
type DelegationsCmd (line 879) | pub struct DelegationsCmd {
method run (line 886) | async fn run(&self) -> Result<()> {
type ValidatorsCmd (line 934) | pub struct ValidatorsCmd {
method run (line 941) | async fn run(&self) -> Result<()> {
type DelegateCmd (line 965) | pub struct DelegateCmd {
method run (line 979) | async fn run(&self) -> Result<()> {
type DeclareCmd (line 998) | pub struct DeclareCmd {
method run (line 1030) | async fn run(&self) -> Result<()> {
type DeclareInfo (line 1016) | pub struct DeclareInfo {
type EditCmd (line 1085) | pub struct EditCmd {
method run (line 1108) | async fn run(&self) -> Result<()> {
type UnbondCmd (line 1139) | pub struct UnbondCmd {
method run (line 1153) | async fn run(&self) -> Result<()> {
type RedelegateCmd (line 1172) | pub struct RedelegateCmd {
method run (line 1188) | async fn run(&self) -> Result<()> {
type UnjailCmd (line 1209) | pub struct UnjailCmd {
method run (line 1216) | async fn run(&self) -> Result<()> {
type ClaimCmd (line 1231) | pub struct ClaimCmd {
method run (line 1238) | async fn run(&self) -> Result<()> {
type AirdropCmd (line 1253) | pub struct AirdropCmd {
method run (line 1264) | async fn run(&self) -> Result<()> {
type ClaimAirdropCmd (line 1284) | pub struct ClaimAirdropCmd {
method run (line 1294) | async fn run(&self) -> Result<()> {
type RelayerCmd (line 1344) | pub struct RelayerCmd {
method btc_client (line 1368) | async fn btc_client(&self) -> Result<BtcClient> {
method run (line 1387) | async fn run(&self) -> Result<()> {
type SignerCmd (line 1437) | pub struct SignerCmd {
method run (line 1486) | async fn run(&self) -> Result<()> {
type SetSignatoryKeyCmd (line 1529) | pub struct SetSignatoryKeyCmd {
method run (line 1541) | async fn run(&self) -> Result<()> {
function deposit (line 1567) | async fn deposit(
type DepositCmd (line 1625) | pub struct DepositCmd {
method run (line 1636) | async fn run(&self) -> Result<()> {
type InterchainDepositCmd (line 1647) | pub struct InterchainDepositCmd {
method run (line 1664) | async fn run(&self) -> Result<()> {
constant ONE_DAY_NS (line 1661) | const ONE_DAY_NS: u64 = 86400 * 1_000_000_000;
type WithdrawCmd (line 1687) | pub struct WithdrawCmd {
method run (line 1699) | async fn run(&self) -> Result<()> {
type IbcWithdrawNbtcCmd (line 1747) | pub struct IbcWithdrawNbtcCmd {
method run (line 1757) | async fn run(&self) -> Result<()> {
type EthTransferNbtcCmd (line 1773) | pub struct EthTransferNbtcCmd {
method run (line 1789) | async fn run(&self) -> Result<()> {
type GrpcCmd (line 1821) | pub struct GrpcCmd {
method run (line 1834) | async fn run(&self) -> Result<()> {
type IbcTransferCmd (line 1856) | pub struct IbcTransferCmd {
method run (line 1879) | async fn run(&self) -> Result<()> {
type ExportCmd (line 1908) | pub struct ExportCmd {
method run (line 1915) | async fn run(&self) -> Result<()> {
type UpgradeStatusCmd (line 1935) | pub struct UpgradeStatusCmd {
method run (line 1942) | async fn run(&self) -> Result<()> {
type RelayOpKeysCmd (line 2123) | pub struct RelayOpKeysCmd {
method run (line 2132) | async fn run(&self) -> Result<()> {
type SetRecoveryAddressCmd (line 2156) | pub struct SetRecoveryAddressCmd {
method run (line 2166) | async fn run(&self) -> Result<()> {
type SigningStatusCmd (line 2194) | pub struct SigningStatusCmd {
method run (line 2201) | async fn run(&self) -> Result<()> {
type RecoverDepositCmd (line 2292) | pub struct RecoverDepositCmd {
method btc_client (line 2353) | async fn btc_client(&self) -> Result<BtcClient> {
method relay_deposit (line 2368) | async fn relay_deposit(&self, dest: Dest, sigset_index: u32) -> Result...
method run (line 2417) | async fn run(&self) -> Result<()> {
type PayToFeePoolCmd (line 2540) | pub struct PayToFeePoolCmd {
method run (line 2550) | async fn run(&self) -> Result<()> {
type BabylonRelayerCmd (line 2565) | pub struct BabylonRelayerCmd {
method btc_client (line 2580) | async fn btc_client(&self) -> Result<BtcClient> {
method run (line 2594) | async fn run(&self) -> Result<()> {
type StakeNbtcCmd (line 2628) | pub struct StakeNbtcCmd {
method run (line 2637) | async fn run(&self) -> Result<()> {
type FrostSignerCmd (line 2653) | pub struct FrostSignerCmd {
method run (line 2660) | async fn run(&self) -> Result<()> {
type RelayEthereumCmd (line 2680) | pub struct RelayEthereumCmd {
method run (line 2700) | async fn run(&self) -> Result<()> {
type GetSigsetEthAddressesCmd (line 3104) | pub struct GetSigsetEthAddressesCmd {
method run (line 3114) | async fn run(&self) -> Result<()> {
type CreateEthConnectionCmd (line 3144) | pub struct CreateEthConnectionCmd {
method run (line 3160) | async fn run(&self) -> Result<()> {
function main (line 3192) | pub fn main() {
FILE: src/bitcoin/adapter.rs
type Adapter (line 16) | pub struct Adapter<T> {
function new (line 24) | pub fn new(inner: T) -> Self {
function into_inner (line 29) | pub fn into_inner(self) -> T {
function from (line 35) | fn from(value: T) -> Self {
method default (line 41) | fn default() -> Self {
method attach (line 52) | fn attach(&mut self, _: Store) -> OrgaResult<()> {
method flush (line 57) | fn flush<W: std::io::Write>(self, out: &mut W) -> OrgaResult<()> {
method load (line 61) | fn load(_store: Store, bytes: &mut &[u8]) -> OrgaResult<Self> {
method describe (line 67) | fn describe() -> orga::describe::Descriptor {
type Target (line 73) | type Target = T;
method deref (line 75) | fn deref(&self) -> &Self::Target {
method deref_mut (line 81) | fn deref_mut(&mut self) -> &mut Self::Target {
method encode (line 87) | fn encode(&self) -> EncodingResult<Vec<u8>> {
method encode_into (line 93) | fn encode_into<W: Write>(&self, dest: &mut W) -> EncodingResult<()> {
method encoding_length (line 100) | fn encoding_length(&self) -> EncodingResult<usize> {
method decode (line 110) | fn decode<R: Read>(mut input: R) -> EncodingResult<Self> {
type Query (line 126) | type Query = ();
method query (line 128) | fn query(&self, _: Self::Query) -> Result<()> {
type Call (line 134) | type Call = ();
method call (line 136) | fn call(&mut self, _: Self::Call) -> Result<()> {
FILE: src/bitcoin/checkpoint.rs
type CheckpointStatus (line 59) | pub enum CheckpointStatus {
method attach (line 81) | fn attach(&mut self, _: Store) -> OrgaResult<()> {
method flush (line 86) | fn flush<W: std::io::Write>(self, out: &mut W) -> OrgaResult<()> {
method load (line 90) | fn load(_store: Store, bytes: &mut &[u8]) -> OrgaResult<Self> {
type Query (line 96) | type Query = ();
method query (line 98) | fn query(&self, _: ()) -> OrgaResult<()> {
type Call (line 104) | type Call = ();
method call (line 106) | fn call(&mut self, _: ()) -> OrgaResult<()> {
method describe (line 112) | fn describe() -> orga::describe::Descriptor {
type Input (line 124) | pub struct Input {
method to_txin (line 163) | pub fn to_txin(&self) -> Result<TxIn> {
method new (line 179) | pub fn new(
method est_vsize (line 203) | pub fn est_vsize(&self) -> u64 {
method migrate_from (line 209) | fn migrate_from(_value: InputV0) -> OrgaResult<Self> {
type Output (line 215) | pub type Output = Adapter<bitcoin::TxOut>;
type BitcoinTx (line 220) | pub struct BitcoinTx {
method to_bitcoin_tx (line 239) | pub fn to_bitcoin_tx(&self) -> Result<Transaction> {
method with_lock_time (line 258) | pub fn with_lock_time(lock_time: u32) -> Self {
method signed (line 267) | pub fn signed(&self) -> bool {
method est_vsize (line 273) | pub fn est_vsize(&self) -> Result<u64> {
method txid (line 284) | pub fn txid(&self) -> Result<bitcoin::Txid> {
method value (line 290) | pub fn value(&self) -> Result<u64> {
method populate_input_sig_message (line 301) | pub fn populate_input_sig_message(&mut self, input_index: usize) -> Re...
method deduct_fee (line 328) | pub fn deduct_fee(&mut self, fee: u64) -> Result<()> {
type BatchType (line 385) | pub enum BatchType {
type Batch (line 418) | pub struct Batch {
method signed (line 438) | fn signed(&self) -> bool {
type Target (line 424) | type Target = Deque<BitcoinTx>;
method deref (line 426) | fn deref(&self) -> &Self::Target {
method deref_mut (line 432) | fn deref_mut(&mut self) -> &mut Self::Target {
constant DEFAULT_FEE_RATE (line 445) | pub const DEFAULT_FEE_RATE: u64 = 10;
type Checkpoint (line 472) | pub struct Checkpoint {
method new (line 545) | pub fn new(sigset: SignatorySet) -> Result<Self> {
method sign (line 588) | fn sign(&mut self, xpub: Xpub, sigs: LengthVec<u16, Signature>, btc_he...
method checkpoint_tx (line 671) | pub fn checkpoint_tx(&self) -> Result<Adapter<bitcoin::Transaction>> {
method checkpoint_txs (line 685) | pub fn checkpoint_txs(&self) -> Result<Vec<Adapter<bitcoin::Transactio...
method reserve_output (line 705) | pub fn reserve_output(&self) -> Result<Option<TxOut>> {
method to_sign (line 723) | pub fn to_sign(&self, xpub: Xpub) -> Result<Vec<([u8; 32], u32)>> {
method signed_batches (line 750) | fn signed_batches(&self) -> Result<u64> {
method current_batch (line 765) | pub fn current_batch(&self) -> Result<Option<Ref<Batch>>> {
method create_time (line 775) | pub fn create_time(&self) -> u64 {
method signed (line 781) | pub fn signed(&self) -> Result<bool> {
method emergency_disbursal_txs (line 789) | pub fn emergency_disbursal_txs(&self) -> Result<Vec<Adapter<bitcoin::T...
method checkpoint_tx_miner_fees (line 806) | pub fn checkpoint_tx_miner_fees(&self) -> Result<u64> {
method base_fee (line 825) | fn base_fee(&self, config: &Config, timestamping_commitment: &[u8]) ->...
method est_vsize (line 830) | fn est_vsize(&self, config: &Config, timestamping_commitment: &[u8]) -...
method additional_outputs (line 854) | fn additional_outputs(
method migrate_from (line 523) | fn migrate_from(value: CheckpointV3) -> OrgaResult<Self> {
type Config (line 882) | pub struct Config {
method regtest (line 1037) | fn regtest() -> Self {
method bitcoin (line 1048) | fn bitcoin() -> Self {
method migrate_from (line 994) | fn migrate_from(value: ConfigV2) -> OrgaResult<Self> {
method migrate_from (line 1015) | fn migrate_from(value: ConfigV3) -> OrgaResult<Self> {
method default (line 1073) | fn default() -> Self {
type CheckpointQueue (line 1099) | pub struct CheckpointQueue {
method configure (line 1696) | pub fn configure(&mut self, config: Config) {
method config (line 1701) | pub fn config(&self) -> Config {
method reset (line 1706) | pub fn reset(&mut self) -> OrgaResult<()> {
method get (line 1717) | pub fn get(&self, index: u32) -> Result<Ref<'_, Checkpoint>> {
method get_mut (line 1725) | pub fn get_mut(&mut self, index: u32) -> Result<ChildMut<'_, u64, Chec...
method get_deque_index (line 1738) | fn get_deque_index(&self, index: u32) -> Result<u32> {
method len (line 1755) | pub fn len(&self) -> Result<u32> {
method is_empty (line 1762) | pub fn is_empty(&self) -> Result<bool> {
method index (line 1769) | pub fn index(&self) -> u32 {
method all (line 1779) | pub fn all(&self) -> Result<Vec<(u32, Ref<'_, Checkpoint>)>> {
method completed (line 1799) | pub fn completed(&self, limit: u32) -> Result<Vec<CompletedCheckpoint<...
method last_completed_index (line 1825) | pub fn last_completed_index(&self) -> Result<u32> {
method first_index (line 1835) | pub fn first_index(&self) -> Result<u32> {
method last_completed (line 1841) | pub fn last_completed(&self) -> Result<Ref<Checkpoint>> {
method last_completed_mut (line 1846) | pub fn last_completed_mut(&mut self) -> Result<ChildMut<u64, Checkpoin...
method last_completed_tx (line 1852) | pub fn last_completed_tx(&self) -> Result<Adapter<bitcoin::Transaction...
method completed_txs (line 1858) | pub fn completed_txs(&self, limit: u32) -> Result<Vec<Adapter<bitcoin:...
method emergency_disbursal_txs (line 1874) | pub fn emergency_disbursal_txs(&self) -> Result<Vec<Adapter<bitcoin::T...
method signing (line 1884) | pub fn signing(&self) -> Result<Option<SigningCheckpoint<'_>>> {
method signing_mut (line 1899) | pub fn signing_mut(&mut self) -> Result<Option<SigningCheckpointMut>> {
method building (line 1918) | pub fn building(&self) -> Result<BuildingCheckpoint> {
method building_mut (line 1929) | pub fn building_mut(&mut self) -> Result<BuildingCheckpointMut> {
method prune (line 1935) | pub fn prune(&mut self) -> Result<()> {
method maybe_step (line 1989) | pub fn maybe_step(
method should_push (line 2110) | pub fn should_push(
method maybe_push (line 2230) | pub fn maybe_push(
method active_sigset (line 2268) | pub fn active_sigset(&self) -> Result<SignatorySet> {
method sign (line 2287) | pub fn sign(
method sigset (line 2315) | pub fn sigset(&self, index: u32) -> Result<SignatorySet> {
method num_unconfirmed (line 2322) | pub fn num_unconfirmed(&self) -> Result<u32> {
method first_unconfirmed_index (line 2343) | pub fn first_unconfirmed_index(&self) -> Result<Option<u32>> {
method unconfirmed (line 2355) | pub fn unconfirmed(&self) -> Result<Vec<Ref<'_, Checkpoint>>> {
method unconfirmed_fees_paid (line 2372) | pub fn unconfirmed_fees_paid(&self) -> Result<u64> {
method unconfirmed_vbytes (line 2382) | pub fn unconfirmed_vbytes(&self, config: &Config) -> Result<u64> {
method fee_adjustment (line 2392) | fn fee_adjustment(&self, fee_rate: u64, config: &Config) -> Result<u64> {
method backfill (line 2398) | pub fn backfill(
method pending (line 2431) | pub fn pending(&self) -> Result<Vec<(Dest, Identity, u64)>> {
method migrate_from (line 1120) | fn migrate_from(value: CheckpointQueueV1) -> OrgaResult<Self> {
type CompletedCheckpoint (line 1133) | pub struct CompletedCheckpoint<'a>(Ref<'a, Checkpoint>);
type SigningCheckpoint (line 1138) | pub struct SigningCheckpoint<'a>(Ref<'a, Checkpoint>);
type Query (line 1141) | type Query = ();
method query (line 1143) | fn query(&self, _: ()) -> OrgaResult<()> {
type SigningCheckpointMut (line 1151) | pub struct SigningCheckpointMut<'a>(ChildMut<'a, u64, Checkpoint>);
function sign (line 1160) | pub fn sign(
function advance (line 1170) | pub fn advance(self) -> Result<()> {
type BuildingCheckpoint (line 1182) | pub struct BuildingCheckpoint<'a>(Ref<'a, Checkpoint>);
type BuildingCheckpointMut (line 1187) | pub struct BuildingCheckpointMut<'a>(ChildMut<'a, u64, Checkpoint>);
type BuildingAdvanceRes (line 1190) | type BuildingAdvanceRes = (
function link_intermediate_tx (line 1203) | fn link_intermediate_tx(&mut self, tx: &mut BitcoinTx, threshold: (u64, ...
function deduct_emergency_disbursal_fees (line 1249) | fn deduct_emergency_disbursal_fees(&mut self, fee_rate: u64) -> Result<(...
function generate_emergency_disbursal_txs (line 1350) | fn generate_emergency_disbursal_txs(
function advance (line 1535) | pub fn advance(
function adjust_fee_rate (line 2444) | pub fn adjust_fee_rate(prev_fee_rate: u64, up: bool, config: &Config) ->...
function push_bitcoin_tx_output (line 2475) | fn push_bitcoin_tx_output(tx: &mut BitcoinTx, value: u64) {
function deduct_fee (line 2484) | fn deduct_fee() {
function deduct_fee_multi_pass (line 2496) | fn deduct_fee_multi_pass() {
function deduct_fee_multi_pass_empty_result (line 2509) | fn deduct_fee_multi_pass_empty_result() {
function create_queue_with_statuses (line 2520) | fn create_queue_with_statuses(complete: u32, signing: bool) -> Checkpoin...
function completed_with_signing (line 2552) | fn completed_with_signing() {
function completed_without_signing (line 2560) | fn completed_without_signing() {
function completed_no_complete (line 2568) | fn completed_no_complete() {
function completed_zero_limit (line 2575) | fn completed_zero_limit() {
function completed_oversized_limit (line 2582) | fn completed_oversized_limit() {
function completed_pruned (line 2589) | fn completed_pruned() {
function num_unconfirmed (line 2598) | fn num_unconfirmed() {
function first_unconfirmed_index (line 2625) | fn first_unconfirmed_index() {
function adjust_fee_rate (line 2652) | fn adjust_fee_rate() {
function fee_adjustments (line 2666) | fn fee_adjustments() {
function max_unconfirmed_checkpoints (line 2876) | fn max_unconfirmed_checkpoints() {
function sigset (line 3021) | fn sigset(n: u32) -> SignatorySet {
function backfill_basic (line 3047) | fn backfill_basic() {
function backfill_with_zeroth (line 3104) | fn backfill_with_zeroth() {
FILE: src/bitcoin/deposit_index.rs
type Deposit (line 8) | pub struct Deposit {
type DepositInfo (line 20) | pub struct DepositInfo {
type ReceiverIndex (line 25) | type ReceiverIndex = HashMap<String, HashMap<Address, HashMap<(Txid, u32...
type DepositIndex (line 28) | pub struct DepositIndex {
method new (line 33) | pub fn new() -> Self {
method insert_deposit (line 37) | pub fn insert_deposit(
method remove_address_index_deposit (line 51) | fn remove_address_index_deposit(
method remove_deposit (line 68) | pub fn remove_deposit(
method get_deposits_by_receiver (line 79) | pub fn get_deposits_by_receiver(
FILE: src/bitcoin/header_queue.rs
constant MAX_LENGTH (line 16) | const MAX_LENGTH: u64 = 24_192;
constant MAX_RELAY (line 17) | const MAX_RELAY: u64 = 250;
constant MAX_TIME_INCREASE (line 18) | const MAX_TIME_INCREASE: u32 = 2 * 60 * 60;
constant RETARGET_INTERVAL (line 19) | const RETARGET_INTERVAL: u32 = 2016;
constant TARGET_SPACING (line 20) | const TARGET_SPACING: u32 = 10 * 60;
constant TARGET_TIMESPAN (line 21) | const TARGET_TIMESPAN: u32 = RETARGET_INTERVAL * TARGET_SPACING;
constant MAX_TARGET (line 22) | const MAX_TARGET: u32 = 0x1d00ffff;
type WrappedHeader (line 28) | pub struct WrappedHeader {
method new (line 36) | pub fn new(header: Adapter<BlockHeader>, height: u32) -> Self {
method from_header (line 41) | pub fn from_header(header: &BlockHeader, height: u32) -> Self {
method time (line 49) | pub fn time(&self) -> u32 {
method target (line 55) | pub fn target(&self) -> Uint256 {
method block_hash (line 60) | pub fn block_hash(&self) -> BlockHash {
method prev_blockhash (line 65) | pub fn prev_blockhash(&self) -> BlockHash {
method work (line 71) | pub fn work(&self) -> Uint256 {
method height (line 76) | pub fn height(&self) -> u32 {
method bits (line 81) | pub fn bits(&self) -> u32 {
method u256_from_compact (line 86) | pub fn u256_from_compact(compact: u32) -> Uint256 {
method compact_target_from_u256 (line 91) | pub fn compact_target_from_u256(target: &Uint256) -> u32 {
method u32_to_u256 (line 96) | fn u32_to_u256(value: u32) -> Uint256 {
method validate_pow (line 106) | fn validate_pow(&self, required_target: &Uint256) -> Result<BlockHash> {
type HeaderList (line 114) | pub struct HeaderList(Vec<WrappedHeader>);
method from (line 117) | fn from(headers: Vec<WrappedHeader>) -> Self {
method from_iter (line 158) | fn from_iter<T: IntoIterator<Item = WrappedHeader>>(iter: T) -> Self {
function from (line 123) | fn from(headers: HeaderList) -> Self {
method encode_into (line 129) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> orga::encoding...
method encoding_length (line 138) | fn encoding_length(&self) -> orga::encoding::Result<usize> {
method decode (line 144) | fn decode<R: std::io::Read>(mut reader: R) -> orga::encoding::Result<Sel...
type WorkHeader (line 169) | pub struct WorkHeader {
method new (line 176) | pub fn new(header: WrappedHeader, chain_work: Uint256) -> WorkHeader {
method time (line 184) | pub fn time(&self) -> u32 {
method block_hash (line 190) | pub fn block_hash(&self) -> BlockHash {
method work (line 196) | pub fn work(&self) -> Uint256 {
method height (line 201) | pub fn height(&self) -> u32 {
method merkle_root (line 206) | pub fn merkle_root(&self) -> TxMerkleNode {
type Config (line 215) | pub struct Config {
method mainnet (line 259) | pub fn mainnet() -> Self {
method testnet (line 281) | pub fn testnet() -> Self {
method signet (line 303) | pub fn signet() -> Self {
method regtest (line 325) | pub fn regtest() -> Self {
method default (line 248) | fn default() -> Self {
type HeaderQueue (line 360) | pub struct HeaderQueue {
method add (line 406) | pub fn add(&mut self, headers: HeaderList) -> Result<()> {
method add_into_iter (line 434) | pub fn add_into_iter<T>(&mut self, headers: T) -> Result<()>
method verify_and_add_headers (line 483) | fn verify_and_add_headers(&mut self, headers: &[WrappedHeader]) -> Res...
method get_next_target (line 533) | fn get_next_target(
method calculate_next_target (line 572) | fn calculate_next_target(
method pop_back_to (line 620) | fn pop_back_to(&mut self, height: u32) -> Result<Uint256> {
method validate_time (line 636) | fn validate_time(&self, current_header: &WrappedHeader) -> Result<()> {
method height (line 678) | pub fn height(&self) -> Result<u32> {
method hash (line 687) | pub fn hash(&self) -> Result<Vec<u8>> {
method len (line 697) | pub fn len(&self) -> u64 {
method is_empty (line 705) | pub fn is_empty(&self) -> bool {
method get_by_height (line 717) | pub fn get_by_height(&self, height: u32) -> Result<Option<WorkHeader>> {
method trusted_height (line 739) | pub fn trusted_height(&self) -> u32 {
method configure (line 745) | pub fn configure(&mut self, config: Config) -> OrgaResult<()> {
method network (line 768) | pub fn network(&self) -> bitcoin::Network {
method migrate_from (line 367) | fn migrate_from(_value: HeaderQueueV0) -> OrgaResult<Self> {
method default (line 373) | fn default() -> Self {
function primitive_adapter_encode_decode (line 787) | fn primitive_adapter_encode_decode() {
function add_multiple (line 815) | fn add_multiple() {
function add_into_iterator (line 974) | fn add_into_iterator() {
function add_wrong_bits_non_retarget (line 1022) | fn add_wrong_bits_non_retarget() {
FILE: src/bitcoin/mod.rs
type Nbtc (line 58) | pub struct Nbtc(());
constant INDEX (line 60) | const INDEX: u8 = 21;
constant NAME (line 61) | const NAME: &'static str = "usat";
constant NETWORK (line 70) | pub const NETWORK: ::bitcoin::Network = ::bitcoin::Network::Bitcoin;
constant NETWORK (line 72) | pub const NETWORK: ::bitcoin::Network = ::bitcoin::Network::Signet;
constant NETWORK (line 74) | pub const NETWORK: ::bitcoin::Network = ::bitcoin::Network::Testnet;
constant NETWORK (line 76) | pub const NETWORK: ::bitcoin::Network = ::bitcoin::Network::Regtest;
constant SIGSET_THRESHOLD (line 80) | pub const SIGSET_THRESHOLD: (u64, u64) = (9, 10);
constant SIGSET_THRESHOLD (line 82) | pub const SIGSET_THRESHOLD: (u64, u64) = (2, 3);
type Config (line 86) | pub struct Config {
method bitcoin (line 153) | fn bitcoin() -> Self {
method regtest (line 178) | fn regtest() -> Self {
method migrate_from (line 132) | fn migrate_from(value: ConfigV3) -> OrgaResult<Self> {
method default (line 190) | fn default() -> Self {
function matches_bitcoin_network (line 198) | pub fn matches_bitcoin_network(network: &bitcoin::Network) -> bool {
function calc_bridge_deposit_fee (line 212) | pub fn calc_bridge_deposit_fee(amount: u64) -> u64 {
type Bitcoin (line 224) | pub struct Bitcoin {
method configure (line 392) | pub fn configure(&mut self, config: Config) {
method config (line 397) | pub fn config() -> Config {
method set_signatory_key (line 407) | pub fn set_signatory_key(&mut self, _signatory_key: Xpub) -> Result<()> {
method set_recovery_script (line 442) | pub fn set_recovery_script(&mut self, signatory_script: Adapter<Script...
method should_push_checkpoint (line 467) | pub fn should_push_checkpoint(&mut self) -> Result<bool> {
method amount_after_deposit_fee (line 473) | pub fn amount_after_deposit_fee(
method relay_deposit (line 525) | pub fn relay_deposit(
method relay_checkpoint (line 680) | pub fn relay_checkpoint(
method withdraw (line 740) | pub fn withdraw(&mut self, script_pubkey: Adapter<Script>, amount: Amo...
method withdrawal_fee_amount (line 754) | pub fn withdrawal_fee_amount(&self, script_len: u64) -> Result<u64> {
method validate_withdrawal (line 762) | pub fn validate_withdrawal(
method add_withdrawal (line 808) | pub fn add_withdrawal(
method insert_pending (line 845) | pub fn insert_pending(
method transfer (line 866) | pub fn transfer(&mut self, to: Address, amount: Amount) -> Result<()> {
method sign (line 891) | pub fn sign(
method value_locked (line 904) | pub fn value_locked(&self) -> Result<u64> {
method network (line 911) | pub fn network(&self) -> bitcoin::Network {
method change_rates (line 922) | pub fn change_rates(&self, interval: u64, now: u64, reset_index: u32) ...
method begin_block_step (line 997) | pub fn begin_block_step(
method offline_signers (line 1050) | fn offline_signers(&mut self) -> Result<Vec<ConsensusKey>> {
method take_pending (line 1101) | pub fn take_pending(&mut self) -> Result<Vec<(Dest, Coin<Nbtc>, Identi...
method give_miner_fee (line 1125) | pub fn give_miner_fee(&mut self, coin: Coin<Nbtc>) -> Result<()> {
method give_rewards (line 1135) | pub fn give_rewards(&mut self, coin: Coin<Nbtc>) -> Result<()> {
method give_funding_to_fee_pool (line 1158) | pub fn give_funding_to_fee_pool(&mut self, amount: Amount) -> Result<(...
method transfer_to_fee_pool (line 1168) | pub fn transfer_to_fee_pool(&mut self, amount: Amount) -> Result<()> {
method migrate_from (line 270) | fn migrate_from(value: BitcoinV1) -> OrgaResult<Self> {
type ConsensusKey (line 287) | pub type ConsensusKey = [u8; 32];
type Xpub (line 293) | pub struct Xpub {
method new (line 309) | pub fn new(key: ExtendedPubKey) -> Self {
method inner (line 314) | pub fn inner(&self) -> &ExtendedPubKey {
method from (line 367) | fn from(key: ExtendedPubKey) -> Self {
method from (line 373) | fn from(key: &ExtendedPubKey) -> Self {
method describe (line 300) | fn describe() -> orga::describe::Descriptor {
constant XPUB_LENGTH (line 305) | pub const XPUB_LENGTH: usize = 78;
method attach (line 321) | fn attach(&mut self, _: Store) -> OrgaResult<()> {
method flush (line 326) | fn flush<W: std::io::Write>(self, out: &mut W) -> OrgaResult<()> {
method load (line 330) | fn load(_store: Store, bytes: &mut &[u8]) -> OrgaResult<Self> {
type Target (line 336) | type Target = ExtendedPubKey;
method deref (line 338) | fn deref(&self) -> &Self::Target {
method encode_into (line 344) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 350) | fn encoding_length(&self) -> ed::Result<usize> {
method decode (line 356) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
function exempt_from_fee (line 380) | pub fn exempt_from_fee() -> Result<()> {
type ChangeRates (line 1192) | pub struct ChangeRates {
type SignatoryKeys (line 1203) | pub struct SignatoryKeys {
method reset (line 1211) | pub fn reset(&mut self) -> OrgaResult<()> {
method map (line 1227) | pub fn map(&self) -> &Map<ConsensusKey, Xpub> {
method insert (line 1233) | pub fn insert(&mut self, consensus_key: ConsensusKey, xpub: Xpub) -> R...
method get (line 1252) | pub fn get(&self, cons_key: ConsensusKey) -> Result<Option<Xpub>> {
function clear_map (line 1258) | fn clear_map<K, V>(map: &mut Map<K, V>) -> OrgaResult<()>
function clear_deque (line 1277) | fn clear_deque<V>(deque: &mut Deque<V>) -> OrgaResult<()>
function relay_height_validity (line 1305) | fn relay_height_validity() {
function check_change_rates (line 1366) | fn check_change_rates() -> Result<()> {
FILE: src/bitcoin/outpoint_set.rs
type Outpoint (line 4) | pub type Outpoint = ([u8; 32], u32);
type OutpointSet (line 19) | pub struct OutpointSet {
method reset (line 30) | pub fn reset(&mut self) -> Result<()> {
method contains (line 39) | pub fn contains(&self, outpoint: Outpoint) -> Result<bool> {
method insert (line 45) | pub fn insert(&mut self, outpoint: Outpoint, expiration: u64) -> Resul...
method remove_expired (line 52) | pub fn remove_expired(&mut self, now: u64) -> Result<()> {
FILE: src/bitcoin/recovery.rs
type RecoveryTx (line 16) | pub struct RecoveryTx {
type SignedRecoveryTx (line 24) | pub struct SignedRecoveryTx {
type RecoveryTxs (line 31) | pub struct RecoveryTxs {
method new (line 47) | pub fn new() -> Self {
method create_recovery_tx (line 51) | pub fn create_recovery_tx(&mut self, args: RecoveryTxInput) -> Result<...
method to_sign (line 93) | pub fn to_sign(&self, xpub: Xpub) -> Result<Vec<([u8; 32], u32)>> {
method sign (line 114) | fn sign(&mut self, xpub: Xpub, sigs: LengthVec<u16, Signature>) -> Res...
method signed (line 168) | pub fn signed(&self) -> Result<Vec<SignedRecoveryTx>> {
type RecoveryTxInput (line 35) | pub struct RecoveryTxInput<'a> {
FILE: src/bitcoin/relayer.rs
function warp_reply_json (line 33) | pub fn warp_reply_json<T>(val: T) -> Json
constant HEADER_BATCH_SIZE (line 40) | const HEADER_BATCH_SIZE: usize = 250;
type DepositsQuery (line 43) | pub struct DepositsQuery {
type SigsetQuery (line 48) | pub struct SigsetQuery {
type Relayer (line 52) | pub struct Relayer {
method new (line 61) | pub fn new(btc_client: BitcoinRpcClient, app_client_addr: String) -> S...
method sidechain_block_hash (line 70) | async fn sidechain_block_hash(&self) -> Result<BlockHash> {
method btc_client (line 78) | async fn btc_client(&self) -> RwLockReadGuard<BitcoinRpcClient> {
method start_header_relay (line 82) | pub async fn start_header_relay(&mut self) -> Result<()> {
method relay_headers (line 94) | async fn relay_headers(&mut self) -> Result<()> {
method start_deposit_relay (line 124) | pub async fn start_deposit_relay<P: AsRef<Path>>(
method create_address_server (line 170) | fn create_address_server(
method relay_deposits (line 377) | async fn relay_deposits(
method scan_for_deposits (line 408) | async fn scan_for_deposits(
method scan_for_mempool_deposits (line 440) | async fn scan_for_mempool_deposits(
method miner_fee_rate (line 507) | pub async fn miner_fee_rate(&self, sigset_index: u32) -> Result<f64> {
method bridge_fee_rate (line 524) | pub fn bridge_fee_rate(&self, dest: &Dest, _sigset_index: u32) -> Resu...
method start_emergency_disbursal_transaction_relay (line 539) | pub async fn start_emergency_disbursal_transaction_relay(&mut self) ->...
method relay_emergency_disbursal_transactions (line 553) | async fn relay_emergency_disbursal_transactions(&mut self) -> Result<(...
method start_checkpoint_relay (line 602) | pub async fn start_checkpoint_relay(&mut self) -> Result<()> {
method relay_checkpoints (line 615) | async fn relay_checkpoints(&mut self) -> Result<()> {
method start_recovery_tx_relay (line 662) | pub async fn start_recovery_tx_relay<P: AsRef<Path>>(&mut self, store_...
method relay_recovery_txs (line 677) | async fn relay_recovery_txs(&mut self) -> Result<()> {
method start_checkpoint_conf_relay (line 740) | pub async fn start_checkpoint_conf_relay(&mut self) -> Result<()> {
method relay_checkpoint_confs (line 752) | async fn relay_checkpoint_confs(&mut self) -> Result<()> {
method scan_for_txid (line 832) | async fn scan_for_txid(
method insert_announced_addrs (line 858) | async fn insert_announced_addrs(&self, recv: &mut Receiver<(Dest, u32)...
method last_n_blocks (line 887) | pub async fn last_n_blocks(&self, n: usize, hash: BlockHash) -> Result...
method relevant_txs (line 908) | pub async fn relevant_txs<'a>(
method relevant_outputs (line 921) | pub async fn relevant_outputs<'a>(
method maybe_relay_deposit (line 948) | async fn maybe_relay_deposit(
method relay_header_batch (line 1051) | async fn relay_header_batch(
method get_header_batch (line 1098) | async fn get_header_batch(&self, from_hash: BlockHash) -> Result<Vec<W...
method common_ancestor (line 1136) | async fn common_ancestor(&self, a: BlockHash, b: BlockHash) -> Result<...
type DepositAddress (line 1159) | pub struct DepositAddress {
type OutputMatch (line 1164) | pub struct OutputMatch {
type BridgeFeeOverrides (line 1170) | pub struct BridgeFeeOverrides {
method default (line 1176) | fn default() -> Self {
type RawSignatorySet (line 1185) | pub struct RawSignatorySet {
method new (line 1201) | pub fn new(
type RawSignatory (line 1237) | pub struct RawSignatory {
method from (line 1243) | fn from(sig: Signatory) -> Self {
type WatchedScripts (line 1254) | pub struct WatchedScripts {
method new (line 1260) | pub fn new() -> Self {
method get (line 1264) | pub fn get(&self, script: &::bitcoin::Script) -> Option<(Dest, u32)> {
method has (line 1268) | pub fn has(&self, script: &::bitcoin::Script) -> bool {
method len (line 1272) | pub fn len(&self) -> usize {
method is_empty (line 1276) | pub fn is_empty(&self) -> bool {
method insert (line 1280) | pub fn insert(&mut self, dest: Dest, sigset: &SignatorySet) -> Result<...
method remove_expired (line 1298) | pub fn remove_expired(&mut self, max_age: u64) -> Result<()> {
method derive_script (line 1315) | fn derive_script(
type WatchedScriptStore (line 1329) | pub struct WatchedScriptStore {
method open (line 1335) | pub async fn open<P: AsRef<Path>>(path: P, app_client_addr: &str) -> R...
method maybe_load (line 1357) | async fn maybe_load<P: AsRef<Path>>(
method insert (line 1406) | pub fn insert(&mut self, dest: Dest, sigset: &SignatorySet) -> Result<...
method write (line 1414) | fn write(file: &mut File, dest: &Dest, sigset_index: u32) -> Result<()> {
function relayer_fetch_batch (line 1429) | async fn relayer_fetch_batch() {
function relayer_seek_uneven_batch (line 1461) | async fn relayer_seek_uneven_batch() {
FILE: src/bitcoin/signatory.rs
constant MAX_SIGNATORIES (line 50) | pub const MAX_SIGNATORIES: u64 = 20;
type Signatory (line 55) | pub struct Signatory {
function derive_pubkey (line 62) | pub fn derive_pubkey<T>(secp: &Secp256k1<T>, xpub: Xpub, sigset_index: u...
type SignatorySet (line 84) | pub struct SignatorySet {
method from_validator_ctx (line 111) | pub fn from_validator_ctx(index: u32, sig_keys: &Map<ConsensusKey, Xpu...
method from_script (line 162) | pub fn from_script(
method insert (line 331) | fn insert(&mut self, signatory: Signatory) {
method sort_and_truncate (line 339) | fn sort_and_truncate(&mut self) {
method signature_threshold (line 351) | pub fn signature_threshold(&self, (numerator, denominator): (u64, u64)...
method quorum_threshold (line 356) | pub fn quorum_threshold(&self) -> u64 {
method present_vp (line 362) | pub fn present_vp(&self) -> u64 {
method possible_vp (line 369) | pub fn possible_vp(&self) -> u64 {
method has_quorum (line 378) | pub fn has_quorum(&self) -> bool {
method len (line 385) | pub fn len(&self) -> usize {
method is_empty (line 390) | pub fn is_empty(&self) -> bool {
method redeem_script (line 401) | pub fn redeem_script(&self, dest: &[u8], threshold: (u64, u64)) -> Res...
method output_script (line 473) | pub fn output_script(&self, dest: &[u8], threshold: (u64, u64)) -> Res...
method get_truncation (line 480) | fn get_truncation(&self, target_precision: u32) -> u32 {
method create_time (line 486) | pub fn create_time(&self) -> u64 {
method index (line 491) | pub fn index(&self) -> u32 {
method iter (line 496) | pub fn iter(&self) -> impl Iterator<Item = &Signatory> {
method est_witness_vsize (line 507) | pub fn est_witness_vsize(&self) -> u64 {
function from_script (line 629) | fn from_script() {
FILE: src/bitcoin/signer.rs
function load_xpriv (line 56) | pub fn load_xpriv<P: AsRef<Path> + Clone>(path: P) -> Result<ExtendedPri...
type Signer (line 70) | pub struct Signer<W, F> {
function load_xprivs (line 111) | pub fn load_xprivs<P: AsRef<Path> + Clone>(
function new (line 168) | pub fn new(
function start (line 194) | pub async fn start(self) -> Result<()> {
function start_checkpoint_signing (line 249) | pub async fn start_checkpoint_signing(
function start_recovery_signing (line 296) | pub async fn start_recovery_signing(
function client (line 318) | pub fn client(&self) -> AppClient<InnerApp, InnerApp, HttpClient, Nom, W> {
function try_sign_checkpoint (line 332) | async fn try_sign_checkpoint(
function try_sign_recovery_txs (line 414) | async fn try_sign_recovery_txs(
function check_change_rates (line 449) | async fn check_change_rates(&self) -> Result<()> {
function sign (line 494) | pub fn sign(
function signer_default_path (line 523) | fn signer_default_path() {
function signer_primary_path (line 549) | fn signer_primary_path() {
function signer_provided_primary_path_non_existent (line 576) | fn signer_provided_primary_path_non_existent() {
function signer_additional_paths (line 593) | fn signer_additional_paths() {
FILE: src/bitcoin/threshold_sig.rs
type Message (line 20) | pub type Message = [u8; MESSAGE_SIZE];
type Signature (line 40) | pub struct Signature(
type Pubkey (line 47) | pub struct Pubkey {
method new (line 65) | pub fn new(pubkey: [u8; PUBLIC_KEY_SIZE]) -> Result<Self> {
method try_from_slice (line 81) | pub fn try_from_slice(bytes: &[u8]) -> Result<Self> {
method as_slice (line 93) | pub fn as_slice(&self) -> &[u8] {
method from (line 105) | fn from(pubkey: PublicKey) -> Self {
method default (line 53) | fn default() -> Self {
method migrate_from (line 99) | fn migrate_from(value: PubkeyV0) -> Result<Self> {
type ThresholdSig (line 118) | pub struct ThresholdSig {
method new (line 141) | pub fn new() -> Self {
method len (line 147) | pub fn len(&self) -> u16 {
method set_message (line 152) | pub fn set_message(&mut self, message: Message) {
method clear_sigs (line 157) | pub fn clear_sigs(&mut self) -> Result<()> {
method message (line 176) | pub fn message(&self) -> Message {
method from_sigset (line 182) | pub fn from_sigset(signatories: &SignatorySet) -> Result<Self> {
method from_shares (line 211) | pub fn from_shares(shares: Vec<(Pubkey, Share)>) -> Result<Self> {
method signed (line 234) | pub fn signed(&self) -> bool {
method sigs (line 241) | pub fn sigs(&self) -> Result<Vec<(Pubkey, Signature)>> {
method shares (line 257) | pub fn shares(&self) -> Result<Vec<(Pubkey, Share)>> {
method contains_key (line 267) | pub fn contains_key(&self, pubkey: Pubkey) -> Result<bool> {
method needs_sig (line 275) | pub fn needs_sig(&self, pubkey: Pubkey) -> Result<bool> {
method sign (line 288) | pub fn sign(&mut self, pubkey: Pubkey, sig: Signature) -> Result<()> {
method verify (line 313) | pub fn verify(&self, pubkey: Pubkey, sig: Signature) -> crate::error::...
method to_witness (line 334) | pub fn to_witness(&self) -> crate::error::Result<Vec<Vec<u8>>> {
method fmt (line 360) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type Share (line 375) | pub struct Share {
FILE: src/cosmos.rs
constant MAX_SIGSET_SIZE (line 53) | pub const MAX_SIGSET_SIZE: usize = 40;
constant RECOVERY_THRESHOLD (line 54) | pub const RECOVERY_THRESHOLD: (u64, u64) = (2, 3);
type Cosmos (line 57) | pub struct Cosmos {
method op_key_present (line 64) | pub fn op_key_present(&self, client_id: ClientId, cons_key: LengthVec<...
method build_outputs (line 72) | pub fn build_outputs(&self, ibc: &Ibc, index: u32) -> Result<Vec<bitco...
method relay_op_key (line 132) | pub fn relay_op_key(
function tmhash (line 217) | pub fn tmhash(bytes: &[u8]) -> [u8; 20] {
type Proof (line 229) | pub struct Proof {
method verify (line 276) | pub fn verify(&self, root: &CommitmentRoot, store: &str) -> Result<()> {
method key (line 301) | pub fn key(&self) -> Result<&Vec<u8>> {
method value (line 305) | pub fn value(&self) -> Result<&Vec<u8>> {
method outer_proof (line 309) | pub fn outer_proof(&self) -> Result<&ExistenceProof> {
method inner_proof (line 322) | pub fn inner_proof(&self) -> Result<&ExistenceProof> {
method encode_into (line 235) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 252) | fn encoding_length(&self) -> ed::Result<usize> {
method decode (line 262) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
type Chain (line 337) | pub struct Chain {
method to_sigset (line 343) | pub fn to_sigset(&self, index: u32, client: &Client) -> Result<Option<...
function relay_op_keys (line 397) | pub async fn relay_op_keys<
function proof_ok (line 527) | fn proof_ok() {
FILE: src/error.rs
type Error (line 8) | pub enum Error {
method from (line 79) | fn from(_: warp::Rejection) -> Self {
function from (line 88) | fn from(err: Error) -> Self {
type Result (line 97) | pub type Result<T> = std::result::Result<T, Error>;
FILE: src/ethereum/consensus/mod.rs
type LightClient (line 41) | pub struct LightClient {
method new (line 49) | pub fn new(bootstrap: Bootstrap, network: Network) -> Result<Self> {
method update (line 69) | pub fn update(&mut self, update: Update, now_seconds: u64) -> Result<(...
method slot (line 92) | pub fn slot(&self) -> u64 {
method block_number (line 97) | pub fn block_number(&self) -> u64 {
method state_root (line 108) | pub fn state_root(&self) -> Bytes32 {
method light_client_store (line 120) | pub fn light_client_store(&self) -> &LightClientStore {
method attach (line 126) | fn attach(&mut self, _store: orga::prelude::Store) -> orga::Result<()> {
method field_keyop (line 130) | fn field_keyop(_field_name: &str) -> Option<orga::describe::KeyOp> {
method flush (line 135) | fn flush<W: std::io::Write>(self, out: &mut W) -> orga::Result<()> {
method load (line 139) | fn load(_store: orga::prelude::Store, bytes: &mut &[u8]) -> orga::Result...
method migrate (line 145) | fn migrate(
type FieldCall (line 155) | type FieldCall = ();
method field_call (line 157) | fn field_call(&mut self, _call: ()) -> orga::Result<()> {
type FieldQuery (line 163) | type FieldQuery = ();
method field_query (line 165) | fn field_query(&self, _query: ()) -> orga::Result<()> {
type Target (line 171) | type Target = LightClientStore;
method deref (line 173) | fn deref(&self) -> &Self::Target {
method deref_mut (line 179) | fn deref_mut(&mut self) -> &mut Self::Target {
method encode_into (line 185) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 200) | fn encoding_length(&self) -> ed::Result<usize> {
method decode (line 223) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
method describe (line 249) | fn describe() -> orga::describe::Descriptor {
type Network (line 256) | pub struct Network {
method ethereum_mainnet (line 264) | pub fn ethereum_mainnet() -> Self {
method ethereum_sepolia (line 275) | pub fn ethereum_sepolia() -> Self {
type Update (line 289) | pub struct Update {
method encode_into (line 301) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 309) | fn encoding_length(&self) -> ed::Result<usize> {
method decode (line 316) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
type Error (line 331) | type Error = crate::error::Error;
method try_from (line 333) | fn try_from(value: Update) -> Result<Self> {
method from (line 371) | fn from(value: Update) -> Self {
function serialize (line 394) | pub fn serialize<S>(value: &u64, serializer: S) -> Result<S::Ok, S::Error>
function deserialize (line 401) | pub fn deserialize<'de, D>(deserializer: D) -> Result<u64, D::Error>
type Bootstrap (line 411) | pub struct Bootstrap {
method from (line 418) | fn from(value: Bootstrap) -> Self {
type LightClientHeader (line 436) | pub struct LightClientHeader(HeliosLightClientHeader);
method into_inner (line 439) | pub fn into_inner(self) -> HeliosLightClientHeader {
type Target (line 445) | type Target = HeliosLightClientHeader;
method deref (line 447) | fn deref(&self) -> &Self::Target {
method deref_mut (line 453) | fn deref_mut(&mut self) -> &mut Self::Target {
method encode_into (line 459) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 463) | fn encoding_length(&self) -> ed::Result<usize> {
function encode_lc_header (line 471) | pub fn encode_lc_header<W: std::io::Write>(
method decode (line 495) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
type ExecutionPayloadHeader (line 529) | pub struct ExecutionPayloadHeader(HeliosExecutionPayloadHeader);
method into_inner (line 532) | pub fn into_inner(self) -> HeliosExecutionPayloadHeader {
type Target (line 538) | type Target = HeliosExecutionPayloadHeader;
method deref (line 540) | fn deref(&self) -> &Self::Target {
method deref_mut (line 546) | fn deref_mut(&mut self) -> &mut Self::Target {
method encode_into (line 552) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 556) | fn encoding_length(&self) -> ed::Result<usize> {
function encode_ep_header (line 564) | fn encode_ep_header<W: std::io::Write>(
method decode (line 595) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
type BeaconBlockHeader (line 642) | pub struct BeaconBlockHeader(HeliosBeaconBlockHeader);
method into_inner (line 645) | pub fn into_inner(self) -> HeliosBeaconBlockHeader {
type Target (line 651) | type Target = HeliosBeaconBlockHeader;
method deref (line 653) | fn deref(&self) -> &Self::Target {
method deref_mut (line 659) | fn deref_mut(&mut self) -> &mut Self::Target {
method encode_into (line 665) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 669) | fn encoding_length(&self) -> ed::Result<usize> {
function encode_bb_header (line 674) | pub fn encode_bb_header<W: std::io::Write>(
method decode (line 686) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
type SyncCommittee (line 707) | pub struct SyncCommittee(HeliosSyncCommittee);
method into_inner (line 710) | pub fn into_inner(self) -> HeliosSyncCommittee {
type Target (line 716) | type Target = HeliosSyncCommittee;
method deref (line 718) | fn deref(&self) -> &Self::Target {
method deref_mut (line 724) | fn deref_mut(&mut self) -> &mut Self::Target {
method encode_into (line 730) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 734) | fn encoding_length(&self) -> ed::Result<usize> {
function encode_sync_committee (line 739) | pub fn encode_sync_committee<W: std::io::Write>(
method decode (line 750) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
type SyncAggregate (line 768) | pub struct SyncAggregate(HeliosSyncAggregate);
method into_inner (line 771) | pub fn into_inner(self) -> HeliosSyncAggregate {
type Target (line 777) | type Target = HeliosSyncAggregate;
method deref (line 779) | fn deref(&self) -> &Self::Target {
method deref_mut (line 785) | fn deref_mut(&mut self) -> &mut Self::Target {
method encode_into (line 791) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 795) | fn encoding_length(&self) -> ed::Result<usize> {
function encode_sync_aggregate (line 800) | pub fn encode_sync_aggregate<W: std::io::Write>(
method decode (line 809) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
type PublicKey (line 826) | pub struct PublicKey(HeliosPublicKey);
method into_inner (line 829) | pub fn into_inner(self) -> HeliosPublicKey {
method from (line 835) | fn from(value: HeliosPublicKey) -> Self {
type Target (line 841) | type Target = HeliosPublicKey;
method deref (line 843) | fn deref(&self) -> &Self::Target {
method deref_mut (line 849) | fn deref_mut(&mut self) -> &mut Self::Target {
method encode (line 855) | fn encode(&self) -> ed::Result<Vec<u8>> {
method encode_into (line 859) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 864) | fn encoding_length(&self) -> ed::Result<usize> {
function encode_public_key (line 869) | fn encode_public_key<W: std::io::Write>(pk: &HeliosPublicKey, dest: &mut...
method decode (line 874) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
type Signature (line 888) | pub struct Signature(HeliosSignature);
method into_inner (line 891) | pub fn into_inner(self) -> HeliosSignature {
method from (line 897) | fn from(value: HeliosSignature) -> Self {
type Target (line 903) | type Target = HeliosSignature;
method deref (line 905) | fn deref(&self) -> &Self::Target {
method deref_mut (line 911) | fn deref_mut(&mut self) -> &mut Self::Target {
method encode (line 917) | fn encode(&self) -> ed::Result<Vec<u8>> {
method encode_into (line 921) | fn encode_into<W: std::io::Write>(&self, dest: &mut W) -> ed::Result<()> {
method encoding_length (line 926) | fn encoding_length(&self) -> ed::Result<usize> {
function encode_signature (line 931) | fn encode_signature<W: std::io::Write>(sig: &HeliosSignature, dest: &mut...
method decode (line 936) | fn decode<R: std::io::Read>(mut input: R) -> ed::Result<Self> {
type Bytes32 (line 951) | pub struct Bytes32(#[serde(with = "SerHex::<StrictPfx>")] pub [u8; 32]);
method into_inner (line 954) | pub fn into_inner(self) -> [u8; 32] {
method from (line 960) | fn from(value: [u8; 32]) -> Self {
method fmt (line 966) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type Err (line 972) | type Err = crate::error::Error;
method from_str (line 974) | fn from_str(s: &str) -> Result<Self> {
function encode_decode (line 992) | fn encode_decode() {
function serialize_deserialize (line 1003) | fn serialize_deserialize() {
function update (line 1016) | async fn update() {
FILE: src/ethereum/consensus/relayer.rs
function get_updates (line 18) | pub async fn get_updates<C: OrgaClient<LightClient>>(
type RpcClient (line 52) | pub struct RpcClient {
method new (line 58) | pub fn new(rpc_addr: String) -> Self {
method get_updates (line 64) | pub async fn get_updates(
method get_finality_update (line 84) | pub async fn get_finality_update(&self) -> Result<Response<Update>> {
method block_root (line 100) | pub async fn block_root(&self, slot: u64) -> Result<Response<Root>> {
method bootstrap (line 113) | pub async fn bootstrap(&self, block_root: Bytes32) -> Result<Response<...
type Response (line 131) | pub struct Response<T> {
type Root (line 138) | pub struct Root {
function get_updates (line 147) | async fn get_updates() {
FILE: src/ethereum/mod.rs
constant VALSET_INTERVAL (line 75) | pub const VALSET_INTERVAL: u64 = 60 * 60 * 24;
constant GAS_PRICE (line 77) | pub const GAS_PRICE: u64 = 160_000;
constant APPROX_TRANSFER_GAS (line 80) | pub const APPROX_TRANSFER_GAS: u64 = 80_000;
constant APPROX_CALL_GAS (line 83) | pub const APPROX_CALL_GAS: u64 = 100_000;
type Ethereum (line 87) | pub struct Ethereum {
method step (line 96) | pub fn step(&mut self, active_sigset: &SignatorySet) -> Result<()> {
method take_pending (line 114) | pub fn take_pending(&mut self) -> Result<Vec<(Dest, Coin<Nbtc>, Identi...
method relay_consensus_update (line 132) | pub fn relay_consensus_update(
method relay_return (line 152) | pub fn relay_return(
method sign (line 179) | pub fn sign(
method create_connection (line 203) | pub fn create_connection(
method to_sign (line 232) | pub fn to_sign(&self, xpub: Xpub) -> Result<ToSign> {
method network (line 269) | pub fn network(&self, network: u32) -> Result<Ref<Network>> {
method network_mut (line 277) | pub fn network_mut(&mut self, network: u32) -> Result<ChildMut<u32, Ne...
method now (line 286) | fn now(&mut self) -> Result<i64> {
method token_contract (line 296) | pub fn token_contract(&self, network: u32, connection: Address) -> Res...
method message_index (line 307) | pub fn message_index(&self, network: u32, connection: Address) -> Resu...
method return_index (line 318) | pub fn return_index(&self, network: u32, connection: Address) -> Resul...
method signed (line 329) | pub fn signed(&self, network: u32, connection: Address, msg_index: u64...
method msd (line 342) | pub fn msd(
method block_number (line 360) | pub fn block_number(&self, network: u32) -> Result<u64> {
method light_client (line 369) | pub fn light_client(&self, chain_id: u32) -> Result<LightClient> {
type ToSign (line 378) | type ToSign = Vec<(u32, Address, u64, u32, [u8; 32], OutMessageArgs)>;
type Sigs (line 379) | type Sigs = Vec<(Pubkey, Option<Signature>)>;
type Network (line 382) | pub struct Network {
method new (line 392) | pub fn new(
method step (line 408) | pub fn step(&mut self, active_sigset: &SignatorySet) -> Result<()> {
method take_pending (line 426) | pub fn take_pending(&mut self) -> Result<Vec<(Dest, Coin<Nbtc>, Identi...
method connection (line 441) | pub fn connection(&self, connection: Address) -> Result<Ref<Connection...
method connection_mut (line 449) | pub fn connection_mut(&mut self, connection: Address) -> Result<ChildM...
type Connection (line 466) | pub struct Connection {
method new (line 508) | pub fn new(
method step (line 538) | pub fn step(&mut self, active_sigset: &SignatorySet) -> Result<()> {
method validate_transfer (line 549) | pub fn validate_transfer(&self, dest: Address, amount: u64) -> Result<...
method transfer (line 564) | pub fn transfer(&mut self, dest: Address, coins: Coin<Nbtc>) -> Result...
method validate_contract_call (line 592) | pub fn validate_contract_call(
method call_contract (line 611) | pub fn call_contract(
method update_valset (line 641) | fn update_valset(&mut self, mut new_valset: SignatorySet) -> Result<()> {
method push_outbox (line 654) | fn push_outbox(&mut self, msg: OutMessageArgs) -> Result<()> {
method take_pending (line 674) | pub fn take_pending(&mut self) -> Result<Vec<(Dest, Coin<Nbtc>, Identi...
method sign (line 685) | pub fn sign(&mut self, msg_index: u64, pubkey: Pubkey, sig: Signature)...
method relay_return (line 695) | pub fn relay_return(
method adjust_emergency_disbursal_balance (line 743) | pub fn adjust_emergency_disbursal_balance(
method get (line 781) | pub fn get(&self, msg_index: u64) -> Result<Ref<OutMessage>> {
method get_mut (line 787) | pub fn get_mut(&mut self, msg_index: u64) -> Result<ChildMut<u64, OutM...
method abs_index (line 795) | pub fn abs_index(&self, msg_index: u64) -> Result<u64> {
method message_hash (line 805) | fn message_hash(&self, msg: &OutMessageArgs) -> [u8; 32] {
method needs_sig (line 847) | pub fn needs_sig(&self, msg_index: u64, pubkey: Pubkey) -> Result<bool> {
method get_sigs (line 851) | pub fn get_sigs(&self, msg_index: u64) -> Result<Vec<(Pubkey, Option<S...
type OutMessage (line 873) | pub struct OutMessage {
type OutMessageArgs (line 882) | pub enum OutMessageArgs {
method field_query (line 908) | fn field_query(&self, _query: Self::FieldQuery) -> orga::Result<()> {
method method_query (line 913) | fn method_query(&self, _query: Self::MethodQuery) -> orga::Result<()> {
method default (line 918) | fn default() -> Self {
method attach (line 928) | fn attach(&mut self, _store: Store) -> orga::Result<()> {
method field_keyop (line 931) | fn field_keyop(_field_name: &str) -> Option<orga::describe::KeyOp> {
method flush (line 934) | fn flush<W: std::io::Write>(self, out: &mut W) -> orga::Result<()> {
method load (line 937) | fn load(_store: Store, bytes: &mut &[u8]) -> orga::Result<Self> {
method migrate (line 942) | fn migrate(_src: Store, _dest: Store, bytes: &mut &[u8]) -> orga::Result...
method describe (line 947) | fn describe() -> orga::describe::Descriptor {
function call_hash (line 955) | pub fn call_hash(
function logic_call_args (line 992) | pub fn logic_call_args(
type Transfer (line 1020) | pub struct Transfer {
function checkpoint_hash (line 1027) | pub fn checkpoint_hash(
function batch_hash (line 1057) | pub fn batch_hash(
function sighash (line 1089) | pub fn sighash(message: [u8; 32]) -> [u8; 32] {
function to_eth_sig (line 1098) | pub fn to_eth_sig(
function bytes32 (line 1129) | pub fn bytes32(bytes: &[u8]) -> Result<[u8; 32]> {
function uint256 (line 1140) | pub fn uint256(n: u64) -> [u8; 32] {
function addr_to_bytes32 (line 1147) | pub fn addr_to_bytes32(addr: Address) -> [u8; 32] {
method eth_addresses (line 1155) | pub fn eth_addresses(&self) -> Vec<Address> {
method normalize_vp (line 1169) | pub fn normalize_vp(&mut self, total: u64) {
method to_abi (line 1182) | pub fn to_abi(&self, nonce: u64) -> ValsetArgs {
function checkpoint_fixture (line 1228) | fn checkpoint_fixture() {
function indices (line 1284) | fn indices() {
function ss_normalize_vp (line 1341) | fn ss_normalize_vp() {
function valset_update (line 1381) | async fn valset_update() {
function create_connection (line 1496) | fn create_connection() -> Result<()> {
function transfer (line 1541) | async fn transfer() {
function contract_call (line 1721) | async fn contract_call() {
function return_queue (line 1879) | async fn return_queue() {
FILE: src/ethereum/proofs.rs
type Account (line 21) | struct Account {
type EncodedProof (line 31) | type EncodedProof = LengthVec<u8, LengthVec<u16, u8>>;
type IndexProof (line 33) | type IndexProof = LengthVec<u8, EncodedProof>;
type StateProof (line 37) | pub struct StateProof {
method from_response (line 47) | pub fn from_response(
method verify (line 99) | pub fn verify(self, state_root: [u8; 32]) -> AppResult<Vec<BridgeContr...
function verify_key (line 203) | fn verify_key(root: [u8; 32], key: &[u8], proof: &EncodedProof) -> AppRe...
type BridgeContractData (line 218) | pub struct BridgeContractData {
constant RETURN_DESTS_SLOT (line 227) | pub const RETURN_DESTS_SLOT: u64 = 7;
constant RETURN_AMOUNTS_SLOT (line 229) | pub const RETURN_AMOUNTS_SLOT: u64 = 8;
constant RETURN_SENDERS_SLOT (line 231) | pub const RETURN_SENDERS_SLOT: u64 = 9;
method dest_keys (line 235) | pub fn dest_keys(value: &str, index: u64) -> Vec<[u8; 32]> {
method dest_key (line 257) | pub fn dest_key(index: u64) -> [u8; 32] {
method sender_key (line 264) | pub fn sender_key(index: u64) -> [u8; 32] {
method amount_key (line 271) | pub fn amount_key(index: u64) -> [u8; 32] {
method dest_chunk_key (line 278) | pub fn dest_chunk_key(index: u64, chunk_index: u64) -> [u8; 32] {
method get_key (line 290) | fn get_key(index: U256, slot: U256) -> [u8; 32] {
function extra_slots_required (line 305) | pub fn extra_slots_required(len: usize) -> usize {
FILE: src/ethereum/relayer.rs
function get_state_proof (line 11) | pub async fn get_state_proof<
FILE: src/ethereum/signer.rs
function start_ethereum_signing (line 18) | pub async fn start_ethereum_signing(
function sign_eth_messages (line 34) | async fn sign_eth_messages(
FILE: src/frost/dkg.rs
type DkgState (line 13) | pub enum DkgState {
type Query (line 22) | type Query = ();
method query (line 24) | fn query(&self, _query: Self::Query) -> Result<()> {
type Dkg (line 30) | pub struct Dkg {
method from_config (line 42) | pub fn from_config(config: &Config) -> Result<Self> {
method state (line 49) | pub fn state(&self) -> DkgState {
method submit_round1 (line 65) | pub fn submit_round1(
method submit_round2 (line 82) | pub fn submit_round2(
method attest_pubkey_package (line 105) | pub fn attest_pubkey_package(
method group_pubkey (line 128) | pub fn group_pubkey(&self) -> Result<Option<Adapter<PublicKeyPackage>>> {
method round1_packages (line 136) | pub fn round1_packages(&self) -> Result<Vec<(u16, round1::Package)>> {
method round2_packages (line 147) | pub fn round2_packages(&self, receiver: u16) -> Result<Vec<(u16, round...
method requires_action_from (line 160) | pub fn requires_action_from(&self, participant: u16) -> Result<bool> {
method absent (line 169) | pub fn absent(&self, participant: u16) -> Result<bool> {
FILE: src/frost/encoding.rs
type Adapter (line 12) | pub struct Adapter<T> {
type Query (line 17) | type Query = ();
method query (line 19) | fn query(&self, _query: Self::Query) -> Result<()> {
method describe (line 25) | fn describe() -> Descriptor {
method attach (line 34) | fn attach(&mut self, _store: Store) -> Result<()> {
method load (line 38) | fn load(_store: Store, bytes: &mut &[u8]) -> Result<Self> {
method flush (line 42) | fn flush<W: std::io::Write>(self, out: &mut W) -> Result<()> {
method encode_into (line 50) | fn encode_into<W: std::io::prelude::Write>(&self, dest: &mut W) -> ed::R...
method encoding_length (line 59) | fn encoding_length(&self) -> ed::Result<usize> {
method decode (line 68) | fn decode<R: std::io::prelude::Read>(bytes: R) -> ed::Result<Self> {
FILE: src/frost/mod.rs
type Config (line 29) | pub struct Config {
method from_staking (line 35) | pub fn from_staking<S: Symbol>(
method total_shares (line 66) | pub fn total_shares(&self) -> u16 {
method contains (line 70) | pub fn contains(&self, address: Address) -> bool {
method share_range (line 74) | pub fn share_range(&self, address: Address) -> Result<Range<u16>> {
type FrostGroup (line 88) | pub struct FrostGroup {
method with_config (line 108) | pub fn with_config(config: Config, now: i64) -> Result<Self> {
method push_message (line 118) | pub fn push_message(&mut self, message: LengthVec<u16, u8>) -> Result<...
method signer (line 126) | fn signer(&mut self) -> Result<Address> {
method now (line 133) | fn now(&mut self) -> Result<i64> {
method submit_dkg_round1 (line 140) | pub fn submit_dkg_round1(
method submit_dkg_round2 (line 159) | pub fn submit_dkg_round2(
method attest_pubkey_package (line 179) | pub fn attest_pubkey_package(
method submit_commitments (line 192) | pub fn submit_commitments(
method submit_sig_shares (line 213) | pub fn submit_sig_shares(
method advance_with_timeout (line 240) | pub fn advance_with_timeout(&mut self, timeout: i64) -> Result<()> {
method absent (line 253) | pub fn absent(&self) -> Result<HashSet<Address>> {
type Frost (line 96) | pub struct Frost {
method noop_call (line 273) | pub fn noop_call(&mut self) -> Result<()> {
method submit_dkg_round1 (line 278) | pub fn submit_dkg_round1(
method submit_dkg_round2 (line 293) | pub fn submit_dkg_round2(
method attest_dkg_pubkey (line 308) | pub fn attest_dkg_pubkey(
method submit_commitments (line 323) | pub fn submit_commitments(
method submit_sig_shares (line 340) | pub fn submit_sig_shares(
method dkg_round1_packages (line 357) | pub fn dkg_round1_packages(
method dkg_round2_packages (line 368) | pub fn dkg_round2_packages(
method dkg_state (line 380) | pub fn dkg_state(&self, index: u64) -> Result<DkgState> {
method signing_state (line 388) | pub fn signing_state(&self, group_index: u64, sig_index: u64) -> Resul...
method signing_state_with_iteration (line 403) | pub fn signing_state_with_iteration(
method config (line 422) | pub fn config(&self, index: u64) -> Result<Config> {
method group_pubkey (line 430) | pub fn group_pubkey(&self, index: u64) -> Result<Option<Adapter<Public...
method dkg_action_required (line 439) | pub fn dkg_action_required(&self, address: Address) -> Result<Vec<u64>> {
method signing_action_required (line 466) | pub fn signing_action_required(&self, address: Address) -> Result<Vec<...
method signing_package (line 497) | pub fn signing_package(
method signature (line 514) | pub fn signature(
method most_recent_with_key (line 531) | pub fn most_recent_with_key(&self) -> Result<Option<u64>> {
method advance_with_timeout (line 541) | pub fn advance_with_timeout(&mut self, timeout: i64) -> Result<()> {
type Participant (line 102) | pub struct Participant {
function identifier (line 554) | fn identifier(participant_index: u16) -> Identifier {
function assemble_by_identifier (line 558) | fn assemble_by_identifier<T>(packages: impl Iterator<Item = (u16, T)>) -...
function disassemble_by_identifier (line 564) | fn disassemble_by_identifier<T: Clone>(map: &BTreeMap<Identifier, T>) ->...
FILE: src/frost/signer.rs
type SecretStore (line 27) | pub struct SecretStore {
method new (line 32) | fn new<P: AsRef<Path>>(path: P) -> Self {
method new_store (line 38) | pub fn new_store<P: AsRef<Path>>(path: P) -> Store {
method flush (line 76) | fn flush(&mut self) -> Result<()> {
method get (line 48) | fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
method get_next (line 52) | fn get_next(&self, key: &[u8]) -> Result<Option<orga::store::KV>> {
method get_prev (line 56) | fn get_prev(&self, key: Option<&[u8]>) -> Result<Option<orga::store::KV>> {
method delete (line 62) | fn delete(&mut self, key: &[u8]) -> Result<()> {
method put (line 68) | fn put(&mut self, key: Vec<u8>, value: Vec<u8>) -> Result<()> {
type Signer (line 83) | pub struct Signer<W, C> {
function new (line 97) | pub fn new(secret_store: Store, client: C, address: Address) -> Self {
function with_key_package (line 108) | fn with_key_package<T, F: FnMut(&mut Map<(u64, u16), Adapter<KeyPackage>...
function with_signing_nonces (line 122) | fn with_signing_nonces<
function call (line 139) | pub async fn call<F: FnOnce(&InnerApp) -> <InnerApp as Call>::Call>(
function client (line 150) | fn client(&self) -> AppClient<InnerApp, InnerApp, HttpClient, Nom, W> {
function step (line 154) | pub async fn step(&mut self) -> Result<()> {
function dkg_step (line 161) | pub async fn dkg_step(&mut self) -> Result<()> {
function signing_step (line 192) | pub async fn signing_step(&mut self) -> Result<()> {
function get_config (line 224) | async fn get_config(&self, index: u64) -> Result<Config> {
function dkg_part1 (line 230) | async fn dkg_part1(&mut self, index: u64) -> Result<()> {
function dkg_part2 (line 254) | async fn dkg_part2(&mut self, index: u64) -> Result<()> {
function dkg_part3 (line 291) | async fn dkg_part3(&mut self, index: u64) -> Result<()> {
function signing_commit (line 350) | async fn signing_commit(
function signing_sign (line 404) | async fn signing_sign(
FILE: src/frost/signing.rs
type SigningState (line 18) | pub enum SigningState {
type Query (line 26) | type Query = ();
method query (line 28) | fn query(&self, _query: Self::Query) -> Result<()> {
type Signing (line 34) | pub struct Signing {
method new (line 48) | pub fn new(config: Config, message: LengthVec<u16, u8>, now: i64) -> S...
method advance_with_timeout (line 57) | pub fn advance_with_timeout(&mut self, now: i64, timeout: i64) -> Resu...
method next_iteration (line 65) | pub fn next_iteration(&mut self, now: i64) -> Result<()> {
method requires_action_from (line 75) | pub fn requires_action_from(&self, participant: u16) -> Result<bool> {
method state (line 90) | pub fn state(&self) -> SigningState {
method submit_commitments (line 101) | pub fn submit_commitments(
method submit_sig_share (line 128) | pub fn submit_sig_share(
method build_signing_package (line 157) | fn build_signing_package(&mut self) -> Result<()> {
method aggregate_signature (line 184) | fn aggregate_signature(&mut self, pubkey_package: &PublicKeyPackage) -...
FILE: src/incentives.rs
type Incentives (line 20) | pub struct Incentives {
method from_csv (line 52) | pub fn from_csv(data: &[u8], funds: Coin<Nom>) -> Result<Self> {
method get (line 103) | pub fn get(&self, address: Address) -> Result<Option<Account>> {
method signer_acct_mut (line 107) | pub fn signer_acct_mut(&mut self) -> OrgaResult<ChildMut<Address, Acco...
method pay_as_funding (line 119) | fn pay_as_funding(&mut self, amount: u64) -> Result<()> {
method claim_testnet_participation_incentives (line 128) | pub fn claim_testnet_participation_incentives(&mut self) -> OrgaResult...
method join_accounts (line 136) | pub fn join_accounts(&mut self, dest_addr: Address) -> OrgaResult<u64> {
type Account (line 25) | pub struct Account {
method is_empty (line 45) | pub fn is_empty(&self) -> bool {
method clone (line 30) | fn clone(&self) -> Self {
method migrate_from (line 38) | fn migrate_from(_old: AccountV0) -> orga::Result<Self> {
FILE: src/lib.rs
function app_client (line 42) | pub fn app_client(
FILE: src/network.rs
type Network (line 28) | pub enum Network {
method config (line 39) | pub fn config(&self) -> InnerConfig {
type Err (line 59) | type Err = Error;
method from_str (line 61) | fn from_str(s: &str) -> Result<Self> {
type InnerConfig (line 76) | pub struct InnerConfig {
type Config (line 141) | pub struct Config {
method home (line 150) | pub fn home(&self) -> Option<PathBuf> {
method home_expect (line 161) | pub fn home_expect(&self) -> Result<PathBuf> {
method is_empty (line 173) | pub fn is_empty(&self) -> bool {
method client (line 181) | pub fn client(&self) -> AppClient<InnerApp, InnerApp, HttpClient, Nom,...
method network (line 187) | pub fn network(&self) -> Option<Network> {
type Target (line 200) | type Target = InnerConfig;
method deref (line 201) | fn deref(&self) -> &Self::Target {
method deref_mut (line 207) | fn deref_mut(&mut self) -> &mut Self::Target {
method from_arg_matches (line 215) | fn from_arg_matches(matches: &ArgMatches) -> std::result::Result<Self, c...
method update_from_arg_matches (line 223) | fn update_from_arg_matches(
method into_app (line 305) | fn into_app<'help>() -> Command<'help> {
method into_app_for_update (line 309) | fn into_app_for_update<'help>() -> Command<'help> {
method augment_args (line 315) | fn augment_args(cmd: Command<'_>) -> Command<'_> {
method augment_args_for_update (line 319) | fn augment_args_for_update(cmd: Command<'_>) -> Command<'_> {
FILE: src/utils.rs
constant DEFAULT_RPC (line 57) | const DEFAULT_RPC: &str = "http://localhost:26657";
function retry (line 59) | pub fn retry<F, T, E>(f: F, max_retries: u32) -> std::result::Result<T, E>
function time_now (line 78) | pub fn time_now() -> u64 {
function sleep (line 85) | pub fn sleep(seconds: u64) {
function generate_sign_doc (line 90) | pub fn generate_sign_doc(chain_id: String, msg: sdk::Msg, nonce: u64) ->...
function make_std_tx (line 107) | pub fn make_std_tx(
function generate_bitcoin_key (line 131) | pub fn generate_bitcoin_key(network: bitcoin::Network) -> Result<Extende...
function load_bitcoin_key (line 144) | pub fn load_bitcoin_key<P: AsRef<Path> + Clone>(path: P) -> Result<Exten...
function load_or_generate (line 163) | pub fn load_or_generate(path: PathBuf, network: bitcoin::Network) -> Res...
function load_privkey (line 178) | pub fn load_privkey(dir: &Path) -> Result<SecretKey> {
function load_consensus_key (line 194) | pub fn load_consensus_key(dir: &Path) -> Result<[u8; 32]> {
function set_time (line 206) | pub fn set_time<T: Into<Time>>(time: T) {
function setup_chain_id_context (line 210) | pub fn setup_chain_id_context(chain_id: String) {
function test_bitcoin_client (line 216) | pub async fn test_bitcoin_client(rpc_url: String, cookie_file: PathBuf) ...
function address_from_privkey (line 222) | pub fn address_from_privkey(privkey: &SecretKey) -> Address {
function setup_test_signer (line 228) | pub fn setup_test_signer<T: AsRef<Path>, F>(home: T, client: F) -> Signe...
type DeclareInfo (line 254) | pub struct DeclareInfo {
function declare_validator (line 262) | pub async fn declare_validator(
function poll_for_blocks (line 304) | pub async fn poll_for_blocks() {
function poll_for_active_sigset (line 321) | pub async fn poll_for_active_sigset() {
function poll_for_signatory_key (line 334) | pub async fn poll_for_signatory_key(consensus_key: [u8; 32]) {
function poll_for_signing_checkpoint (line 347) | pub async fn poll_for_signing_checkpoint() {
function poll_for_completed_checkpoint (line 362) | pub async fn poll_for_completed_checkpoint(num_checkpoints: u32) {
function poll_for_updated_balance (line 378) | pub async fn poll_for_updated_balance(address: Address, expected_balance...
function poll_for_bitcoin_header (line 404) | pub async fn poll_for_bitcoin_header(height: u32) -> Result<()> {
type BitcoinBlockData (line 418) | pub struct BitcoinBlockData {
function populate_bitcoin_block (line 424) | pub async fn populate_bitcoin_block(client: &BitcoinRpcClient) -> Bitcoi...
type NomicTestWallet (line 448) | pub struct NomicTestWallet {
method new_rand (line 466) | pub fn new_rand() -> Self {
method bitcoin_address (line 480) | pub fn bitcoin_address(&self) -> bitcoin::Address {
method address (line 456) | fn address(&self) -> OrgaResult<Option<Address>> {
method sign (line 460) | fn sign(&self, call_bytes: &[u8]) -> OrgaResult<SignerCall> {
function setup_test_app (line 486) | pub fn setup_test_app(
function address_to_script (line 559) | pub fn address_to_script(address: Address) -> Result<Script> {
function start_rest (line 566) | pub fn start_rest() -> Result<Child> {
FILE: tests/bitcoin.rs
function app_client (line 59) | fn app_client() -> AppClient<InnerApp, InnerApp, orga::tendermint::clien...
function generate_deposit_address (line 64) | async fn generate_deposit_address(address: &Address) -> Result<DepositAd...
function broadcast_deposit_addr (line 89) | pub async fn broadcast_deposit_addr(
function set_recovery_address (line 119) | async fn set_recovery_address(nomic_account: NomicTestWallet) -> Result<...
function deposit_bitcoin (line 137) | async fn deposit_bitcoin(
function withdraw_bitcoin (line 167) | async fn withdraw_bitcoin(
function get_signatory_script (line 184) | async fn get_signatory_script() -> Result<Script> {
function client_provider (line 193) | fn client_provider() -> AppClient<InnerApp, InnerApp, HttpClient, Nom, D...
function bitcoin_test (line 202) | async fn bitcoin_test() {
function signing_completed_checkpoint_test (line 662) | async fn signing_completed_checkpoint_test() {
function pending_deposits (line 946) | async fn pending_deposits() {
function signer_key_updating (line 1171) | async fn signer_key_updating() {
function recover_expired_deposit (line 1516) | async fn recover_expired_deposit() {
function generate_deposit_expired (line 1771) | async fn generate_deposit_expired() {
FILE: tests/header_queue.rs
function into_json (line 17) | fn into_json<T>(val: T) -> Result<bitcoincore_rpc::jsonrpc::serde_json::...
function reorg (line 26) | fn reorg() {
function reorg_competing_chain_similar (line 126) | fn reorg_competing_chain_similar() {
function reorg_deep (line 230) | fn reorg_deep() {
function mainnet_from_file (line 333) | fn mainnet_from_file() {
FILE: tests/ibc.rs
constant TEST_CHAIN_ID (line 50) | const TEST_CHAIN_ID: &str = "nomic-e2e";
function app_client (line 52) | fn app_client() -> AppClient<InnerApp, InnerApp, orga::tendermint::clien...
function generate_deposit_address (line 57) | async fn generate_deposit_address(address: &Address) -> Result<DepositAd...
function broadcast_deposit_addr (line 82) | pub async fn broadcast_deposit_addr(
function direct_deposit_bitcoin (line 112) | async fn direct_deposit_bitcoin(
function deposit_bitcoin (line 177) | async fn deposit_bitcoin(
function client_provider (line 207) | fn client_provider() -> AppClient<InnerApp, InnerApp, HttpClient, Nom, D...
type GmHandler (line 213) | struct GmHandler {}
method start (line 216) | async fn start(gm_path: String) -> Result<()> {
function ibc_test (line 232) | async fn ibc_test() {
FILE: tests/node.rs
function node_shutdown (line 15) | async fn node_shutdown() {
FILE: tests/node_spawn.rs
function fresh_local_network (line 6) | fn fresh_local_network() {
function migrate (line 48) | fn migrate() {
function testnet (line 97) | fn testnet() {
FILE: tests/relayer.rs
function relayer (line 12) | fn relayer() {
FILE: wasm/src/error.rs
type Error (line 7) | pub enum Error {
method from (line 23) | fn from(err: JsValue) -> Self {
FILE: wasm/src/lib.rs
function main (line 30) | pub fn main() -> std::result::Result<(), JsValue> {
function app_client (line 35) | pub fn app_client() -> AppClient<InnerApp, InnerApp, WebClient, Nom, Uns...
function transfer (line 42) | pub async fn transfer(to_addr: String, amount: u64) -> Result<JsValue, J...
function balance (line 57) | pub async fn balance(addr: String) -> Result<u64, JsError> {
function nom_reward_balance (line 68) | pub async fn nom_reward_balance(addr: String) -> Result<u64, JsError> {
function nbtc_reward_balance (line 89) | pub async fn nbtc_reward_balance(addr: String) -> Result<u64, JsError> {
function delegations (line 110) | pub async fn delegations(addr: String) -> Result<Array, JsError> {
function all_validators (line 147) | pub async fn all_validators() -> Result<Array, JsError> {
function claim (line 170) | pub async fn claim(address: String) -> Result<String, JsError> {
function claim_airdrop1 (line 185) | pub async fn claim_airdrop1(address: String) -> Result<String, JsError> {
function claim_airdrop2 (line 200) | pub async fn claim_airdrop2(address: String) -> Result<String, JsError> {
function claim_testnet_participation_airdrop (line 215) | pub async fn claim_testnet_participation_airdrop(address: String) -> Res...
function claim_testnet_participation_incentives (line 230) | pub async fn claim_testnet_participation_incentives(address: String) -> ...
function claim_incoming_ibc_btc (line 245) | pub async fn claim_incoming_ibc_btc(address: String) -> Result<String, J...
function set_recovery_address (line 260) | pub async fn set_recovery_address(
function get_recovery_address (line 278) | pub async fn get_recovery_address(address: String) -> Result<String, JsE...
function delegate (line 296) | pub async fn delegate(from_addr: String, to_addr: String, amount: u64) -...
function unbond (line 317) | pub async fn unbond(address: String, val_addr: String, amount: u64) -> R...
function redelegate (line 341) | pub async fn redelegate(
function parse_part (line 370) | fn parse_part(part: nomic::airdrop::Part) -> RewardDetails {
function airdrop_balances (line 380) | pub async fn airdrop_balances(addr: String) -> Result<Airdrop, JsError> {
function incentive_balances (line 394) | pub async fn incentive_balances(addr: String) -> Result<Incentives, JsEr...
function nonce (line 410) | pub async fn nonce(addr: String) -> Result<u64, JsError> {
function gen_deposit_addr (line 419) | pub async fn gen_deposit_addr(dest_addr: String) -> Result<DepositAddres...
function nbtc_balance (line 452) | pub async fn nbtc_balance(addr: String) -> Result<u64, JsError> {
function incoming_ibc_nbtc_balance (line 463) | pub async fn incoming_ibc_nbtc_balance(addr: String) -> Result<u64, JsEr...
function value_locked (line 471) | pub async fn value_locked() -> Result<u64, JsError> {
function latest_checkpoint_hash (line 478) | pub async fn latest_checkpoint_hash() -> Result<String, JsError> {
function bitcoin_height (line 487) | pub async fn bitcoin_height() -> Result<u32, JsError> {
function capacity_limit (line 494) | pub async fn capacity_limit() -> Result<u64, JsError> {
function fee_info (line 501) | pub async fn fee_info() -> Result<FeeInfo, JsError> {
function deposits_enabled (line 522) | pub async fn deposits_enabled() -> Result<bool, JsError> {
function get_address (line 530) | pub async fn get_address() -> Result<String, JsError> {
function broadcast_deposit_addr (line 537) | pub async fn broadcast_deposit_addr(
function withdraw (line 604) | pub async fn withdraw(address: String, dest_addr: String, amount: u64) -...
function stake_nbtc (line 624) | pub async fn stake_nbtc(address: String, amount: u64) -> Result<String, ...
function unstake_nbtc (line 643) | pub async fn unstake_nbtc(address: String, amount: u64) -> Result<String...
function pay_to_fee_pool (line 661) | pub async fn pay_to_fee_pool(address: String, amount: u64) -> Result<Str...
function join_reward_accounts (line 679) | pub async fn join_reward_accounts(
function ibc_transfer_out (line 704) | pub async fn ibc_transfer_out(
function local_storage_chain_id (line 736) | fn local_storage_chain_id() -> String {
function gen_call_bytes (line 749) | async fn gen_call_bytes(address: String, msg: sdk::Msg) -> Result<String...
function convert_eth_address (line 782) | pub fn convert_eth_address(str: String) -> Result<String, JsError> {
FILE: wasm/src/types.rs
type DepositAddress (line 4) | pub struct DepositAddress {
type FeeInfo (line 12) | pub struct FeeInfo {
type ValidatorQueryInfo (line 18) | pub struct ValidatorQueryInfo {
type UnbondInfo (line 30) | pub struct UnbondInfo {
type Delegation (line 37) | pub struct Delegation {
type Coin (line 45) | pub struct Coin {
type RewardDetails (line 52) | pub struct RewardDetails {
type Airdrop (line 61) | pub struct Airdrop {
method total (line 68) | pub fn total(&self) -> u64 {
method claimed_total (line 74) | pub fn claimed_total(&self) -> u64 {
type Incentives (line 82) | pub struct Incentives {
method total (line 89) | pub fn total(&self) -> u64 {
method claimed_total (line 94) | pub fn claimed_total(&self) -> u64 {
FILE: wasm/src/web_client.rs
type WebClient (line 23) | pub struct WebClient {
method new (line 28) | pub fn new() -> Self {
method call (line 34) | async fn call(&self, _call: <ABCIPlugin<T> as Call>::Call) -> Result<(...
method query (line 38) | async fn query(&self, query: T::Query) -> Result<Store> {
type UnsafeSendFuture (line 125) | pub struct UnsafeSendFuture<F>(F);
type Output (line 130) | type Output = F::Output;
method poll (line 132) | fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
type UnsafeSend (line 138) | struct UnsafeSend<T>(pub T);
type Output (line 141) | type Output = std::result::Result<JsValue, JsValue>;
method poll (line 143) | fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<std::result::Res...
Condensed preview — 144 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (8,441K chars).
[
{
"path": ".github/workflows/ci.yml",
"chars": 5506,
"preview": "name: CI\n\non:\n push:\n branches: [master, develop]\n pull_request:\n branches: [master, develop]\n\nconcurrency:\n gr"
},
{
"path": ".gitignore",
"chars": 89,
"preview": "target\n**/target/\nmerk.db/\n\n.vscode/\n.DS_Store\n\n# Added by cargo\n\n/target\nwasm/Cargo.lock"
},
{
"path": "Cargo.toml",
"chars": 4995,
"preview": "[package]\nname = \"nomic\"\nversion = \"9.2.0\"\nauthors = [\"Nomic DAO Foundation <foundation@nomic.io>\"]\nedition = \"2021\"\ndef"
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 2457,
"preview": "<h1 align=\"center\">\n<picture>\n <source media=\"(prefers-color-scheme: dark)\" srcset=\"./nomic-logo-dark-100.png\">\n <sour"
},
{
"path": "SECURITY.md",
"chars": 4180,
"preview": "# Security Policy\n\n## Introduction\n\nSecurity researchers are essential in identifying vulnerabilities that may impact th"
},
{
"path": "build.rs",
"chars": 4289,
"preview": "fn main() {\n let branch_name = std::process::Command::new(\"git\")\n .args([\"symbolic-ref\", \"--short\", \"HEAD\"])\n "
},
{
"path": "build.sh",
"chars": 951,
"preview": "#!/bin/bash\n\nset -e\n\nBUILD_DIR=$OUT_DIR/nomic\nNOMIC_LEGACY_PATH=$OUT_DIR/nomic-$NOMIC_LEGACY_REV\n\nif [ ! -f \"$NOMIC_LEGA"
},
{
"path": "genesis/stakenet-2.json",
"chars": 492,
"preview": "{\n \"genesis_time\": \"2022-03-31T16:00:00Z\",\n \"chain_id\": \"nomic-stakenet-2\",\n \"initial_height\": \"0\",\n \"consensus_para"
},
{
"path": "genesis/stakenet-3.json",
"chars": 492,
"preview": "{\n \"genesis_time\": \"2022-07-04T00:00:00Z\",\n \"chain_id\": \"nomic-stakenet-3\",\n \"initial_height\": \"0\",\n \"consensus_para"
},
{
"path": "genesis/testnet-4.json",
"chars": 486,
"preview": "{\n \"genesis_time\": \"2022-06-22T00:00:00Z\",\n \"chain_id\": \"nomic-testnet-4\",\n \"initial_height\": \"1\",\n \"consensus_param"
},
{
"path": "genesis/testnet-4d.json",
"chars": 492,
"preview": "{\n \"genesis_time\": \"2022-10-05T00:00:00Z\",\n \"chain_id\": \"nomic-testnet-4d\",\n \"initial_height\": \"0\",\n \"consensus_para"
},
{
"path": "networks/stakenet.toml",
"chars": 806,
"preview": "state_sync_rpc = [\n \"http://161.35.51.124:26667\",\n \"http://161.35.51.124:26667\"\n]\ntendermint_flags = [\n \"--p2p.seed"
},
{
"path": "networks/testnet.toml",
"chars": 1076,
"preview": "state_sync_rpc = [\n \"http://147.182.171.216:26657\",\n \"http://147.182.171.216:26657\",\n]\ntendermint_flags = [\"--p2p.seed"
},
{
"path": "rest/Cargo.toml",
"chars": 833,
"preview": "[package]\nname = \"nomic-rest\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.r"
},
{
"path": "rest/src/main.rs",
"chars": 47088,
"preview": "#[macro_use]\nextern crate rocket;\n\nuse chrono::{TimeZone, Utc};\nuse nomic::{\n app::{InnerApp, Nom},\n bitcoin::Nbtc"
},
{
"path": "rust-toolchain",
"chars": 43,
"preview": "[toolchain]\nchannel = \"nightly-2024-07-21\"\n"
},
{
"path": "rustfmt.toml",
"chars": 41,
"preview": "comment_width = 80\nwrap_comments = true\n\n"
},
{
"path": "src/airdrop.rs",
"chars": 15876,
"preview": "//! State and logic for airdrop accounts which can be claimed by users.\n\nuse orga::coins::Address;\n#[cfg(feature = \"full"
},
{
"path": "src/app/migrations.rs",
"chars": 3348,
"preview": "#[cfg(feature = \"babylon\")]\nuse crate::babylon::Babylon;\n#[cfg(feature = \"ethereum\")]\nuse crate::ethereum::{bytes32, Con"
},
{
"path": "src/app.rs",
"chars": 79559,
"preview": "//! The top-level application state and logic of the Nomic protocol. The main\n//! state type is the [InnerApp] struct.\n\n"
},
{
"path": "src/babylon/mod.rs",
"chars": 48475,
"preview": "use bitcoin::{\n hashes::Hash,\n psbt::Prevouts,\n secp256k1::{schnorr, PublicKey, Secp256k1},\n util::{\n "
},
{
"path": "src/babylon/proto/babylon/btccheckpoint/v1/btccheckpoint.proto",
"chars": 6583,
"preview": "syntax = \"proto3\";\npackage babylon.btccheckpoint.v1;\n\nimport \"gogoproto/gogo.proto\";\n\noption go_package = \"github.com/ba"
},
{
"path": "src/babylon/proto/babylon/btccheckpoint/v1/genesis.proto",
"chars": 355,
"preview": "syntax = \"proto3\";\npackage babylon.btccheckpoint.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"babylon/btccheckpoint/v1/pa"
},
{
"path": "src/babylon/proto/babylon/btccheckpoint/v1/params.proto",
"chars": 1198,
"preview": "syntax = \"proto3\";\npackage babylon.btccheckpoint.v1;\n\nimport \"gogoproto/gogo.proto\";\n\noption go_package = \"github.com/ba"
},
{
"path": "src/babylon/proto/babylon/btccheckpoint/v1/query.proto",
"chars": 5875,
"preview": "syntax = \"proto3\";\npackage babylon.btccheckpoint.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos_proto/cosmos.proto\";"
},
{
"path": "src/babylon/proto/babylon/btccheckpoint/v1/tx.proto",
"chars": 1865,
"preview": "syntax = \"proto3\";\npackage babylon.btccheckpoint.v1;\n\nimport \"babylon/btccheckpoint/v1/btccheckpoint.proto\";\nimport \"cos"
},
{
"path": "src/babylon/proto/babylon/btclightclient/v1/btclightclient.proto",
"chars": 884,
"preview": "syntax = \"proto3\";\npackage babylon.btclightclient.v1;\n\nimport \"gogoproto/gogo.proto\";\n\noption go_package = \"github.com/b"
},
{
"path": "src/babylon/proto/babylon/btclightclient/v1/event.proto",
"chars": 1059,
"preview": "syntax = \"proto3\";\npackage babylon.btclightclient.v1;\n\nimport \"babylon/btclightclient/v1/btclightclient.proto\";\n\noption "
},
{
"path": "src/babylon/proto/babylon/btclightclient/v1/genesis.proto",
"chars": 458,
"preview": "syntax = \"proto3\";\npackage babylon.btclightclient.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"babylon/btclightclient/v1/"
},
{
"path": "src/babylon/proto/babylon/btclightclient/v1/params.proto",
"chars": 457,
"preview": "syntax = \"proto3\";\npackage babylon.btclightclient.v1;\n\nimport \"gogoproto/gogo.proto\";\n\n\noption go_package = \"github.com/"
},
{
"path": "src/babylon/proto/babylon/btclightclient/v1/query.proto",
"chars": 6032,
"preview": "syntax = \"proto3\";\npackage babylon.btclightclient.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos_proto/cosmos.proto\""
},
{
"path": "src/babylon/proto/babylon/btclightclient/v1/tx.proto",
"chars": 1860,
"preview": "syntax = \"proto3\";\npackage babylon.btclightclient.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos/msg/v1/msg.proto\";\n"
},
{
"path": "src/babylon/proto/babylon/btcstaking/v1/btcstaking.proto",
"chars": 9834,
"preview": "syntax = \"proto3\";\npackage babylon.btcstaking.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos_proto/cosmos.proto\";\nim"
},
{
"path": "src/babylon/proto/babylon/btcstaking/v1/events.proto",
"chars": 2079,
"preview": "syntax = \"proto3\";\npackage babylon.btcstaking.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"babylon/btcstaking/v1/btcstaki"
},
{
"path": "src/babylon/proto/babylon/btcstaking/v1/genesis.proto",
"chars": 3376,
"preview": "syntax = \"proto3\";\npackage babylon.btcstaking.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"babylon/btcstaking/v1/params.p"
},
{
"path": "src/babylon/proto/babylon/btcstaking/v1/incentive.proto",
"chars": 2176,
"preview": "syntax = \"proto3\";\npackage babylon.btcstaking.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos_proto/cosmos.proto\";\nim"
},
{
"path": "src/babylon/proto/babylon/btcstaking/v1/params.proto",
"chars": 2360,
"preview": "syntax = \"proto3\";\npackage babylon.btcstaking.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos_proto/cosmos.proto\";\n\no"
},
{
"path": "src/babylon/proto/babylon/btcstaking/v1/pop.proto",
"chars": 1379,
"preview": "syntax = \"proto3\";\npackage babylon.btcstaking.v1;\n\noption go_package = \"github.com/babylonchain/babylon/x/btcstaking/typ"
},
{
"path": "src/babylon/proto/babylon/btcstaking/v1/query.proto",
"chars": 14952,
"preview": "syntax = \"proto3\";\npackage babylon.btcstaking.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"google/api/annotations.proto\";"
},
{
"path": "src/babylon/proto/babylon/btcstaking/v1/tx.proto",
"chars": 10455,
"preview": "syntax = \"proto3\";\npackage babylon.btcstaking.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos_proto/cosmos.proto\";\nim"
},
{
"path": "src/babylon/proto/babylon/checkpointing/v1/bls_key.proto",
"chars": 2200,
"preview": "syntax = \"proto3\";\npackage babylon.checkpointing.v1;\n\nimport \"gogoproto/gogo.proto\";\n\noption go_package = \"github.com/ba"
},
{
"path": "src/babylon/proto/babylon/checkpointing/v1/checkpoint.proto",
"chars": 4268,
"preview": "syntax = \"proto3\";\npackage babylon.checkpointing.v1;\n\nimport \"google/protobuf/timestamp.proto\";\nimport \"gogoproto/gogo.p"
},
{
"path": "src/babylon/proto/babylon/checkpointing/v1/events.proto",
"chars": 1406,
"preview": "syntax = \"proto3\";\npackage babylon.checkpointing.v1;\n\nimport \"babylon/checkpointing/v1/checkpoint.proto\";\n\noption go_pac"
},
{
"path": "src/babylon/proto/babylon/checkpointing/v1/genesis.proto",
"chars": 829,
"preview": "syntax = \"proto3\";\npackage babylon.checkpointing.v1;\n\nimport \"cosmos/crypto/ed25519/keys.proto\";\nimport \"babylon/checkpo"
},
{
"path": "src/babylon/proto/babylon/checkpointing/v1/query.proto",
"chars": 8257,
"preview": "syntax = \"proto3\";\npackage babylon.checkpointing.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"google/api/annotations.prot"
},
{
"path": "src/babylon/proto/babylon/checkpointing/v1/tx.proto",
"chars": 1060,
"preview": "syntax = \"proto3\";\npackage babylon.checkpointing.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"babylon/checkpointing/v1/bl"
},
{
"path": "src/babylon/proto/babylon/epoching/v1/epoching.proto",
"chars": 4189,
"preview": "syntax = \"proto3\";\npackage babylon.epoching.v1;\n\nimport \"google/protobuf/timestamp.proto\";\nimport \"gogoproto/gogo.proto\""
},
{
"path": "src/babylon/proto/babylon/epoching/v1/events.proto",
"chars": 2195,
"preview": "syntax = \"proto3\";\npackage babylon.epoching.v1;\n\nimport \"gogoproto/gogo.proto\";\n\noption go_package = \"github.com/babylon"
},
{
"path": "src/babylon/proto/babylon/epoching/v1/genesis.proto",
"chars": 335,
"preview": "syntax = \"proto3\";\npackage babylon.epoching.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"babylon/epoching/v1/params.proto"
},
{
"path": "src/babylon/proto/babylon/epoching/v1/params.proto",
"chars": 419,
"preview": "syntax = \"proto3\";\npackage babylon.epoching.v1;\n\nimport \"gogoproto/gogo.proto\";\n\noption go_package = \"github.com/babylon"
},
{
"path": "src/babylon/proto/babylon/epoching/v1/query.proto",
"chars": 9537,
"preview": "syntax = \"proto3\";\npackage babylon.epoching.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"google/protobuf/timestamp.proto\""
},
{
"path": "src/babylon/proto/babylon/epoching/v1/tx.proto",
"chars": 3981,
"preview": "syntax = \"proto3\";\npackage babylon.epoching.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos/staking/v1beta1/tx.proto\""
},
{
"path": "src/babylon/proto/babylon/finality/v1/events.proto",
"chars": 438,
"preview": "syntax = \"proto3\";\npackage babylon.finality.v1;\n\nimport \"babylon/finality/v1/finality.proto\";\n\noption go_package = \"gith"
},
{
"path": "src/babylon/proto/babylon/finality/v1/finality.proto",
"chars": 1968,
"preview": "syntax = \"proto3\";\npackage babylon.finality.v1;\n\noption go_package = \"github.com/babylonchain/babylon/x/finality/types\";"
},
{
"path": "src/babylon/proto/babylon/finality/v1/genesis.proto",
"chars": 2150,
"preview": "syntax = \"proto3\";\npackage babylon.finality.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"babylon/finality/v1/params.proto"
},
{
"path": "src/babylon/proto/babylon/finality/v1/params.proto",
"chars": 391,
"preview": "syntax = \"proto3\";\npackage babylon.finality.v1;\n\nimport \"gogoproto/gogo.proto\";\n\noption go_package = \"github.com/babylon"
},
{
"path": "src/babylon/proto/babylon/finality/v1/query.proto",
"chars": 6359,
"preview": "syntax = \"proto3\";\npackage babylon.finality.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"google/api/annotations.proto\";\ni"
},
{
"path": "src/babylon/proto/babylon/finality/v1/tx.proto",
"chars": 3894,
"preview": "syntax = \"proto3\";\npackage babylon.finality.v1;\n\noption go_package = \"github.com/babylonchain/babylon/x/finality/types\";"
},
{
"path": "src/babylon/proto/babylon/incentive/genesis.proto",
"chars": 335,
"preview": "syntax = \"proto3\";\npackage babylon.incentive;\n\nimport \"gogoproto/gogo.proto\";\nimport \"babylon/incentive/params.proto\";\n\n"
},
{
"path": "src/babylon/proto/babylon/incentive/incentive.proto",
"chars": 1410,
"preview": "syntax = \"proto3\";\npackage babylon.incentive;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos/base/v1beta1/coin.proto\";\n\n"
},
{
"path": "src/babylon/proto/babylon/incentive/params.proto",
"chars": 1593,
"preview": "syntax = \"proto3\";\npackage babylon.incentive;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos_proto/cosmos.proto\";\n\noptio"
},
{
"path": "src/babylon/proto/babylon/incentive/query.proto",
"chars": 3079,
"preview": "syntax = \"proto3\";\npackage babylon.incentive;\n\nimport \"gogoproto/gogo.proto\";\nimport \"google/api/annotations.proto\";\nimp"
},
{
"path": "src/babylon/proto/babylon/incentive/tx.proto",
"chars": 2162,
"preview": "syntax = \"proto3\";\npackage babylon.incentive;\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos_proto/cosmos.proto\";\nimport"
},
{
"path": "src/babylon/proto/babylon/monitor/v1/genesis.proto",
"chars": 204,
"preview": "syntax = \"proto3\";\npackage babylon.monitor.v1;\n\noption go_package = \"github.com/babylonchain/babylon/x/monitor/types\";\n\n"
},
{
"path": "src/babylon/proto/babylon/monitor/v1/query.proto",
"chars": 1794,
"preview": "syntax = \"proto3\";\npackage babylon.monitor.v1;\n\nimport \"google/api/annotations.proto\";\n\noption go_package = \"github.com/"
},
{
"path": "src/babylon/proto/babylon/zoneconcierge/v1/genesis.proto",
"chars": 379,
"preview": "syntax = \"proto3\";\npackage babylon.zoneconcierge.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"babylon/zoneconcierge/v1/pa"
},
{
"path": "src/babylon/proto/babylon/zoneconcierge/v1/packet.proto",
"chars": 2108,
"preview": "syntax = \"proto3\";\npackage babylon.zoneconcierge.v1;\n\nimport \"babylon/btccheckpoint/v1/btccheckpoint.proto\";\nimport \"bab"
},
{
"path": "src/babylon/proto/babylon/zoneconcierge/v1/params.proto",
"chars": 512,
"preview": "syntax = \"proto3\";\npackage babylon.zoneconcierge.v1;\n\nimport \"gogoproto/gogo.proto\";\n\noption go_package = \"github.com/ba"
},
{
"path": "src/babylon/proto/babylon/zoneconcierge/v1/query.proto",
"chars": 7959,
"preview": "syntax = \"proto3\";\npackage babylon.zoneconcierge.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"google/api/annotations.prot"
},
{
"path": "src/babylon/proto/babylon/zoneconcierge/v1/tx.proto",
"chars": 1290,
"preview": "syntax = \"proto3\";\npackage babylon.zoneconcierge.v1;\n\n\nimport \"gogoproto/gogo.proto\";\nimport \"cosmos_proto/cosmos.proto\""
},
{
"path": "src/babylon/proto/babylon/zoneconcierge/v1/zoneconcierge.proto",
"chars": 5949,
"preview": "syntax = \"proto3\";\npackage babylon.zoneconcierge.v1;\n\nimport \"gogoproto/gogo.proto\";\nimport \"google/protobuf/timestamp.p"
},
{
"path": "src/babylon/proto/btccheckpoint.rs",
"chars": 19130,
"preview": "// @generated\n/// Consider we have a Merkle tree with following structure:\n/// ROOT\n/// / \\\n//"
},
{
"path": "src/babylon/proto/buf.gen.yaml",
"chars": 84,
"preview": "version: v1\nplugins:\n - plugin: buf.build/community/neoeinstein-prost\n out: gen\n"
},
{
"path": "src/babylon/proto/buf.yaml",
"chars": 683,
"preview": "version: v1\nname: buf.build/babylon/babylond\ndeps:\n - buf.build/cosmos/cosmos-sdk:v0.50.0\n - buf.build/cosmos/cosmos-p"
},
{
"path": "src/babylon/proto/gen/babylon.btccheckpoint.v1.rs",
"chars": 18959,
"preview": "// @generated\n/// Consider we have a Merkle tree with following structure:\n/// ROOT\n/// / \\\n//"
},
{
"path": "src/babylon/proto/gen/babylon.btclightclient.v1.rs",
"chars": 10794,
"preview": "// @generated\n/// BTCHeaderInfo is a structure that contains all relevant information about a\n/// BTC header\n/// - Ful"
},
{
"path": "src/babylon/proto/gen/babylon.btcstaking.v1.rs",
"chars": 56089,
"preview": "// @generated\n/// ProofOfPossession is the proof of possession that a Babylon secp256k1\n/// secret key and a Bitcoin sec"
},
{
"path": "src/babylon/proto/gen/babylon.checkpointing.v1.rs",
"chars": 22724,
"preview": "// @generated\n/// BlsKey wraps BLS public key with PoP\n#[allow(clippy::derive_partial_eq_without_eq)]\n#[derive(Clone, Pa"
},
{
"path": "src/babylon/proto/gen/babylon.epoching.v1.rs",
"chars": 27367,
"preview": "// @generated\n/// Epoch is a structure that contains the metadata of an epoch\n#[allow(clippy::derive_partial_eq_without_"
},
{
"path": "src/babylon/proto/gen/babylon.finality.v1.rs",
"chars": 16996,
"preview": "// @generated\n/// IndexedBlock is the necessary metadata and finalization status of a block\n#[allow(clippy::derive_parti"
},
{
"path": "src/babylon/proto/gen/babylon.incentive.rs",
"chars": 7512,
"preview": "// @generated\n/// Params defines the parameters for the module, including portions of rewards\n/// distributed to each ty"
},
{
"path": "src/babylon/proto/gen/babylon.monitor.v1.rs",
"chars": 1695,
"preview": "// @generated\n/// GenesisState defines the monitor module's genesis state.\n#[allow(clippy::derive_partial_eq_without_eq)"
},
{
"path": "src/babylon/proto/gen/babylon.zoneconcierge.v1.rs",
"chars": 20707,
"preview": "// @generated\n/// Params defines the parameters for the module.\n#[allow(clippy::derive_partial_eq_without_eq)]\n#[derive("
},
{
"path": "src/babylon/proto/mod.rs",
"chars": 57025,
"preview": "#![allow(clippy::all)]\n\npub mod btccheckpoint;\n\n// @generated\n/// ProofOfPossession is the proof of possession that a Ba"
},
{
"path": "src/babylon/relayer.rs",
"chars": 8568,
"preview": "// TODO: scan loop\n// TODO: relay confirmed delegations to nomic\n// TODO: relay signed, confirmed delegations to babylon"
},
{
"path": "src/bin/create-checkpoint.rs",
"chars": 2447,
"preview": "//! Outputs a block header for Bitcoin in JSON, which can be used to bootstrap a\n//! [nomic::bitcoin::HeaderQueue] state"
},
{
"path": "src/bin/eth-bootstrap.rs",
"chars": 1204,
"preview": "use clap::Parser;\nuse nomic::error::Result;\nuse nomic::ethereum::consensus::relayer::RpcClient;\n\npub const SYNC_PERIOD_L"
},
{
"path": "src/bin/get-reserve-scripts.rs",
"chars": 3032,
"preview": "//! This script is used to get the reserve scripts for the last N days by\n//! fetching the chain of checkpoint transacti"
},
{
"path": "src/bin/nomic.rs",
"chars": 109483,
"preview": "//! This binary provides the command-line interface for running a Nomic full\n//! node, as well as client commands for qu"
},
{
"path": "src/bitcoin/adapter.rs",
"chars": 3432,
"preview": "use bitcoin::consensus::{Decodable, Encodable};\nuse orga::describe::Describe;\nuse orga::encoding::Result as EncodingResu"
},
{
"path": "src/bitcoin/checkpoint.json",
"chars": 296,
"preview": "[\n 808416,\n {\n \"version\": 691150848,\n \"prev_blockhash\": \"000000000000000000027ecc78c2da1cc5c0b0496706baa7e4d7c80"
},
{
"path": "src/bitcoin/checkpoint.rs",
"chars": 116132,
"preview": "#[cfg(feature = \"full\")]\nuse super::ConsensusKey;\nuse super::{\n adapter::Adapter,\n signatory::SignatorySet,\n th"
},
{
"path": "src/bitcoin/deposit_index.rs",
"chars": 2659,
"preview": "use crate::{app::Dest, error::Result};\nuse bitcoin::{Address, Txid};\nuse serde::{Deserialize, Serialize};\nuse std::colle"
},
{
"path": "src/bitcoin/header_queue.rs",
"chars": 38074,
"preview": "use crate::bitcoin::adapter::Adapter;\nuse crate::error::{Error, Result};\nuse bitcoin::blockdata::block::BlockHeader;\nuse"
},
{
"path": "src/bitcoin/mod.rs",
"chars": 53169,
"preview": "//! State and logic for verifying and processing Bitcoin transactions, as well\n//! as managing the checkpointing process"
},
{
"path": "src/bitcoin/outpoint_set.rs",
"chars": 2388,
"preview": "use orga::{collections::Map, orga, Result};\n\n/// A Bitcoin transaction ID and output index.\npub type Outpoint = ([u8; 32"
},
{
"path": "src/bitcoin/recovery.rs",
"chars": 5080,
"preview": "use super::{\n adapter::Adapter,\n checkpoint::{BitcoinTx, Input},\n signatory::{derive_pubkey, SignatorySet},\n "
},
{
"path": "src/bitcoin/relayer.rs",
"chars": 52140,
"preview": "use super::signatory::Signatory;\nuse super::SignatorySet;\nuse super::SIGSET_THRESHOLD;\nuse crate::app::Dest;\nuse crate::"
},
{
"path": "src/bitcoin/signatory.rs",
"chars": 32843,
"preview": "#![allow(clippy::redundant_closure_call)] // TODO: fix bitcoin-script then remove this\n#![allow(unused_imports)] // TODO"
},
{
"path": "src/bitcoin/signer.rs",
"chars": 21572,
"preview": "use crate::app::{InnerApp, Nom};\nuse crate::bitcoin::checkpoint::CheckpointStatus;\nuse crate::bitcoin::threshold_sig::Si"
},
{
"path": "src/bitcoin/signet_checkpoint.json",
"chars": 294,
"preview": "[\n 187488,\n {\n \"version\": 536870912,\n \"prev_blockhash\": \"00000145fda2984b2467e98dca41b15a210817ce8507ed6470bfaba"
},
{
"path": "src/bitcoin/testnet_checkpoint.json",
"chars": 297,
"preview": "[\n 3191328,\n {\n \"version\": 712925184,\n \"prev_blockhash\": \"00000000000000b1c5d067792aae5ae74e4cf30b0f28caa064b5d7"
},
{
"path": "src/bitcoin/threshold_sig.rs",
"chars": 11539,
"preview": "use super::{SignatorySet, SIGSET_THRESHOLD};\nuse bitcoin::blockdata::transaction::EcdsaSighashType;\nuse bitcoin::secp256"
},
{
"path": "src/cosmos.rs",
"chars": 23023,
"preview": "//! The Cosmos state, allowing for relaying data about remote Cosmos chains\n//! which is not available in the IBC module"
},
{
"path": "src/error.rs",
"chars": 2856,
"preview": "//! This module adds the [Error] type, which is used throughout the library to\n//! represent the various ways that opera"
},
{
"path": "src/ethereum/bootstrap/sepolia.json",
"chars": 58135,
"preview": "{\n \"header\": {\n \"beacon\": {\n \"slot\": \"6184960\",\n \"proposer_index\": \"332\",\n \"parent_root\": \"0x4a55c4a3"
},
{
"path": "src/ethereum/consensus/mod.rs",
"chars": 31617,
"preview": "use std::{\n fmt::Display,\n ops::{Deref, DerefMut},\n str::FromStr,\n};\n\nuse ed::{Decode, Encode, Terminated};\nuse"
},
{
"path": "src/ethereum/consensus/relayer.rs",
"chars": 4830,
"preview": "use orga::client::Client as OrgaClient;\nuse reqwest::get;\nuse serde::{Deserialize, Serialize};\n\nuse super::{Bootstrap, B"
},
{
"path": "src/ethereum/consensus/test_fixtures.json",
"chars": 230994,
"preview": "[\n {\"version\":\"deneb\",\"data\":{\"header\":{\"beacon\":{\"slot\":\"10051584\",\"proposer_index\":\"963687\",\"parent_root\":\"0x5d2f33"
},
{
"path": "src/ethereum/contracts/Babylon.json",
"chars": 45154,
"preview": "{\"abi\":[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_id\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_tokenContract"
},
{
"path": "src/ethereum/contracts/Babylon.sol",
"chars": 2460,
"preview": "//SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.20;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";"
},
{
"path": "src/ethereum/contracts/CosmosERC20.json",
"chars": 44183,
"preview": "{\"abi\":[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_gravityAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_n"
},
{
"path": "src/ethereum/contracts/CosmosToken.sol",
"chars": 1186,
"preview": "//SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.20;\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n"
},
{
"path": "src/ethereum/contracts/Nomic.json",
"chars": 159814,
"preview": "{\"abi\":[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_validators"
},
{
"path": "src/ethereum/contracts/Nomic.sol",
"chars": 28000,
"preview": "//SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.20;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";"
},
{
"path": "src/ethereum/mod.rs",
"chars": 67549,
"preview": "use alloy_core::{\n primitives::keccak256,\n sol_types::{sol, SolValue},\n};\nuse bitcoin::secp256k1::{\n ecdsa::{Re"
},
{
"path": "src/ethereum/proofs.rs",
"chars": 10950,
"preview": "use crate::error::Error;\nuse crate::error::Result as AppResult;\nuse alloy_primitives::Address as EthAddress;\nuse alloy_r"
},
{
"path": "src/ethereum/relayer.rs",
"chars": 2120,
"preview": "use super::proofs::{BridgeContractData, StateProof};\nuse crate::error::Result as AppResult;\nuse crate::ethereum::proofs:"
},
{
"path": "src/ethereum/signer.rs",
"chars": 2448,
"preview": "use crate::app::{InnerApp, Nom};\nuse crate::bitcoin::signatory::derive_pubkey;\nuse crate::bitcoin::signer::Signer;\nuse c"
},
{
"path": "src/frost/dkg.rs",
"chars": 4851,
"preview": "use super::{Adapter, Config};\nuse ed::{Decode, Encode};\nuse frost_secp256k1_tr::keys::{dkg::*, PublicKeyPackage};\nuse or"
},
{
"path": "src/frost/encoding.rs",
"chars": 2108,
"preview": "use ed::{Decode, Encode, Terminated};\nuse orga::describe::Descriptor;\nuse orga::migrate::Migrate;\nuse orga::query::Query"
},
{
"path": "src/frost/mod.rs",
"chars": 22081,
"preview": "use std::collections::{BTreeMap, HashSet};\nuse std::ops::Range;\n\nuse orga::coins::{Address, Symbol};\nuse orga::collectio"
},
{
"path": "src/frost/signer.rs",
"chars": 14884,
"preview": "use std::collections::HashMap;\nuse std::path::Path;\n\nuse frost_secp256k1_tr::round1::{commit, SigningCommitments, Signin"
},
{
"path": "src/frost/signing.rs",
"chars": 6754,
"preview": "use ed::{Decode, Encode};\nuse frost_secp256k1_tr::keys::PublicKeyPackage;\nuse frost_secp256k1_tr::round2::SignatureShare"
},
{
"path": "src/incentives.rs",
"chars": 4761,
"preview": "//! This module creates incentive accounts, allowing eligible users to claim\n//! tokens based on participation in the No"
},
{
"path": "src/lib.rs",
"chars": 1121,
"preview": "//! Nomic is a protocol which enables decentralized custody of Bitcoin, to power\n//! bridging, L2's, Bitcoin staking, an"
},
{
"path": "src/network.rs",
"chars": 11137,
"preview": "//! Network configuration, for setting defaults configured for Nomic Stakenet,\n//! Nomic Testnet, or a local network. Th"
},
{
"path": "src/utils.rs",
"chars": 16884,
"preview": "//! Utility functions used by end-to-end tests.\n\n#![cfg(not(target_arch = \"wasm32\"))]\n#[cfg(feature = \"full\")]\nuse crate"
},
{
"path": "stakenet_reserve_scripts.csv",
"chars": 6252038,
"preview": "5275,2102518c5d0375d493837a3c594208e35ed7c49edc804891377baab3841f2149dec9ac630347a8126700687c21027df902288aef0b57b5085fa"
},
{
"path": "testnet_addresses.csv",
"chars": 45045,
"preview": "nomic1p72gksuyyc304764w4l2f0em7yu03y3sh9d38j\nnomic1nk636qct5tpsyr06s2nmrpvgx79ur0jesdvntp\nnomic15r6m2ekr886gd9rkx6e2sm78"
},
{
"path": "tests/bitcoin.rs",
"chars": 62470,
"preview": "#![feature(async_closure)]\nuse bitcoin::blockdata::transaction::EcdsaSighashType;\nuse bitcoin::util::bip32::{ChildNumber"
},
{
"path": "tests/header_queue.rs",
"chars": 11915,
"preview": "use bitcoin::consensus::Decodable;\nuse bitcoin::BlockHeader;\nuse bitcoind::bitcoincore_rpc::{self, Error as RpcError, Rp"
},
{
"path": "tests/ibc.rs",
"chars": 26777,
"preview": "#![feature(async_closure)]\nuse bitcoin::secp256k1;\nuse bitcoin::util::bip32::ExtendedPubKey;\nuse bitcoincore_rpc_async::"
},
{
"path": "tests/node.rs",
"chars": 1076,
"preview": "use chrono::{TimeZone, Utc};\nuse log::info;\nuse nomic::utils::{poll_for_blocks, set_time, setup_test_app};\nuse orga::abc"
},
{
"path": "tests/node_spawn.rs",
"chars": 3432,
"preview": "use orga::merk::MerkStore;\n\n#[ignore]\n#[serial_test::serial]\n#[test]\nfn fresh_local_network() {\n let dir = tempfile::"
},
{
"path": "tests/relayer.rs",
"chars": 1595,
"preview": "#![cfg(todo)]\n\nuse bitcoincore_rpc::{Auth, Client as BtcClient, RpcApi};\nuse bitcoind::BitcoinD;\nuse nomic::bitcoin::ada"
},
{
"path": "wasm/Cargo.toml",
"chars": 1098,
"preview": "[package]\nname = \"nomic-wasm\"\nversion = \"0.6.2\"\nauthors = [\"The wasm-bindgen Developers\"]\nedition = \"2018\"\n\n[lib]\ncrate-"
},
{
"path": "wasm/index.html",
"chars": 458,
"preview": "<html>\n\n<head>\n <meta content=\"text/html;charset=utf-8\" http-equiv=\"Content-Type\" />\n</head>\n\n<body>\n <script type"
},
{
"path": "wasm/src/error.rs",
"chars": 565,
"preview": "use std::string::FromUtf8Error;\n\nuse nomic::thiserror;\nuse wasm_bindgen::prelude::JsValue;\n\n#[derive(Debug, thiserror::E"
},
{
"path": "wasm/src/lib.rs",
"chars": 24877,
"preview": "#![feature(async_closure)]\n#![feature(async_fn_in_trait)]\nmod error;\nmod types;\nmod web_client;\n\nuse crate::error::Error"
},
{
"path": "wasm/src/types.rs",
"chars": 2080,
"preview": "use wasm_bindgen::prelude::*;\n\n#[wasm_bindgen(getter_with_clone)]\npub struct DepositAddress {\n pub address: String,\n "
},
{
"path": "wasm/src/web_client.rs",
"chars": 5290,
"preview": "use futures_lite::Future;\nuse nomic::orga::abci::App;\nuse nomic::orga::call::Call;\nuse nomic::orga::client::Transport;\nu"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the nomic-io/nomic GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 144 files (62.3 MB), approximately 2.1M tokens, and a symbol index with 1716 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.