From 491e89ebdf0a77027b00f55024469a049afeacf5 Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Sat, 30 Mar 2024 16:22:53 -0700 Subject: [PATCH] Set pointer in etching runestone (#3420) --- src/wallet/batch/plan.rs | 12 +-- tests/wallet/balance.rs | 28 +++---- tests/wallet/batch_command.rs | 149 ++++++++++++++++++++++++++++++---- 3 files changed, 147 insertions(+), 42 deletions(-) diff --git a/src/wallet/batch/plan.rs b/src/wallet/batch/plan.rs index 2f09e1ab62..dd4475a6da 100644 --- a/src/wallet/batch/plan.rs +++ b/src/wallet/batch/plan.rs @@ -431,8 +431,6 @@ impl Plan { let runestone; if let Some(etching) = self.etching { - let mut edicts = Vec::new(); - let vout; let destination; premine = etching.premine.to_integer(etching.divisibility)?; @@ -446,12 +444,6 @@ impl Plan { value: TARGET_POSTAGE.to_sat(), }); - edicts.push(Edict { - id: RuneId::default(), - amount: premine, - output, - }); - vout = Some(output); } else { vout = None; @@ -460,7 +452,7 @@ impl Plan { let inner = Runestone { cenotaph: 0, - edicts, + edicts: Vec::new(), etching: Some(ordinals::Etching { divisibility: (etching.divisibility > 0).then_some(etching.divisibility), terms: etching @@ -486,7 +478,7 @@ impl Plan { symbol: Some(etching.symbol), }), mint: None, - pointer: None, + pointer: (premine > 0).then_some((reveal_outputs.len() - 1).try_into().unwrap()), }; let script_pubkey = inner.encipher(); diff --git a/tests/wallet/balance.rs b/tests/wallet/balance.rs index acf61fd106..c5d5ea4001 100644 --- a/tests/wallet/balance.rs +++ b/tests/wallet/balance.rs @@ -1,4 +1,4 @@ -use {super::*, ord::subcommand::wallet::balance::Output}; +use super::*; #[test] fn wallet_balance() { @@ -12,7 +12,7 @@ fn wallet_balance() { CommandBuilder::new("wallet balance") .core(&core) .ord(&ord) - .run_and_deserialize_output::() + .run_and_deserialize_output::() .cardinal, 0 ); @@ -23,8 +23,8 @@ fn wallet_balance() { CommandBuilder::new("wallet balance") .core(&core) .ord(&ord) - .run_and_deserialize_output::(), - Output { + .run_and_deserialize_output::(), + Balance { cardinal: 50 * COIN_VALUE, ordinal: 0, runic: None, @@ -46,8 +46,8 @@ fn inscribed_utxos_are_deducted_from_cardinal() { CommandBuilder::new("wallet balance") .core(&core) .ord(&ord) - .run_and_deserialize_output::(), - Output { + .run_and_deserialize_output::(), + Balance { cardinal: 0, ordinal: 0, runic: None, @@ -62,8 +62,8 @@ fn inscribed_utxos_are_deducted_from_cardinal() { CommandBuilder::new("wallet balance") .core(&core) .ord(&ord) - .run_and_deserialize_output::(), - Output { + .run_and_deserialize_output::(), + Balance { cardinal: 100 * COIN_VALUE - 10_000, ordinal: 10_000, runic: None, @@ -85,8 +85,8 @@ fn runic_utxos_are_deducted_from_cardinal() { CommandBuilder::new("--regtest --index-runes wallet balance") .core(&core) .ord(&ord) - .run_and_deserialize_output::(), - Output { + .run_and_deserialize_output::(), + Balance { cardinal: 0, ordinal: 0, runic: Some(0), @@ -121,8 +121,8 @@ fn runic_utxos_are_deducted_from_cardinal() { CommandBuilder::new("--regtest --index-runes wallet balance") .core(&core) .ord(&ord) - .run_and_deserialize_output::(), - Output { + .run_and_deserialize_output::(), + Balance { cardinal: 50 * COIN_VALUE * 8 - 20_000, ordinal: 10000, runic: Some(10_000), @@ -148,8 +148,8 @@ fn unsynced_wallet_fails_with_unindexed_output() { CommandBuilder::new("wallet balance") .ord(&ord) .core(&core) - .run_and_deserialize_output::(), - Output { + .run_and_deserialize_output::(), + Balance { cardinal: 50 * COIN_VALUE, ordinal: 0, runic: None, diff --git a/tests/wallet/batch_command.rs b/tests/wallet/batch_command.rs index 5e7a648aa9..399db299b4 100644 --- a/tests/wallet/batch_command.rs +++ b/tests/wallet/batch_command.rs @@ -1,4 +1,4 @@ -use {super::*, ord::subcommand::wallet::send}; +use {super::*, ord::subcommand::wallet::send, pretty_assertions::assert_eq}; fn receive(core: &mockcore::Handle, ord: &TestServer) -> Address { let address = CommandBuilder::new("wallet receive") @@ -1411,7 +1411,7 @@ inscriptions: } #[test] -fn batch_inscribe_can_etch_rune() { +fn batch_can_etch_rune() { let core = mockcore::builder().network(Network::Regtest).build(); let ord = TestServer::spawn_with_server_args(&core, &["--regtest", "--index-runes"], &[]); @@ -1420,16 +1420,18 @@ fn batch_inscribe_can_etch_rune() { core.mine_blocks(1); + let rune = SpacedRune { + rune: Rune(RUNE), + spacers: 0, + }; + let batch = batch( &core, &ord, batch::File { etching: Some(batch::Etching { divisibility: 0, - rune: SpacedRune { - rune: Rune(RUNE), - spacers: 0, - }, + rune, supply: "1000".parse().unwrap(), premine: "1000".parse().unwrap(), symbol: '¢', @@ -1463,21 +1465,132 @@ fn batch_inscribe_can_etch_rune() { ), ); - assert!(core.state().is_wallet_address( - &batch - .output - .rune - .unwrap() - .destination - .unwrap() - .require_network(Network::Regtest) - .unwrap() - )); + let destination = batch + .output + .rune + .unwrap() + .destination + .unwrap() + .require_network(Network::Regtest) + .unwrap(); + + assert!(core.state().is_wallet_address(&destination)); + + let reveal = core.tx_by_id(batch.output.reveal); + + assert_eq!( + reveal.input[0].sequence, + Sequence::from_height(Runestone::COMMIT_INTERVAL) + ); + + let runestone = Runestone::from_transaction(&reveal).unwrap(); + + let pointer = reveal.output.len() - 2; + + assert_eq!(runestone.pointer, Some(pointer.try_into().unwrap())); + + assert_eq!( + reveal.output[pointer].script_pubkey, + destination.script_pubkey(), + ); + + assert_eq!( + CommandBuilder::new("--regtest wallet balance") + .core(&core) + .ord(&ord) + .run_and_deserialize_output::(), + Balance { + cardinal: 44999980000, + ordinal: 10000, + runic: Some(10000), + runes: Some(vec![(rune, 1000)].into_iter().collect()), + total: 450 * COIN_VALUE, + } + ); +} + +#[test] +fn batch_can_etch_rune_without_premine() { + let core = mockcore::builder().network(Network::Regtest).build(); + + let ord = TestServer::spawn_with_server_args(&core, &["--regtest", "--index-runes"], &[]); + + create_wallet(&core, &ord); + + core.mine_blocks(1); + + let rune = SpacedRune { + rune: Rune(RUNE), + spacers: 0, + }; + + let batch = batch( + &core, + &ord, + batch::File { + etching: Some(batch::Etching { + divisibility: 0, + rune, + supply: "1000".parse().unwrap(), + premine: "0".parse().unwrap(), + symbol: '¢', + terms: Some(batch::Terms { + cap: 1, + amount: "1000".parse().unwrap(), + height: None, + offset: None, + }), + }), + inscriptions: vec![batch::Entry { + file: "inscription.jpeg".into(), + ..default() + }], + ..default() + }, + ); + + let parent = batch.output.inscriptions[0].id; + + let request = ord.request(format!("/content/{parent}")); + + assert_eq!(request.status(), 200); + assert_eq!(request.headers().get("content-type").unwrap(), "image/jpeg"); + assert_eq!(request.text().unwrap(), "inscription"); + + ord.assert_response_regex( + format!("/inscription/{parent}"), + r".*
rune
\s*
AAAAAAAAAAAAA
.*", + ); + + ord.assert_response_regex( + "/rune/AAAAAAAAAAAAA", + format!( + r".*
parent
\s*
{parent}
.*" + ), + ); + + assert_eq!(batch.output.rune.unwrap().destination, None); + + let reveal = core.tx_by_id(batch.output.reveal); assert_eq!( - core.tx_by_id(batch.output.reveal).input[0].sequence, + reveal.input[0].sequence, Sequence::from_height(Runestone::COMMIT_INTERVAL) ); + + assert_eq!( + CommandBuilder::new("--regtest wallet balance") + .core(&core) + .ord(&ord) + .run_and_deserialize_output::(), + Balance { + cardinal: 44999990000, + ordinal: 10000, + runic: Some(0), + runes: Some(default()), + total: 450 * COIN_VALUE, + } + ); } #[test] @@ -2358,7 +2471,7 @@ fn oversize_runestone_error() { ) .core(&core) .ord(&ord) - .expected_stderr("error: runestone greater than maximum OP_RETURN size: 125 > 82\n") + .expected_stderr("error: runestone greater than maximum OP_RETURN size: 104 > 82\n") .expected_exit_code(1) .run_and_extract_stdout(); }