Skip to content

Commit

Permalink
Allow reinscribing with wallet (#2432)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphjaph authored Sep 11, 2023
1 parent 422bc01 commit 833854d
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/subcommand/preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ impl Preview {
satpoint: None,
dry_run: false,
no_limit: false,
reinscribe: false,
destination: None,
parent: None,
postage: Some(TransactionBuilder::TARGET_POSTAGE),
Expand Down
32 changes: 29 additions & 3 deletions src/subcommand/wallet/inscribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ pub(crate) struct Inscribe {
pub(crate) postage: Option<Amount>,
#[clap(long, help = "Make inscription a child of <PARENT>.")]
pub(crate) parent: Option<InscriptionId>,
#[clap(long, help = "Allow reinscription.")]
pub(crate) reinscribe: bool,
}

impl Inscribe {
Expand Down Expand Up @@ -127,6 +129,7 @@ impl Inscribe {
self.commit_fee_rate.unwrap_or(self.fee_rate),
self.fee_rate,
self.no_limit,
self.reinscribe,
match self.postage {
Some(postage) => postage,
_ => TransactionBuilder::TARGET_POSTAGE,
Expand Down Expand Up @@ -209,6 +212,7 @@ impl Inscribe {
commit_fee_rate: FeeRate,
reveal_fee_rate: FeeRate,
no_limit: bool,
reinscribe: bool,
postage: Amount,
) -> Result<(Transaction, Transaction, TweakedKeyPair, u64)> {
let satpoint = if let Some(satpoint) = satpoint {
Expand All @@ -229,9 +233,16 @@ impl Inscribe {
.ok_or_else(|| anyhow!("wallet contains no cardinal utxos"))?
};

let mut reinscription = false;

for (inscribed_satpoint, inscription_id) in &inscriptions {
if inscribed_satpoint == &satpoint {
return Err(anyhow!("sat at {} already inscribed", satpoint));
if *inscribed_satpoint == satpoint {
reinscription = true;
if reinscribe {
continue;
} else {
return Err(anyhow!("sat at {} already inscribed", satpoint));
}
}

if inscribed_satpoint.outpoint == satpoint.outpoint {
Expand All @@ -242,6 +253,12 @@ impl Inscribe {
}
}

if reinscribe && !reinscription {
return Err(anyhow!(
"reinscribe flag set but this would not be a reinscription"
));
}

let secp256k1 = Secp256k1::new();
let key_pair = UntweakedKeyPair::new(&secp256k1, &mut rand::thread_rng());
let (public_key, _parity) = XOnlyPublicKey::from_keypair(&key_pair);
Expand Down Expand Up @@ -527,6 +544,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
false,
false,
TransactionBuilder::TARGET_POSTAGE,
)
.unwrap();
Expand All @@ -542,7 +560,7 @@ mod tests {
}

#[test]
fn inscript_tansactions_opt_in_to_rbf() {
fn inscribe_tansactions_opt_in_to_rbf() {
let utxos = vec![(outpoint(1), Amount::from_sat(20000))];
let inscription = inscription("text/plain", "ord");
let commit_address = change(0);
Expand All @@ -560,6 +578,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
false,
false,
TransactionBuilder::TARGET_POSTAGE,
)
.unwrap();
Expand Down Expand Up @@ -597,6 +616,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
false,
false,
TransactionBuilder::TARGET_POSTAGE,
)
.unwrap_err()
Expand Down Expand Up @@ -641,6 +661,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
false,
false,
TransactionBuilder::TARGET_POSTAGE,
)
.is_ok())
Expand Down Expand Up @@ -679,6 +700,7 @@ mod tests {
FeeRate::try_from(fee_rate).unwrap(),
FeeRate::try_from(fee_rate).unwrap(),
false,
false,
TransactionBuilder::TARGET_POSTAGE,
)
.unwrap();
Expand Down Expand Up @@ -750,6 +772,7 @@ mod tests {
FeeRate::try_from(fee_rate).unwrap(),
FeeRate::try_from(fee_rate).unwrap(),
false,
false,
TransactionBuilder::TARGET_POSTAGE,
)
.unwrap();
Expand Down Expand Up @@ -825,6 +848,7 @@ mod tests {
FeeRate::try_from(commit_fee_rate).unwrap(),
FeeRate::try_from(fee_rate).unwrap(),
false,
false,
TransactionBuilder::TARGET_POSTAGE,
)
.unwrap();
Expand Down Expand Up @@ -876,6 +900,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
false,
false,
TransactionBuilder::TARGET_POSTAGE,
)
.unwrap_err()
Expand Down Expand Up @@ -909,6 +934,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
true,
false,
TransactionBuilder::TARGET_POSTAGE,
)
.unwrap();
Expand Down
102 changes: 102 additions & 0 deletions tests/wallet/inscribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,3 +532,105 @@ fn inscribe_with_parent_inscription_and_fee_rate() {
),
);
}

#[test]
fn reinscribe_with_flag() {
let rpc_server = test_bitcoincore_rpc::spawn();
rpc_server.mine_blocks(1);

assert_eq!(rpc_server.descriptors().len(), 0);

create_wallet(&rpc_server);

let inscribe = CommandBuilder::new("wallet inscribe tulip.png --fee-rate 5.0 ")
.write("tulip.png", [1; 520])
.rpc_server(&rpc_server)
.run_and_deserialize_output::<Inscribe>();

assert_eq!(rpc_server.descriptors().len(), 3);

let txid = rpc_server.mine_blocks(1)[0].txdata[2].txid();

let ord_server = TestServer::spawn_with_args(&rpc_server, &[]);
let request = ord_server.request(format!("/content/{}", inscribe.inscription));

assert_eq!(request.status(), 200);

let reinscribe = CommandBuilder::new(format!(
"wallet inscribe orchid.png --fee-rate 1.1 --reinscribe --satpoint {txid}:0:0"
))
.write("orchid.png", [1; 520])
.rpc_server(&rpc_server)
.run_and_deserialize_output::<Inscribe>();

rpc_server.mine_blocks(1);

let ord_server = TestServer::spawn_with_args(&rpc_server, &["--index-sats"]);
let request = ord_server.request(format!("/content/{}", reinscribe.inscription));

assert_eq!(request.status(), 200);
ord_server.assert_response_regex(
format!("/sat/{}", 50 * COIN_VALUE),
format!(
".*<dt>inscriptions</dt>.*<a href=/inscription/{}>.*<a href=/inscription/{}>.*",
inscribe.inscription, reinscribe.inscription
),
);
}

#[test]
fn with_reinscribe_flag_but_not_actually_a_reinscription() {
let rpc_server = test_bitcoincore_rpc::spawn();
rpc_server.mine_blocks(1);

assert_eq!(rpc_server.descriptors().len(), 0);

create_wallet(&rpc_server);

CommandBuilder::new("wallet inscribe tulip.png --fee-rate 5.0 ")
.write("tulip.png", [1; 520])
.rpc_server(&rpc_server)
.run_and_deserialize_output::<Inscribe>();

let coinbase = rpc_server.mine_blocks(1)[0].txdata[0].txid();

CommandBuilder::new(format!(
"wallet inscribe orchid.png --fee-rate 1.1 --reinscribe --satpoint {coinbase}:0:0"
))
.write("orchid.png", [1; 520])
.rpc_server(&rpc_server)
.expected_exit_code(1)
.stderr_regex("error: reinscribe flag set but this would not be a reinscription.*")
.run_and_extract_stdout();
}

#[test]
fn try_reinscribe_without_flag() {
let rpc_server = test_bitcoincore_rpc::spawn();
rpc_server.mine_blocks(1);

assert_eq!(rpc_server.descriptors().len(), 0);

create_wallet(&rpc_server);

let reveal_txid = CommandBuilder::new("wallet inscribe tulip.png --fee-rate 5.0 ")
.write("tulip.png", [1; 520])
.rpc_server(&rpc_server)
.run_and_deserialize_output::<Inscribe>()
.reveal;

assert_eq!(rpc_server.descriptors().len(), 3);

rpc_server.mine_blocks(1);

CommandBuilder::new(format!(
"wallet inscribe orchid.png --fee-rate 1.1 --satpoint {reveal_txid}:0:0"
))
.write("orchid.png", [1; 520])
.rpc_server(&rpc_server)
.expected_exit_code(1)
.stderr_regex(format!(
"error: sat at {reveal_txid}:0:0 already inscribed.*"
))
.run_and_extract_stdout();
}

0 comments on commit 833854d

Please sign in to comment.