Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 162 additions & 1 deletion lib/state/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ pub fn disconnect_tip(
rwtxn,
&filled_tx,
(**bitname_updates).clone(),
height - 1,
height,
)?;
}
Some(TxData::BatchIcann(batch_icann_data)) => {
Expand Down Expand Up @@ -650,3 +650,164 @@ pub fn disconnect_tip(
}
Ok(())
}

#[cfg(test)]
mod test {
use bitcoin::hashes::Hash as _;

use crate::{
authorization::{self, SigningKey},
state::{
block::{connect, disconnect_tip, validate},
test::fresh_state,
},
types::{
BitName, BitNameDataUpdates, BitNameSeqId, BlockHash, Body,
FilledOutput, FilledOutputContent, FilledTransaction, Hash, Header,
MerkleRoot, MutableBitNameData, OutPoint, OutPointKey, Output,
OutputContent, Transaction, TxData, Update,
},
};

fn header(
prev_side_hash: Option<BlockHash>,
merkle_root: MerkleRoot,
) -> Header {
Header {
merkle_root,
prev_side_hash,
prev_main_hash: bitcoin::BlockHash::from_byte_array([0; 32]),
}
}

fn all_retained_updates() -> BitNameDataUpdates {
BitNameDataUpdates {
commitment: Update::Retain,
socket_addr_v4: Update::Retain,
socket_addr_v6: Update::Retain,
encryption_pubkey: Update::Retain,
signing_pubkey: Update::Retain,
paymail_fee_sats: Update::Retain,
}
}

#[test]
fn disconnect_bitname_data_update() -> anyhow::Result<()> {
let (env, state) = fresh_state("disconnect_bitname_data_update")?;
let signing_key = SigningKey::from_bytes(&[7; 32]);
let verifying_key = signing_key.verifying_key().into();
let address = authorization::get_address(&verifying_key);

let name_hash: Hash = [1; 32];
let revealed_nonce: Hash = [2; 32];
let commitment: Hash =
blake3::keyed_hash(&revealed_nonce, &name_hash).into();
let reservation_txid = [3; 32].into();
let bitname = BitName(name_hash);
let bitname_outpoint = OutPoint::Regular {
txid: [5; 32].into(),
vout: 0,
};

{
let mut rwtxn = env.write_txn()?;
state.bitnames.put_reservation(
&mut rwtxn,
&reservation_txid,
&commitment,
)?;
let registration_tx = Transaction {
inputs: vec![OutPoint::Regular {
txid: reservation_txid,
vout: 0,
}],
outputs: Vec::new(),
memo: Vec::new(),
data: Some(TxData::BitNameRegistration {
name_hash: bitname,
revealed_nonce,
bitname_data: Box::new(MutableBitNameData::default()),
}),
};
let registration_filled = crate::types::FilledTransaction {
transaction: registration_tx,
spent_utxos: vec![FilledOutput {
address,
content: FilledOutputContent::BitNameReservation(
reservation_txid,
commitment,
),
memo: Vec::new(),
}],
};
state.bitnames.apply_registration(
&mut rwtxn,
&registration_filled,
bitname,
&MutableBitNameData::default(),
0,
)?;
let seq = state.bitnames.next_seq(&rwtxn)?;
anyhow::ensure!(seq == BitNameSeqId::new(1));
state.utxos.put(
&mut rwtxn,
&OutPointKey::from_outpoint(&bitname_outpoint),
&FilledOutput {
address,
content: FilledOutputContent::BitName(bitname),
memo: Vec::new(),
},
)?;
rwtxn.commit()?;
}

let genesis_body = Body {
coinbase: Vec::new(),
transactions: Vec::new(),
authorizations: Vec::new(),
};
let genesis_merkle_root =
Body::compute_merkle_root::<FilledTransaction>(&[], &[])?;
let genesis_header = header(None, genesis_merkle_root);
{
let mut rwtxn = env.write_txn()?;
connect(&state, &mut rwtxn, &genesis_header, &genesis_body)?;
rwtxn.commit()?;
}

let mut updates = all_retained_updates();
updates.commitment = Update::Set([9; 32]);
let update_tx = Transaction {
inputs: vec![bitname_outpoint],
outputs: vec![Output::new(address, OutputContent::BitName)],
memo: Vec::new(),
data: Some(TxData::BitNameUpdate(Box::new(updates))),
};
let filled_update_tx = {
let rotxn = env.read_txn()?;
state.fill_transaction(&rotxn, &update_tx)?
};
let authorized_update =
authorization::authorize(&[(address, &signing_key)], update_tx)?;
let update_body = Body::new(vec![authorized_update], Vec::new());
let update_merkle_root =
Body::compute_merkle_root(&[], &[filled_update_tx])?;
let update_header =
header(Some(genesis_header.hash()), update_merkle_root);

{
let rotxn = env.read_txn()?;
validate(&state, &rotxn, &update_header, &update_body)?;
}
{
let mut rwtxn = env.write_txn()?;
connect(&state, &mut rwtxn, &update_header, &update_body)?;
rwtxn.commit()?;
}

let mut rwtxn = env.write_txn()?;
let () =
disconnect_tip(&state, &mut rwtxn, &update_header, &update_body)?;
Ok(())
}
}
Loading