Skip to content

Commit 61440dc

Browse files
committed
feat: add annex to env
1 parent 2251fbd commit 61440dc

File tree

7 files changed

+54
-14
lines changed

7 files changed

+54
-14
lines changed

fuzz/fuzz_lib/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ impl<'f> Extractor<'f> {
6464

6565
/// Attempt to yield a type from the fuzzer.
6666
pub fn extract_final_type(&mut self) -> Option<Arc<FinalTy>> {
67-
// We can costruct extremely large types by duplicating Arcs; there
67+
// We can construct extremely large types by duplicating Arcs; there
6868
// is no need to have an exponential blowup in the number of tasks.
6969
const MAX_N_TASKS: usize = 300;
7070

@@ -206,7 +206,7 @@ impl<'f> Extractor<'f> {
206206

207207
/// Attempt to yield a type from the fuzzer.
208208
pub fn extract_old_final_type(&mut self) -> Option<Arc<OldFinalTy>> {
209-
// We can costruct extremely large types by duplicating Arcs; there
209+
// We can construct extremely large types by duplicating Arcs; there
210210
// is no need to have an exponential blowup in the number of tasks.
211211
const MAX_N_TASKS: usize = 300;
212212

src/analysis.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use std::{cmp, fmt};
66
use crate::value::Word;
77
#[cfg(feature = "elements")]
88
use elements::encode::Encodable;
9+
#[cfg(feature = "serde")]
10+
use serde::Serialize;
911
#[cfg(feature = "elements")]
1012
use std::{convert::TryFrom, io};
1113

@@ -65,6 +67,7 @@ impl From<U32Weight> for bitcoin::Weight {
6567
/// Programs that are CPU-heavy need to be padded
6668
/// so that the witness stack provides a large-enough budget.
6769
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
70+
#[cfg_attr(feature = "serde", derive(Serialize))]
6871
pub struct Cost(u32);
6972

7073
impl Cost {
@@ -215,6 +218,7 @@ impl From<Cost> for bitcoin::Weight {
215218

216219
/// Bounds on the resources required by a node during execution on the Bit Machine
217220
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
221+
#[cfg_attr(feature = "serde", derive(Serialize))]
218222
pub struct NodeBounds {
219223
/// Upper bound on the required number of cells (bits).
220224
/// The root additionally requires the bit width of its source and target type (input, output)

src/dag.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ pub trait DagLike: Sized {
347347
/// with the returned nodes. To correct this, you need to call
348348
/// [`PostOrderIterItem::unswap`].
349349
///
350-
/// To avoid confusion, this structure cannot be directly costructed.
350+
/// To avoid confusion, this structure cannot be directly constructed.
351351
/// Instead it is implicit in the [`DagLike::rtl_post_order_iter`]
352352
/// method.
353353
#[derive(Clone, Debug)]

src/human_encoding/named_node.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ pub struct Namer {
504504
}
505505

506506
impl Namer {
507-
/// Costruct a new `Namer`. Will assign the name `main` to the node with
507+
/// Construct a new `Namer`. Will assign the name `main` to the node with
508508
/// the given CMR.
509509
pub fn new_rooted(root_cmr: Cmr) -> Self {
510510
Namer {
@@ -515,7 +515,7 @@ impl Namer {
515515
}
516516
}
517517

518-
/// Costruct a new `Namer`.
518+
/// Construct a new `Namer`.
519519
pub fn new() -> Self {
520520
Namer {
521521
const_idx: 0,

src/jet/elements/c_env.rs

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! High level APIs for creating C FFI compatible environment.
44
//!
55
6+
use bitcoin::taproot::TAPROOT_ANNEX_PREFIX;
67
use hashes::Hash;
78
use std::os::raw::c_uchar;
89

@@ -33,7 +34,6 @@ struct RawOutputData {
3334
/// passed to the C FFI.
3435
#[derive(Debug)]
3536
struct RawInputData {
36-
#[allow(dead_code)] // see FIXME below
3737
pub annex: Option<Vec<c_uchar>>,
3838
// pegin
3939
pub genesis_hash: Option<[c_uchar; 32]>,
@@ -75,8 +75,12 @@ fn new_raw_input<'raw>(
7575
inp_data: &'raw RawInputData,
7676
) -> c_elements::CRawInput<'raw> {
7777
c_elements::CRawInput {
78-
// FIXME actually pass the annex in; see https://github.com/BlockstreamResearch/simplicity/issues/311 for some difficulty here.
79-
annex: core::ptr::null(),
78+
annex: inp_data
79+
.annex
80+
.as_ref()
81+
.map(|annex| c_elements::CRawBuffer::new(annex))
82+
.as_ref()
83+
.map_or(core::ptr::null(), |ptr| ptr as *const _),
8084
prev_txid: inp.previous_output.txid.as_ref(),
8185
pegin: inp_data.genesis_hash.as_ref(),
8286
issuance: if inp.has_issuance() {
@@ -114,7 +118,7 @@ fn new_tx_data(tx: &elements::Transaction, in_utxos: &[ElementsUtxo]) -> RawTran
114118
};
115119
for (inp, in_utxo) in tx.input.iter().zip(in_utxos.iter()) {
116120
let inp_data = RawInputData {
117-
annex: None, // Actually store annex
121+
annex: get_annex(&inp.witness).map(|s| s.to_vec()),
118122
genesis_hash: inp
119123
.pegin_data()
120124
.map(|x| x.genesis_hash.to_raw_hash().to_byte_array()),
@@ -148,14 +152,29 @@ pub(super) fn new_tx(
148152
) -> *mut c_elements::CTransaction {
149153
let mut raw_inputs = Vec::new();
150154
let mut raw_outputs = Vec::new();
155+
// Allocate space for the raw annexes. This dumb `Vec::from_iter` construction is
156+
// equivalent to `vec![None; tx.input.len()]`, but that won't compile because it
157+
// requires Option::<CRawBuffer>::None to be cloneable, which it's not because
158+
// CRawBuffer isn't.
159+
160+
// SAFETY: this allocation *must* live until after the `simplicity_mallocTransaction`
161+
// at the bottom of this function. We convert the vector to a boxed slice to ensure
162+
// it cannot be resized, which would potentially trigger a reallocation.
163+
let mut raw_annexes = Vec::from_iter((0..tx.input.len()).map(|_| None)).into_boxed_slice();
164+
151165
let txid = tx.txid();
152166
let tx_data = new_tx_data(tx, in_utxos);
153-
for ((inp, in_utxo), inp_data) in tx
167+
for (((n, inp), in_utxo), inp_data) in tx
154168
.input
155169
.iter()
170+
.enumerate()
156171
.zip(in_utxos.iter())
157172
.zip(tx_data.inputs.iter())
158173
{
174+
raw_annexes[n] = inp_data
175+
.annex
176+
.as_ref()
177+
.map(|annex| c_elements::CRawBuffer::new(annex));
159178
let res = new_raw_input(inp, in_utxo, inp_data);
160179
raw_inputs.push(res);
161180
}
@@ -172,10 +191,17 @@ pub(super) fn new_tx(
172191
version: tx.version,
173192
locktime: tx.lock_time.to_consensus_u32(),
174193
};
175-
unsafe {
194+
let ret = unsafe {
176195
// SAFETY: this is a FFI call and we constructed its argument correctly.
177196
c_elements::simplicity_mallocTransaction(&c_raw_tx)
178-
}
197+
};
198+
199+
// Explicitly drop raw_annexes so Rust doesn't try any funny business dropping it early.
200+
// Drop raw_inputs first since it contains pointers into raw_annexes and we don't want
201+
// them to dangle. (It'd be safe since they're raw pointers, but still bad mojo.)
202+
drop(raw_inputs);
203+
drop(raw_annexes);
204+
ret
179205
}
180206

181207
pub(super) fn new_tap_env(
@@ -256,3 +282,13 @@ fn serialize_surjection_proof(surjection_proof: &Option<Box<SurjectionProof>>) -
256282
.map(|x| x.serialize())
257283
.unwrap_or_default()
258284
}
285+
286+
/// If the last item in the witness stack is an annex, return the data following the 0x50 byte.
287+
fn get_annex(in_witness: &elements::TxInWitness) -> Option<&[u8]> {
288+
let last_item = in_witness.script_witness.last()?;
289+
if *last_item.first()? == TAPROOT_ANNEX_PREFIX {
290+
Some(&last_item[1..])
291+
} else {
292+
None
293+
}
294+
}

src/node/convert.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub enum Hide {
5858
/// 4. Finally, the node's data is passed to [`Self::convert_data`], whose job
5959
/// it is to compute the cached data for the new node. For `case` combinators
6060
/// where one child was pruned, `convert_data` will receive an `assertl` or
61-
/// `assertl`, as appropriate, rather than a `case`.
61+
/// `assertr`, as appropriate, rather than a `case`.
6262
///
6363
/// If any method returns an error, then iteration is aborted immediately and
6464
/// the error returned to the caller. If the converter would like to recover

src/node/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ impl<N: Marker> Node<N> {
612612

613613
/// Contruct a node from its constituent parts.
614614
///
615-
/// This method can be used to directly costruct a node. It will compute the CMR
615+
/// This method can be used to directly construct a node. It will compute the CMR
616616
/// automatically based on the value of `inner` but requires that `cached_data`
617617
/// be provided.
618618
///

0 commit comments

Comments
 (0)