Skip to content

RPC: Restore UTXO origin without leaking addition record #933

Description

@Sword-Smith

Add an endpoint that returns all the (block hash, BlockHeader) pairs that could be the origin of the UTXO referenced by the AbsoluteIndexSet.

Suggested interface

async fn utxo_origin_from_absolute_indices_call(
        &self,
        request: UtxoOriginFromAbsoluteIndicesRequest,
    ) -> RpcResult<UtxoOriginFromAbsoluteIndicesResponse>;

pub struct UtxoOriginFromAbsoluteIndicesRequest {
    pub absolute_index_sets: Vec<RpcAbsoluteIndexSet>,
}

pub struct UtxoOriginFromAbsoluteIndicesResponse {
    pub block_infos: Vec<BlockHeaderAndDigest>,
}

pub struct BlockAoclInfo {
    header: BlockHeader,
    block_hash: Digest,
    min_aocl_index: u64,
    max_aocl_index: u64
}

Motivation

Consider the below code in import_randomness in NeptuneWallet. Here, the client reveals the AOCL leaf index (or, equivalently the AdditionRecord) to the server in order to learn the block hash, block height, and timestamp of the block in which the UTXO was mined. To prevent revealing this AdditionRecord to the server, we need an endpoint that returns a list of (block hash, block header)-pairs for all possible blocks in which this UTXO could have originated. The AbsoluteIndexSet::aocl_range method allows the server to identify the possible AOCL range. From this range, the server can call ArchivalState::canonical_block_digest_of_aocl_index and find the block height of the lower range and that of the upper range. The BlockHeader and block hashes of all blocks within this range are returned.

for recovery_data in confirmed_valid {
            let resp = rpc_client::node_rpc_client()
                .find_utxo_origin(recovery_data.addition_record())
                .await?;

            let Some((block_digest, block_header)) = resp else {
                error!("Unable to find origin of UTXO from imported randomness");
                continue;
            };

            total_recovered += recovery_data.utxo.get_native_currency_amount();
            let new_utxo = UtxoDbData {
                id: 0,
                hash: Tip5::hash(&recovery_data.utxo).to_hex(),
                recovery_data,
                spent_in_block: None,
                confirmed_in_block: UtxoBlockInfo {
                    block_height: block_header.height.into(),
                    block_digest,
                    timestamp: block_header.timestamp,
                },
                confirm_height: block_header.height.value().try_into()?,
                spent_height: None,
                confirmed_txid: None,
                spent_txid: None,
            };

            new_utxos.push(new_utxo);
        }

Edit: Added AOCL range to element type and renamed to BlockAoclInfo.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions