diff --git a/src/runes.rs b/src/runes.rs index 3a247aa12a..75a3436cbf 100644 --- a/src/runes.rs +++ b/src/runes.rs @@ -4477,6 +4477,362 @@ mod tests { ); } + #[test] + fn open_mints_must_be_ended_with_etched_height_plus_offset_end() { + let context = Context::builder().arg("--index-runes").build(); + + let (txid0, id) = context.etch( + Runestone { + etching: Some(Etching { + rune: Some(Rune(RUNE)), + terms: Some(Terms { + amount: Some(1000), + cap: Some(100), + height: (None, Some(100)), + offset: (None, Some(2)), + }), + ..default() + }), + ..default() + }, + 1, + ); + + let mut entry = RuneEntry { + block: id.block, + etching: txid0, + spaced_rune: SpacedRune { + rune: Rune(RUNE), + spacers: 0, + }, + terms: Some(Terms { + amount: Some(1000), + height: (None, Some(100)), + offset: (None, Some(2)), + cap: Some(100), + }), + timestamp: id.block, + ..default() + }; + + context.assert_runes([(id, entry)], []); + + let txid1 = context.core.broadcast_tx(TransactionTemplate { + inputs: &[(2, 0, 0, Witness::new())], + op_return: Some( + Runestone { + mint: Some(id), + ..default() + } + .encipher(), + ), + ..default() + }); + + context.mine_blocks(1); + entry.mints += 1; + + context.assert_runes( + [(id, entry)], + [( + OutPoint { + txid: txid1, + vout: 0, + }, + vec![(id, 1000)], + )], + ); + + context.core.broadcast_tx(TransactionTemplate { + inputs: &[(3, 0, 0, Witness::new())], + op_return: Some( + Runestone { + mint: Some(id), + ..default() + } + .encipher(), + ), + ..default() + }); + + context.mine_blocks(1); + + context.assert_runes( + [(id, entry)], + [( + OutPoint { + txid: txid1, + vout: 0, + }, + vec![(id, 1000)], + )], + ); + } + + #[test] + fn open_mints_must_be_ended_with_height_end() { + let context = Context::builder().arg("--index-runes").build(); + + let (txid0, id) = context.etch( + Runestone { + etching: Some(Etching { + rune: Some(Rune(RUNE)), + terms: Some(Terms { + amount: Some(1000), + cap: Some(100), + height: (None, Some(10)), + offset: (None, Some(100)), + }), + ..default() + }), + ..default() + }, + 1, + ); + + let mut entry = RuneEntry { + block: id.block, + etching: txid0, + spaced_rune: SpacedRune { + rune: Rune(RUNE), + spacers: 0, + }, + terms: Some(Terms { + amount: Some(1000), + height: (None, Some(10)), + offset: (None, Some(100)), + cap: Some(100), + }), + timestamp: id.block, + ..default() + }; + + context.assert_runes([(id, entry)], []); + + let txid1 = context.core.broadcast_tx(TransactionTemplate { + inputs: &[(2, 0, 0, Witness::new())], + op_return: Some( + Runestone { + mint: Some(id), + ..default() + } + .encipher(), + ), + ..default() + }); + + context.mine_blocks(1); + entry.mints += 1; + + context.assert_runes( + [(id, entry)], + [( + OutPoint { + txid: txid1, + vout: 0, + }, + vec![(id, 1000)], + )], + ); + + context.core.broadcast_tx(TransactionTemplate { + inputs: &[(3, 0, 0, Witness::new())], + op_return: Some( + Runestone { + mint: Some(id), + ..default() + } + .encipher(), + ), + ..default() + }); + + context.mine_blocks(1); + + context.assert_runes( + [(id, entry)], + [( + OutPoint { + txid: txid1, + vout: 0, + }, + vec![(id, 1000)], + )], + ); + } + + #[test] + fn open_mints_must_be_started_with_height_start() { + let context = Context::builder().arg("--index-runes").build(); + + let (txid0, id) = context.etch( + Runestone { + etching: Some(Etching { + rune: Some(Rune(RUNE)), + terms: Some(Terms { + amount: Some(1000), + cap: Some(100), + height: (Some(11), None), + offset: (Some(1), None), + }), + ..default() + }), + ..default() + }, + 1, + ); + + let mut entry0 = RuneEntry { + block: id.block, + etching: txid0, + spaced_rune: SpacedRune { + rune: Rune(RUNE), + spacers: 0, + }, + terms: Some(Terms { + amount: Some(1000), + height: (Some(11), None), + offset: (Some(1), None), + cap: Some(100), + }), + timestamp: id.block, + ..default() + }; + + context.mine_blocks(1); + + context.core.broadcast_tx(TransactionTemplate { + inputs: &[(2, 0, 0, Witness::new())], + op_return: Some( + Runestone { + mint: Some(id), + ..default() + } + .encipher(), + ), + ..default() + }); + + context.mine_blocks(1); + + context.assert_runes([(id, entry0)], []); + + context.mine_blocks(1); + + let txid1 = context.core.broadcast_tx(TransactionTemplate { + inputs: &[(3, 0, 0, Witness::new())], + op_return: Some( + Runestone { + mint: Some(id), + ..default() + } + .encipher(), + ), + ..default() + }); + + context.mine_blocks(1); + + entry0.mints += 1; + + context.assert_runes( + [(id, entry0)], + [( + OutPoint { + txid: txid1, + vout: 0, + }, + vec![(id, 1000)], + )], + ); + } + + #[test] + fn open_mints_must_be_started_with_etched_height_plus_offset_start() { + let context = Context::builder().arg("--index-runes").build(); + + let (txid0, id) = context.etch( + Runestone { + etching: Some(Etching { + rune: Some(Rune(RUNE)), + terms: Some(Terms { + amount: Some(1000), + cap: Some(100), + height: (Some(9), None), + offset: (Some(3), None), + }), + ..default() + }), + ..default() + }, + 1, + ); + + let mut entry = RuneEntry { + block: id.block, + etching: txid0, + spaced_rune: SpacedRune { + rune: Rune(RUNE), + spacers: 0, + }, + terms: Some(Terms { + amount: Some(1000), + height: (Some(9), None), + offset: (Some(3), None), + cap: Some(100), + }), + timestamp: id.block, + ..default() + }; + + context.mine_blocks(1); + + context.core.broadcast_tx(TransactionTemplate { + inputs: &[(2, 0, 0, Witness::new())], + op_return: Some( + Runestone { + mint: Some(id), + ..default() + } + .encipher(), + ), + ..default() + }); + + context.mine_blocks(1); + + context.assert_runes([(id, entry)], []); + + context.mine_blocks(1); + + let txid1 = context.core.broadcast_tx(TransactionTemplate { + inputs: &[(3, 0, 0, Witness::new())], + op_return: Some( + Runestone { + mint: Some(id), + ..default() + } + .encipher(), + ), + ..default() + }); + + context.mine_blocks(1); + + entry.mints += 1; + + context.assert_runes( + [(id, entry)], + [( + OutPoint { + txid: txid1, + vout: 0, + }, + vec![(id, 1000)], + )], + ); + } + #[test] fn open_mints_with_offset_end_zero_can_be_premined() { let context = Context::builder().arg("--index-runes").build();