Skip to content

Commit 1c461a8

Browse files
authored
Merge branch 'master' into patch-update-env-with-latest-setting
2 parents ab773a9 + abd9654 commit 1c461a8

File tree

11 files changed

+152
-34
lines changed

11 files changed

+152
-34
lines changed

crates/mockcore/src/api.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ pub trait Api {
2525
verbose: bool,
2626
) -> Result<Value, jsonrpc_core::Error>;
2727

28+
#[rpc(name = "getblockheaderinfo")]
29+
fn get_block_header_info(
30+
&self,
31+
block_hash: BlockHash,
32+
) -> Result<GetBlockHeaderResult, jsonrpc_core::Error>;
33+
2834
#[rpc(name = "getblockstats")]
2935
fn get_block_stats(&self, height: usize) -> Result<GetBlockStatsResult, jsonrpc_core::Error>;
3036

crates/mockcore/src/server.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,36 @@ impl Api for Server {
149149
}
150150
}
151151

152+
fn get_block_header_info(
153+
&self,
154+
block_hash: BlockHash,
155+
) -> Result<GetBlockHeaderResult, jsonrpc_core::Error> {
156+
let state = self.state();
157+
158+
let height = match state.hashes.iter().position(|hash| *hash == block_hash) {
159+
Some(height) => height,
160+
None => return Err(Self::not_found()),
161+
};
162+
163+
Ok(GetBlockHeaderResult {
164+
height,
165+
hash: block_hash,
166+
confirmations: 0,
167+
version: Version::ONE,
168+
version_hex: None,
169+
merkle_root: TxMerkleNode::all_zeros(),
170+
time: 0,
171+
median_time: None,
172+
nonce: 0,
173+
bits: String::new(),
174+
difficulty: 0.0,
175+
chainwork: Vec::new(),
176+
n_tx: 0,
177+
previous_block_hash: None,
178+
next_block_hash: None,
179+
})
180+
}
181+
152182
fn get_block_stats(&self, height: usize) -> Result<GetBlockStatsResult, jsonrpc_core::Error> {
153183
let Some(block_hash) = self.state().hashes.get(height).cloned() else {
154184
return Err(Self::not_found());
@@ -630,12 +660,16 @@ impl Api for Server {
630660
blockhash: Option<BlockHash>,
631661
) -> Result<Value, jsonrpc_core::Error> {
632662
assert_eq!(blockhash, None, "Blockhash param is unsupported");
663+
633664
let state = self.state();
665+
634666
let current_height: u32 = (state.hashes.len() - 1).try_into().unwrap();
635-
let confirmations = state
636-
.txid_to_block_height
637-
.get(&txid)
638-
.map(|tx_height| current_height - tx_height);
667+
668+
let tx_height = state.txid_to_block_height.get(&txid);
669+
670+
let confirmations = tx_height.map(|tx_height| current_height - tx_height);
671+
672+
let blockhash = tx_height.map(|tx_height| state.hashes[usize::try_from(*tx_height).unwrap()]);
639673

640674
if verbose.unwrap_or(false) {
641675
match state.transactions.get(&txid) {
@@ -667,7 +701,7 @@ impl Api for Server {
667701
},
668702
})
669703
.collect(),
670-
blockhash: None,
704+
blockhash,
671705
confirmations,
672706
time: None,
673707
blocktime: None,

crates/ordinals/src/runestone.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ enum Payload {
2020

2121
impl Runestone {
2222
pub const MAGIC_NUMBER: opcodes::All = opcodes::all::OP_PUSHNUM_13;
23-
pub const COMMIT_INTERVAL: u16 = 6;
23+
pub const COMMIT_CONFIRMATIONS: u16 = 6;
2424

2525
pub fn decipher(transaction: &Transaction) -> Option<Artifact> {
2626
let payload = match Runestone::payload(transaction) {

src/index/testing.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ impl Context {
161161
..default()
162162
});
163163

164-
self.mine_blocks(Runestone::COMMIT_INTERVAL.into());
164+
self.mine_blocks(Runestone::COMMIT_CONFIRMATIONS.into());
165165

166166
let mut witness = Witness::new();
167167

@@ -197,7 +197,8 @@ impl Context {
197197
(
198198
txid,
199199
RuneId {
200-
block: u64::try_from(block_count + usize::from(Runestone::COMMIT_INTERVAL) + 1).unwrap(),
200+
block: u64::try_from(block_count + usize::from(Runestone::COMMIT_CONFIRMATIONS) + 1)
201+
.unwrap(),
201202
tx: 1,
202203
},
203204
)

src/index/updater/rune_updater.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -388,20 +388,35 @@ impl<'a, 'tx, 'client> RuneUpdater<'a, 'tx, 'client> {
388388
.get_raw_transaction_info(&input.previous_output.txid, None)
389389
.into_option()?
390390
else {
391-
panic!("input not in UTXO set: {}", input.previous_output);
391+
panic!(
392+
"can't get input transaction: {}",
393+
input.previous_output.txid
394+
);
392395
};
393396

394397
let taproot = tx_info.vout[input.previous_output.vout.into_usize()]
395398
.script_pub_key
396399
.script()?
397400
.is_v1_p2tr();
398401

399-
let mature = tx_info
400-
.confirmations
401-
.map(|confirmations| confirmations >= Runestone::COMMIT_INTERVAL.into())
402-
.unwrap_or_default();
402+
if !taproot {
403+
continue;
404+
}
405+
406+
let commit_tx_height = self
407+
.client
408+
.get_block_header_info(&tx_info.blockhash.unwrap())
409+
.into_option()?
410+
.unwrap()
411+
.height;
412+
413+
let confirmations = self
414+
.height
415+
.checked_sub(commit_tx_height.try_into().unwrap())
416+
.unwrap()
417+
+ 1;
403418

404-
if taproot && mature {
419+
if confirmations >= Runestone::COMMIT_CONFIRMATIONS.into() {
405420
return Ok(true);
406421
}
407422
}

src/runes.rs

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ mod tests {
147147
fn runes_must_be_greater_than_or_equal_to_minimum_for_height() {
148148
let minimum = Rune::minimum_at_height(
149149
Chain::Regtest.network(),
150-
Height((Runestone::COMMIT_INTERVAL + 2).into()),
150+
Height((Runestone::COMMIT_CONFIRMATIONS + 2).into()),
151151
)
152152
.0;
153153

@@ -5196,7 +5196,7 @@ mod tests {
51965196
..default()
51975197
});
51985198

5199-
context.mine_blocks(Runestone::COMMIT_INTERVAL.into());
5199+
context.mine_blocks(Runestone::COMMIT_CONFIRMATIONS.into());
52005200

52015201
let mut witness = Witness::new();
52025202

@@ -5256,7 +5256,7 @@ mod tests {
52565256
..default()
52575257
});
52585258

5259-
context.mine_blocks((Runestone::COMMIT_INTERVAL - 1).into());
5259+
context.mine_blocks((Runestone::COMMIT_CONFIRMATIONS - 2).into());
52605260

52615261
let mut witness = Witness::new();
52625262

@@ -5302,6 +5302,68 @@ mod tests {
53025302
context.assert_runes([], []);
53035303
}
53045304

5305+
#[test]
5306+
fn immature_commits_are_not_valid_even_when_bitcoind_is_ahead() {
5307+
let context = Context::builder().arg("--index-runes").build();
5308+
5309+
let block_count = context.index.block_count().unwrap().into_usize();
5310+
5311+
context.mine_blocks_with_update(1, false);
5312+
5313+
context.core.broadcast_tx(TransactionTemplate {
5314+
inputs: &[(block_count, 0, 0, Witness::new())],
5315+
p2tr: true,
5316+
..default()
5317+
});
5318+
5319+
context.mine_blocks_with_update((Runestone::COMMIT_CONFIRMATIONS - 2).into(), false);
5320+
5321+
let mut witness = Witness::new();
5322+
5323+
let runestone = Runestone {
5324+
etching: Some(Etching {
5325+
rune: Some(Rune(RUNE)),
5326+
terms: Some(Terms {
5327+
amount: Some(1000),
5328+
..default()
5329+
}),
5330+
..default()
5331+
}),
5332+
..default()
5333+
};
5334+
5335+
let tapscript = script::Builder::new()
5336+
.push_slice::<&PushBytes>(
5337+
runestone
5338+
.etching
5339+
.unwrap()
5340+
.rune
5341+
.unwrap()
5342+
.commitment()
5343+
.as_slice()
5344+
.try_into()
5345+
.unwrap(),
5346+
)
5347+
.into_script();
5348+
5349+
witness.push(tapscript);
5350+
5351+
witness.push([]);
5352+
5353+
context.core.broadcast_tx(TransactionTemplate {
5354+
inputs: &[(block_count + 1, 1, 0, witness)],
5355+
op_return: Some(runestone.encipher()),
5356+
outputs: 1,
5357+
..default()
5358+
});
5359+
5360+
context.mine_blocks_with_update(2, false);
5361+
5362+
context.mine_blocks_with_update(1, true);
5363+
5364+
context.assert_runes([], []);
5365+
}
5366+
53055367
#[test]
53065368
fn etchings_are_not_valid_without_commitment() {
53075369
let context = Context::builder().arg("--index-runes").build();
@@ -5316,7 +5378,7 @@ mod tests {
53165378
..default()
53175379
});
53185380

5319-
context.mine_blocks(Runestone::COMMIT_INTERVAL.into());
5381+
context.mine_blocks(Runestone::COMMIT_CONFIRMATIONS.into());
53205382

53215383
let mut witness = Witness::new();
53225384

src/subcommand/server.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2078,7 +2078,7 @@ mod tests {
20782078
..default()
20792079
});
20802080

2081-
self.mine_blocks(Runestone::COMMIT_INTERVAL.into());
2081+
self.mine_blocks((Runestone::COMMIT_CONFIRMATIONS - 1).into());
20822082

20832083
let witness = witness.unwrap_or_else(|| {
20842084
let tapscript = script::Builder::new()
@@ -2535,8 +2535,8 @@ mod tests {
25352535

25362536
server.mine_blocks(1);
25372537

2538-
server.assert_redirect("/search/9:1", "/rune/AAAAAAAAAAAAA");
2539-
server.assert_redirect("/search?query=9:1", "/rune/AAAAAAAAAAAAA");
2538+
server.assert_redirect("/search/8:1", "/rune/AAAAAAAAAAAAA");
2539+
server.assert_redirect("/search?query=8:1", "/rune/AAAAAAAAAAAAA");
25402540

25412541
server.assert_response_regex(
25422542
"/search/100000000000000000000:200000000000000000",
@@ -2616,7 +2616,7 @@ mod tests {
26162616
server.mine_blocks(1);
26172617

26182618
server.assert_response_regex(
2619-
"/rune/9:1",
2619+
"/rune/8:1",
26202620
StatusCode::OK,
26212621
".*<title>Rune AAAAAAAAAAAAA</title>.*",
26222622
);
@@ -2763,11 +2763,11 @@ mod tests {
27632763
<dt>number</dt>
27642764
<dd>0</dd>
27652765
<dt>timestamp</dt>
2766-
<dd><time>1970-01-01 00:00:09 UTC</time></dd>
2766+
<dd><time>1970-01-01 00:00:08 UTC</time></dd>
27672767
<dt>id</dt>
2768-
<dd>9:1</dd>
2768+
<dd>8:1</dd>
27692769
<dt>etching block</dt>
2770-
<dd><a href=/block/9>9</a></dd>
2770+
<dd><a href=/block/8>8</a></dd>
27712771
<dt>etching transaction</dt>
27722772
<dd>1</dd>
27732773
<dt>mint</dt>

src/subcommand/wallet/batch_command.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ impl Batch {
120120

121121
let current_height = u32::try_from(bitcoin_client.get_block_count()?).unwrap();
122122

123-
let reveal_height = current_height + 1 + u32::from(Runestone::COMMIT_INTERVAL);
123+
let reveal_height = current_height + u32::from(Runestone::COMMIT_CONFIRMATIONS);
124124

125125
if let Some(terms) = etching.terms {
126126
if let Some((start, end)) = terms.offset.and_then(|range| range.start.zip(range.end)) {

src/wallet.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,14 +320,14 @@ impl Wallet {
320320

321321
if let Some(transaction) = transaction {
322322
if u32::try_from(transaction.info.confirmations).unwrap()
323-
>= Runestone::COMMIT_INTERVAL.into()
323+
>= Runestone::COMMIT_CONFIRMATIONS.into()
324324
{
325325
let tx_out = self
326326
.bitcoin_client()
327327
.get_tx_out(&commit.txid(), 0, Some(true))?;
328328

329329
if let Some(tx_out) = tx_out {
330-
if tx_out.confirmations >= Runestone::COMMIT_INTERVAL.into() {
330+
if tx_out.confirmations >= Runestone::COMMIT_CONFIRMATIONS.into() {
331331
break;
332332
}
333333
} else {

src/wallet/batch/plan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ impl Plan {
711711
script_sig: script::Builder::new().into_script(),
712712
witness: Witness::new(),
713713
sequence: if etching {
714-
Sequence::from_height(Runestone::COMMIT_INTERVAL)
714+
Sequence::from_height(Runestone::COMMIT_CONFIRMATIONS - 1)
715715
} else {
716716
Sequence::ENABLE_RBF_NO_LOCKTIME
717717
},

tests/wallet/batch_command.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,7 +1480,7 @@ fn batch_can_etch_rune() {
14801480

14811481
assert_eq!(
14821482
reveal.input[0].sequence,
1483-
Sequence::from_height(Runestone::COMMIT_INTERVAL)
1483+
Sequence::from_height(Runestone::COMMIT_CONFIRMATIONS - 1)
14841484
);
14851485

14861486
let Artifact::Runestone(runestone) = Runestone::decipher(&reveal).unwrap() else {
@@ -1577,7 +1577,7 @@ fn batch_can_etch_rune_without_premine() {
15771577

15781578
assert_eq!(
15791579
reveal.input[0].sequence,
1580-
Sequence::from_height(Runestone::COMMIT_INTERVAL)
1580+
Sequence::from_height(Runestone::COMMIT_CONFIRMATIONS - 1)
15811581
);
15821582

15831583
assert_eq!(
@@ -1859,7 +1859,7 @@ fn etch_sub_minimum_rune_error() {
18591859
)
18601860
.core(&core)
18611861
.ord(&ord)
1862-
.expected_stderr("error: rune is less than minimum for next block: A < ZZQYZPATYGGX\n")
1862+
.expected_stderr("error: rune is less than minimum for next block: A < ZZRZCNJJBILX\n")
18631863
.expected_exit_code(1)
18641864
.run_and_extract_stdout();
18651865
}
@@ -2236,7 +2236,7 @@ fn invalid_start_height_error() {
22362236
.core(&core)
22372237
.ord(&ord)
22382238
.expected_stderr(
2239-
"error: `terms.height.start` must be greater than the reveal transaction block height of 8\n",
2239+
"error: `terms.height.start` must be greater than the reveal transaction block height of 7\n",
22402240
)
22412241
.expected_exit_code(1)
22422242
.run_and_extract_stdout();
@@ -2287,7 +2287,7 @@ fn invalid_end_height_error() {
22872287
.core(&core)
22882288
.ord(&ord)
22892289
.expected_stderr(
2290-
"error: `terms.height.end` must be greater than the reveal transaction block height of 8\n",
2290+
"error: `terms.height.end` must be greater than the reveal transaction block height of 7\n",
22912291
)
22922292
.expected_exit_code(1)
22932293
.run_and_extract_stdout();

0 commit comments

Comments
 (0)