Skip to content

Commit 8ff8971

Browse files
committed
Merge branch 'main' into lowhung/313-query-error-type
# Conflicts: # modules/rest_blockfrost/src/handlers/accounts.rs
2 parents bd4198a + 53f4cf1 commit 8ff8971

25 files changed

+819
-98
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Pull Request Title
2+
3+
<!--
4+
Use a short, descriptive title:
5+
Example: `node: fix crash when config is absent`
6+
-->
7+
8+
## Description
9+
10+
<!--
11+
Describe what this PR does and why. Keep it concise but include enough context
12+
for reviewers who are not familiar with the area.
13+
-->
14+
15+
## Related Issue(s)
16+
17+
<!--
18+
Link any related issues, e.g. `Fixes #123` or `Relates to #456`.
19+
-->
20+
21+
## How was this tested?
22+
23+
<!--
24+
Describe the tests that you ran to verify your changes. Include instructions
25+
so reviewers can reproduce. Examples:
26+
- unit tests (command)
27+
- integration tests (how to run)
28+
- manual steps
29+
-->
30+
31+
## Checklist
32+
33+
- [ ] My code builds and passes local tests
34+
- [ ] I added/updated tests for my changes, where applicable
35+
- [ ] I updated documentation (if applicable)
36+
- [ ] CI is green for this PR
37+
38+
## Impact / Side effects
39+
40+
<!--
41+
Describe any potential side effects, e.g. performance, compatibility, or security concerns.
42+
If the PR introduces a breaking change, explain migration steps for users.
43+
-->
44+
45+
## Reviewer notes / Areas to focus
46+
47+
<!--
48+
If you want specific feedback, list files/functions to review or aspects you are unsure about.
49+
-->

common/src/messages.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ pub enum CardanoMessage {
311311

312312
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
313313
pub enum SnapshotMessage {
314+
Startup, // subscribers should listen for incremental snapshot data
314315
Bootstrap(SnapshotStateMessage),
315316
DumpRequest(SnapshotDumpMessage),
316317
Dump(SnapshotStateMessage),

common/src/queries/accounts.rs

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,19 @@ pub const DEFAULT_HISTORICAL_ACCOUNTS_QUERY_TOPIC: (&str, &str) = (
1616
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
1717
pub enum AccountsStateQuery {
1818
GetAccountInfo { account: StakeAddress },
19+
GetAccountsUtxoValuesMap { stake_addresses: Vec<StakeAddress> },
20+
GetAccountsUtxoValuesSum { stake_addresses: Vec<StakeAddress> },
21+
GetAccountsBalancesMap { stake_addresses: Vec<StakeAddress> },
22+
GetAccountsBalancesSum { stake_addresses: Vec<StakeAddress> },
23+
24+
// Served from historical accounts state
1925
GetAccountRewardHistory { account: StakeAddress },
2026
GetAccountHistory { stake_key: Vec<u8> },
2127
GetAccountRegistrationHistory { account: StakeAddress },
2228
GetAccountDelegationHistory { account: StakeAddress },
2329
GetAccountMIRHistory { account: StakeAddress },
2430
GetAccountWithdrawalHistory { account: StakeAddress },
2531
GetAccountAssociatedAddresses { account: StakeAddress },
26-
GetAccountAssets { stake_key: Vec<u8> },
27-
GetAccountAssetsTotals { stake_key: Vec<u8> },
28-
GetAccountUTxOs { stake_key: Vec<u8> },
29-
GetAccountsUtxoValuesMap { stake_addresses: Vec<StakeAddress> },
30-
GetAccountsUtxoValuesSum { stake_addresses: Vec<StakeAddress> },
31-
GetAccountsBalancesMap { stake_addresses: Vec<StakeAddress> },
32-
GetAccountsBalancesSum { stake_addresses: Vec<StakeAddress> },
3332

3433
// Epochs-related queries
3534
GetActiveStakes {},
@@ -50,20 +49,19 @@ pub enum AccountsStateQuery {
5049
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
5150
pub enum AccountsStateQueryResponse {
5251
AccountInfo(AccountInfo),
52+
AccountsUtxoValuesMap(HashMap<StakeAddress, u64>),
53+
AccountsUtxoValuesSum(u64),
54+
AccountsBalancesMap(HashMap<StakeAddress, u64>),
55+
AccountsBalancesSum(u64),
56+
57+
// Served from historical accounts state
5358
AccountRewardHistory(Vec<AccountReward>),
5459
AccountHistory(AccountHistory),
5560
AccountRegistrationHistory(Vec<RegistrationUpdate>),
5661
AccountDelegationHistory(Vec<DelegationUpdate>),
5762
AccountMIRHistory(Vec<AccountWithdrawal>),
5863
AccountWithdrawalHistory(Vec<AccountWithdrawal>),
5964
AccountAssociatedAddresses(Vec<ShelleyAddress>),
60-
AccountAssets(AccountAssets),
61-
AccountAssetsTotals(AccountAssetsTotals),
62-
AccountUTxOs(AccountUTxOs),
63-
AccountsUtxoValuesMap(HashMap<StakeAddress, u64>),
64-
AccountsUtxoValuesSum(u64),
65-
AccountsBalancesMap(HashMap<StakeAddress, u64>),
66-
AccountsBalancesSum(u64),
6765

6866
// Epochs-related responses
6967
ActiveStakes(u64),
@@ -162,21 +160,6 @@ pub struct AccountReward {
162160
pub reward_type: RewardType,
163161
}
164162

165-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
166-
pub struct AccountWithdrawalHistory {}
167-
168-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
169-
pub struct AccountAssociatedAddresses {}
170-
171-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
172-
pub struct AccountAssets {}
173-
174-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
175-
pub struct AccountAssetsTotals {}
176-
177-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
178-
pub struct AccountUTxOs {}
179-
180163
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
181164
pub struct OptimalPoolSizing {
182165
pub total_supply: u64, // total_supply - reserves

common/src/queries/addresses.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::queries::errors::QueryError;
2-
use crate::{Address, AddressTotals, TxIdentifier, UTxOIdentifier};
2+
use crate::{
3+
Address, AddressTotals, NativeAssets, ShelleyAddress, TxIdentifier, UTxOIdentifier, ValueDelta,
4+
};
35

46
pub const DEFAULT_ADDRESS_QUERY_TOPIC: (&str, &str) =
57
("address-state-query-topic", "cardano.query.address");
@@ -9,12 +11,22 @@ pub enum AddressStateQuery {
911
GetAddressTotals { address: Address },
1012
GetAddressUTxOs { address: Address },
1113
GetAddressTransactions { address: Address },
14+
15+
// Accounts related queries
16+
GetAddressesAssets { addresses: Vec<ShelleyAddress> },
17+
GetAddressesTotals { addresses: Vec<ShelleyAddress> },
18+
GetAddressesUTxOs { addresses: Vec<ShelleyAddress> },
1219
}
1320

1421
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
1522
pub enum AddressStateQueryResponse {
1623
AddressTotals(AddressTotals),
1724
AddressUTxOs(Vec<UTxOIdentifier>),
1825
AddressTransactions(Vec<TxIdentifier>),
26+
27+
// Accounts related queries
28+
AddressesAssets(NativeAssets),
29+
AddressesTotals(ValueDelta),
30+
AddressesUTxOs(Vec<UTxOIdentifier>),
1931
Error(QueryError),
2032
}

common/src/queries/blocks.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use crate::queries::errors::QueryError;
22
use crate::{
33
queries::misc::Order,
44
serialization::{Bech32Conversion, Bech32WithHrp},
5-
Address, BlockHash, GenesisDelegate, HeavyDelegate, KeyHash, TxHash, TxIdentifier, VrfKeyHash,
5+
Address, BlockHash, GenesisDelegate, HeavyDelegate, KeyHash, TxHash, TxIdentifier,
6+
UTxOIdentifier, VrfKeyHash,
67
};
78
use cryptoxide::hashing::blake2b::Blake2b;
89
use serde::ser::{Serialize, SerializeStruct, Serializer};
@@ -68,6 +69,9 @@ pub enum BlocksStateQuery {
6869
GetTransactionHashes {
6970
tx_ids: Vec<TxIdentifier>,
7071
},
72+
GetUTxOHashes {
73+
utxo_ids: Vec<UTxOIdentifier>,
74+
},
7175
}
7276

7377
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@@ -91,6 +95,7 @@ pub enum BlocksStateQueryResponse {
9195
BlockInvolvedAddresses(BlockInvolvedAddresses),
9296
BlockHashes(BlockHashes),
9397
TransactionHashes(TransactionHashes),
98+
UTxOHashes(UTxOHashes),
9499
Error(QueryError),
95100
}
96101

@@ -229,3 +234,9 @@ pub struct BlockHashes {
229234
pub struct TransactionHashes {
230235
pub tx_hashes: HashMap<TxIdentifier, TxHash>,
231236
}
237+
238+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
239+
pub struct UTxOHashes {
240+
pub block_hashes: Vec<BlockHash>,
241+
pub tx_hashes: Vec<TxHash>,
242+
}

common/src/queries/utxos.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::queries::errors::QueryError;
2-
use crate::{UTxOIdentifier, Value};
2+
use crate::{UTXOValue, UTxOIdentifier, Value};
33

44
pub const DEFAULT_UTXOS_QUERY_TOPIC: (&str, &str) =
55
("utxo-state-query-topic", "cardano.query.utxos");
@@ -9,10 +9,14 @@ pub enum UTxOStateQuery {
99
GetUTxOsSum {
1010
utxo_identifiers: Vec<UTxOIdentifier>,
1111
},
12+
GetUTxOs {
13+
utxo_identifiers: Vec<UTxOIdentifier>,
14+
},
1215
}
1316

1417
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
1518
pub enum UTxOStateQueryResponse {
1619
UTxOsSum(Value),
20+
UTxOs(Vec<UTXOValue>),
1721
Error(QueryError),
1822
}

common/src/snapshot/NOTES.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Bootstrapping from a Snapshot file
2+
3+
We can boot an Acropolis node either from geneis and replay all of the blocks up to
4+
some point, or we can boot from a snapshot file. This module provides the components
5+
needed to boot from a snapshot file.
6+
See [snapshot_bootsrapper](../../../modules/snapshot_bootstrapper/src/snapshot_bootstrapper.rs) for the process that
7+
references and runs with these helpers.
8+
9+
Booting from a snapshot takes minutes instead of the hours it takes to boot from
10+
genesis. It also allows booting from a given epoch which allows one to create tests
11+
that rely only on that epoch of data. We're also skipping some of the problematic
12+
eras and will typically boot from Conway around epoch 305, 306, and 307. It takes
13+
three epochs to have enough context to correctly calculate the rewards.
14+
15+
The required data for boostrapping are:
16+
17+
- snapshot files (each has an associated epoch number and point)
18+
- nonces
19+
- headers
20+
21+
## Snapshot Files
22+
23+
The snapshots come from the Amaru project. In their words,
24+
"the snapshots we generated are different [from a Mithril snapshot]: they're
25+
the actual ledger state; i.e. the in-memory state that is constructed by iterating over each block up to a specific
26+
point. So, it's all the UTxOs, the set of pending governance actions, the account balance, etc.
27+
If you get this from a trusted source, you don't need to do any replay, you can just start up and load this from disk.
28+
The format of these is completely non-standard; we just forked the haskell node and spit out whatever we needed to in
29+
CBOR."
30+
31+
Snapshot files are referenced by their epoch number in the config.json file below.
32+
33+
See [Amaru snapshot format](../../../docs/amaru-snapshot-structure.md)
34+
35+
## Configuration files
36+
37+
There is a path for each network bootstrap configuration file. Network Should
38+
be one of 'mainnet', 'preprod', 'preview' or 'testnet_<magic>' where
39+
`magic` is a 32-bits unsigned value denoting a particular testnet.
40+
41+
Data structure, e.g. as [Amaru mainnet](https://github.com/pragma-org/amaru/tree/main/data/mainnet)
42+
43+
The bootstrapper will be given a path to a directory that is expected to contain
44+
the following files: snapshots.json, nonces.json, and headers.json. The path will
45+
be used as a prefix to resolve per-network configuration files
46+
needed for bootstrapping. Given a source directory `data`, and a
47+
a network name of `preview`, the expected layout for configuration files would be:
48+
49+
* `data/preview/config.json`: a list of epochs to load.
50+
* `data/preview/snapshots.json`: a list of `Snapshot` values (epoch, point, url)
51+
* `data/preview/nonces.json`: a list of `InitialNonces` values,
52+
* `data/preview/headers.json`: a list of `Point`s.
53+
54+
These files are loaded by [snapshot_bootsrapper](../../../modules/snapshot_bootstrapper/src/snapshot_bootstrapper.rs)
55+
during bootup.
56+
57+
## Bootstrapping sequence
58+
59+
The bootstrapper will be started with an argument that specifies a network,
60+
e.g. "mainnet". From the network, it will build a path to the configuration
61+
and snapshot files as shown above, then load the data contained or described
62+
in those files. config.json holds a list of typically 3 epochs that can be
63+
used to index into snapshots.json to find the corresponding URLs and meta-data
64+
for each of the three snapshot files. Loading occurs in this order:
65+
66+
* publish `SnapshotMessage::Startup`
67+
* download the snapshots (on demand; may have already been done externally)
68+
* parse each snapshot and publish their data on the message bus
69+
* read nonces and publish
70+
* read headers and publish
71+
* publish `CardanoMessage::GenesisComplete(GenesisCompleteMessage {...})`
72+
73+
Modules in the system will have subscribed to the Startup message and also
74+
to individual structural data update messages before the
75+
boostrapper runs the above sequence. Upon receiving the `Startup` message,
76+
they will use data messages to populate their state, history (for BlockFrost),
77+
and any other state required to achieve readiness to operate on reception of
78+
the `GenesisCompleteMessage`.
79+
80+
## Data update messages
81+
82+
The bootstrapper will publish data as it parses the snapshot files, nonces, and
83+
headers. Snapshot parsing is done while streaming the data to keep the memory
84+
footprint lower. As elements of the file are parsed, callbacks provide the data
85+
to the boostrapper which publishes the data on the message bus.
86+
87+
There are TODO markers in [snapshot_bootsrapper](../../../modules/snapshot_bootstrapper/src/snapshot_bootstrapper.rs)
88+
that show where to add the
89+
publishing of the parsed snapshot data.
90+
91+
92+

common/src/types.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,22 @@ impl Neg for ValueDelta {
446446
}
447447
}
448448

449+
/// Value stored in UTXO
450+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
451+
pub struct UTXOValue {
452+
/// Address in binary
453+
pub address: Address,
454+
455+
/// Value in Lovelace
456+
pub value: Value,
457+
458+
/// Datum
459+
pub datum: Option<Datum>,
460+
461+
/// Reference script
462+
pub reference_script: Option<ReferenceScript>,
463+
}
464+
449465
/// Transaction output (UTXO)
450466
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
451467
pub struct TxOutput {

modules/address_state/src/address_state.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,30 @@ impl AddressState {
251251
)),
252252
}
253253
}
254+
AddressStateQuery::GetAddressesAssets { addresses } => {
255+
match state.get_addresses_assets(addresses).await {
256+
Ok(assets) => AddressStateQueryResponse::AddressesAssets(assets),
257+
Err(e) => AddressStateQueryResponse::Error(QueryError::internal_error(
258+
e.to_string(),
259+
)),
260+
}
261+
}
262+
AddressStateQuery::GetAddressesTotals { addresses } => {
263+
match state.get_addresses_totals(addresses).await {
264+
Ok(totals) => AddressStateQueryResponse::AddressesTotals(totals),
265+
Err(e) => AddressStateQueryResponse::Error(QueryError::internal_error(
266+
e.to_string(),
267+
)),
268+
}
269+
}
270+
AddressStateQuery::GetAddressesUTxOs { addresses } => {
271+
match state.get_addresses_utxos(addresses).await {
272+
Ok(utxos) => AddressStateQueryResponse::AddressesUTxOs(utxos),
273+
Err(e) => AddressStateQueryResponse::Error(QueryError::internal_error(
274+
e.to_string(),
275+
)),
276+
}
277+
}
254278
};
255279
Arc::new(Message::StateQueryResponse(StateQueryResponse::Addresses(
256280
response,

0 commit comments

Comments
 (0)