From bb1ff5529d994563566e0caac1ad4d2cee4e0f4d Mon Sep 17 00:00:00 2001 From: jolestar Date: Fri, 20 Sep 2024 04:23:15 +0800 Subject: [PATCH] [bitseed] Implement bitseed merge --- .../src/jsonrpc_types/state_view.rs | 4 +- crates/rooch/src/commands/bitseed/inscribe.rs | 142 +++++++------ crates/rooch/src/commands/bitseed/split.rs | 28 --- crates/testsuite/features/bitseed.feature | 51 +++-- examples/bitseed_runner/Move.toml | 18 -- examples/bitseed_runner/readme.md | 7 - examples/bitseed_runner/sources/bitseed.move | 47 ----- examples/bitseed_runner/web/README.md | 5 - frameworks/rooch-nursery/doc/bitseed.md | 140 ++++++++++++- frameworks/rooch-nursery/doc/genesis.md | 1 + .../rooch-nursery/doc/inscribe_factory.md | 45 +++- frameworks/rooch-nursery/doc/tick_info.md | 12 ++ frameworks/rooch-nursery/sources/bitseed.move | 53 ++++- frameworks/rooch-nursery/sources/genesis.move | 2 + .../sources/inscribe_factory.move | 196 +++++++++++++++--- .../rooch-nursery/sources/tick_info.move | 13 +- 16 files changed, 536 insertions(+), 228 deletions(-) delete mode 100644 crates/rooch/src/commands/bitseed/split.rs delete mode 100644 examples/bitseed_runner/Move.toml delete mode 100644 examples/bitseed_runner/readme.md delete mode 100644 examples/bitseed_runner/sources/bitseed.move delete mode 100644 examples/bitseed_runner/web/README.md diff --git a/crates/rooch-rpc-api/src/jsonrpc_types/state_view.rs b/crates/rooch-rpc-api/src/jsonrpc_types/state_view.rs index 2faf1a3d96..a28bb127f8 100644 --- a/crates/rooch-rpc-api/src/jsonrpc_types/state_view.rs +++ b/crates/rooch-rpc-api/src/jsonrpc_types/state_view.rs @@ -504,7 +504,9 @@ fn parse_changed_objects( let mut deleted_objs = vec![]; for obj_change in changes { let metadata = obj_change.metadata.clone(); - debug_assert!(obj_change.value.is_some() || !obj_change.fields.is_empty()); + //TODO fixme + //https://github.com/rooch-network/rooch/issues/2657 + //debug_assert!(obj_change.value.is_some() || !obj_change.fields.is_empty()); match obj_change.value { Some(OpView::New(_)) => new_objs.push(metadata), Some(OpView::Modify(_)) => modified_objs.push(metadata), diff --git a/crates/rooch/src/commands/bitseed/inscribe.rs b/crates/rooch/src/commands/bitseed/inscribe.rs index a0b7134c51..cd88721504 100644 --- a/crates/rooch/src/commands/bitseed/inscribe.rs +++ b/crates/rooch/src/commands/bitseed/inscribe.rs @@ -23,7 +23,7 @@ use bitcoin::{ EcdsaSighashType, OutPoint, }; use clap::Parser; -use rooch_rpc_api::jsonrpc_types::btc::{ord::InscriptionObjectView, utxo::UTXOObjectView}; +use rooch_rpc_api::jsonrpc_types::btc::ord::InscriptionObjectView; use rooch_rpc_client::wallet_context::WalletContext; use rooch_types::{ address::{BitcoinAddress, ParsedAddress}, @@ -129,7 +129,7 @@ pub struct InscribeContext { pub utxos: BTreeMap, pub reveal_scripts_to_sign: Vec, pub control_blocks_to_sign: Vec, - pub reveal_input_start_index: Option, + pub burn_input_start_index: Option, pub total_burn_postage: Option, } @@ -148,7 +148,8 @@ pub struct Inscriber { option: InscribeOptions, inscriptions: Vec, inscriptions_to_burn: Vec, - satpoint: (SatPoint, UTXOObjectView), + satpoint: SatPoint, + utxos: BTreeMap, network: bitcoin::Network, destination: Address, change_address: Address, @@ -200,13 +201,17 @@ impl Inscriber { } }; + let mut utxos = BTreeMap::new(); + utxos.insert(satpoint.outpoint.clone().into(), utxo.tx_output()?); + Ok(Self { context, utxo_selector, option, inscriptions: Vec::new(), inscriptions_to_burn: Vec::new(), - satpoint: (satpoint, utxo), + satpoint, + utxos, network: bitcoin_network.into(), destination: destination.to_bitcoin_address(bitcoin_network)?, change_address: change_address.to_bitcoin_address(bitcoin_network)?, @@ -296,7 +301,7 @@ impl Inscriber { })?; let generator = self.load_generator(generator_id).await?; - let seed_utxo = self.satpoint.0.outpoint.clone(); + let seed_utxo = self.satpoint.outpoint.clone(); let seed = InscribeSeed::new(seed_utxo.into()); @@ -344,7 +349,7 @@ impl Inscriber { ); let mut remaining_amount = sft.amount; - let mut result = self.with_burn(asset_inscription_id).await; + let mut result = self.with_burn(asset_inscription_id).await?; let amounts_len = amounts.len(); @@ -395,7 +400,7 @@ impl Inscriber { }; sft_to_merge.push(sft); - result = result.with_burn(inscription_id).await; + result = result.with_burn(inscription_id).await?; } let mut merged_sft = sft_to_merge[0].clone(); @@ -404,10 +409,11 @@ impl Inscriber { merged_sft.tick == sft.tick, "All SFTs must have the same tick to be merged" ); - ensure!( - merged_sft.attributes == sft.attributes, - "All SFTs must have the same attributes to be merged" - ); + //TODO enable the attributes check + // ensure!( + // merged_sft.attributes == sft.attributes, + // "All SFTs must have the same attributes to be merged" + // ); ensure!( merged_sft.content == sft.content, "All SFTs must have the same content to be merged" @@ -421,9 +427,13 @@ impl Inscriber { Ok(result) } - pub async fn with_burn(mut self, inscription_id: InscriptionID) -> Self { + pub async fn with_burn(mut self, inscription_id: InscriptionID) -> Result { + let inscription_obj = self.get_inscription_object(inscription_id).await?; + let outpoint = inscription_obj.location().outpoint.clone(); + let utxo_obj = self.utxo_selector.get_utxo(&outpoint).await?; self.inscriptions_to_burn.push(inscription_id); - self + self.utxos.insert(outpoint.into(), utxo_obj.tx_output()?); + Ok(self) } fn with_operation(mut self, operation: Operation) -> Self { @@ -569,12 +579,12 @@ impl Inscriber { control_blocks: &[ControlBlock], ) -> Amount { let mut reveal_tx = ctx.reveal_tx.clone(); - let reveal_input_start_index = ctx.reveal_input_start_index.unwrap_or(0); + let burn_input_start_index = ctx.burn_input_start_index.unwrap_or(0); for (current_index, txin) in reveal_tx.input.iter_mut().enumerate() { - if current_index >= reveal_input_start_index { - let reveal_script = &reveal_scripts[current_index - reveal_input_start_index]; - let control_block = &control_blocks[current_index - reveal_input_start_index]; + if current_index < burn_input_start_index { + let reveal_script = &reveal_scripts[current_index]; + let control_block = &control_blocks[current_index]; txin.witness.push( Signature::from_slice(&[0; SCHNORR_SIGNATURE_SIZE]) @@ -649,12 +659,6 @@ impl Inscriber { version: Version::TWO, }; - let mut utxos = BTreeMap::new(); - utxos.insert( - self.satpoint.0.outpoint.clone().into(), - self.satpoint.1.tx_output()?, - ); - Ok(InscribeContext { commit_tx, reveal_tx, @@ -667,10 +671,10 @@ impl Inscriber { taproot_spend_infos: Vec::new(), commit_tx_addresses: Vec::new(), - utxos, + utxos: self.utxos.clone(), reveal_scripts_to_sign: Vec::new(), control_blocks_to_sign: Vec::new(), - reveal_input_start_index: None, + burn_input_start_index: None, total_burn_postage: None, }) } @@ -680,7 +684,7 @@ impl Inscriber { // set satpoint ctx.commit_tx.input.push(TxIn { - previous_output: self.satpoint.0.outpoint.clone().into(), + previous_output: self.satpoint.outpoint.clone().into(), script_sig: ScriptBuf::new(), sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, witness: Witness::new(), @@ -713,43 +717,7 @@ impl Inscriber { } async fn build_reveal(&self, ctx: &mut InscribeContext) -> Result<()> { - // Process the logic of inscription destruction - let mut total_burn_postage = Amount::ZERO; - - for inscription_to_burn in &self.inscriptions_to_burn { - let inscription_id = *inscription_to_burn; - let satpoint = self.get_inscription_satpoint(inscription_id).await?; - let input = TxIn { - previous_output: satpoint.outpoint(), - script_sig: ScriptBuf::new(), - sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, - witness: Witness::new(), - }; - ctx.reveal_tx.input.push(input); - - let inscription_output = ctx - .utxos - .get(&satpoint.outpoint()) - .expect("inscription utxo not found"); - total_burn_postage += inscription_output.value; - } - - if !self.inscriptions_to_burn.is_empty() { - let msg = b"bitseed".to_vec(); - let msg_push_bytes = - script::PushBytesBuf::try_from(msg.clone()).expect("burn message should fit"); - - let script = ScriptBuf::new_op_return(msg_push_bytes); - let output = TxOut { - script_pubkey: script, - value: total_burn_postage, - }; - ctx.reveal_tx.output.push(output); - ctx.total_burn_postage = Some(total_burn_postage.to_btc()); - } - // Process the logic of inscription revelation - let reveal_input_start_index = ctx.reveal_tx.input.len(); for (index, ((_, control_block), reveal_script)) in ctx .commit_tx_addresses @@ -784,7 +752,45 @@ impl Inscriber { } // Set the commit input index in the context - ctx.reveal_input_start_index = Some(reveal_input_start_index); + let burn_input_start_index = ctx.reveal_tx.input.len(); + ctx.burn_input_start_index = Some(burn_input_start_index); + + // Process the logic of inscription destruction + // The ordinals protocol require the inscribe input should be first input, + // So we need to put the burn input after the reveal input. + let mut total_burn_postage = Amount::ZERO; + + for inscription_to_burn in &self.inscriptions_to_burn { + let inscription_id = *inscription_to_burn; + let satpoint = self.get_inscription_satpoint(inscription_id).await?; + let input = TxIn { + previous_output: satpoint.outpoint(), + script_sig: ScriptBuf::new(), + sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, + witness: Witness::new(), + }; + ctx.reveal_tx.input.push(input); + + let inscription_output = ctx + .utxos + .get(&satpoint.outpoint()) + .expect("inscription utxo not found"); + total_burn_postage += inscription_output.value; + } + + if !self.inscriptions_to_burn.is_empty() { + let msg = b"bitseed".to_vec(); + let msg_push_bytes = + script::PushBytesBuf::try_from(msg.clone()).expect("burn message should fit"); + + let script = ScriptBuf::new_op_return(msg_push_bytes); + let output = TxOut { + script_pubkey: script, + value: total_burn_postage, + }; + ctx.reveal_tx.output.push(output); + ctx.total_burn_postage = Some(total_burn_postage.to_btc()); + } Ok(()) } @@ -861,7 +867,7 @@ impl Inscriber { // Update the reveal transaction inputs to reference the new commit transaction outputs let new_commit_txid = ctx.commit_tx.compute_txid(); for (index, input) in ctx.reveal_tx.input.iter_mut().enumerate() { - if index >= ctx.reveal_input_start_index.unwrap() { + if index < ctx.burn_input_start_index.unwrap() { input.previous_output.txid = new_commit_txid; ctx.utxos.insert( @@ -904,7 +910,7 @@ impl Inscriber { } fn sign_reveal_tx(&self, ctx: &mut InscribeContext) -> Result<()> { - let reveal_input_start_index = ctx.reveal_input_start_index.unwrap(); + let burn_input_start_index = ctx.burn_input_start_index.unwrap(); let prevouts: Vec<_> = ctx .reveal_tx @@ -933,7 +939,7 @@ impl Inscriber { { let sighash = sighash_cache .taproot_script_spend_signature_hash( - reveal_input_start_index + index, + index, &Prevouts::All(&prevouts), TapLeafHash::from_script(reveal_script, LeafVersion::TapScript), TapSighashType::Default, @@ -944,7 +950,7 @@ impl Inscriber { let sig = secp.sign_schnorr(&sighash.into(), keypair); let witness = sighash_cache - .witness_mut(reveal_input_start_index + index) + .witness_mut(index) .expect("getting mutable witness reference should work"); witness.push( @@ -962,7 +968,7 @@ impl Inscriber { debug!("Reveal tx after reveal part sign: {:?}", signed_reveal_tx); //sign the burn inscription input - let signed_reveal_tx = if reveal_input_start_index > 0 { + let signed_reveal_tx = if burn_input_start_index < signed_reveal_tx.input.len() { let signed_reveal_tx = sign_tx(&self.context, &signed_reveal_tx, &prevouts)?; debug!( "Reveal tx after burn part sign sign: {:?}", diff --git a/crates/rooch/src/commands/bitseed/split.rs b/crates/rooch/src/commands/bitseed/split.rs deleted file mode 100644 index 6f0044c25e..0000000000 --- a/crates/rooch/src/commands/bitseed/split.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) RoochNetwork -// SPDX-License-Identifier: Apache-2.0 - -use crate::commands::bitseed::inscribe::InscribeOptions; -use crate::commands::bitseed::inscribe::Inscriber; -use clap::Parser; -use rooch_types::bitcoin::ord::InscriptionID; - -#[derive(Debug, Parser)] -pub struct SplitCommand { - #[arg(long, help = "The split SFT inscription ID.")] - sft_inscription_id: InscriptionID, - - #[arg(long, help = "The split amounts.", num_args = 1..)] - amounts: Vec, - - #[clap(flatten)] - inscribe_options: InscribeOptions, -} - -// impl SplitCommand { -// pub fn run(self, wallet: Wallet) -> SubcommandResult { -// let output = Inscriber::new(wallet, self.inscribe_options)? -// .with_split(self.sft_inscription_id, self.amounts)? -// .inscribe()?; -// Ok(Box::new(output)) -// } -// } diff --git a/crates/testsuite/features/bitseed.feature b/crates/testsuite/features/bitseed.feature index 8e49269f9d..8ed1cdb417 100644 --- a/crates/testsuite/features/bitseed.feature +++ b/crates/testsuite/features/bitseed.feature @@ -14,11 +14,7 @@ Feature: Rooch CLI bitseed tests # mint utxos Then cmd bitcoin-cli: "generatetoaddress 101 {{$.account[-1].default.bitcoin_address}}" - Then sleep: "10" # wait rooch to sync - - # publish bitseed runner - Then cmd: "move publish -p ../../examples/bitseed_runner --named-addresses rooch_examples=default --json" - Then assert: "{{$.move[-1].execution_info.status.type}} == executed" + Then sleep: "10" # wait rooch to sync # generator Then cmd: "bitseed generator --fee-rate 5000 --name random --generator ../../generator/cpp/generator.wasm" @@ -28,8 +24,8 @@ Feature: Rooch CLI bitseed tests Then cmd bitcoin-cli: "generatetoaddress 1 {{$.account[-1].default.bitcoin_address}}" Then sleep: "10" - # Sync bitseed - Then cmd: "move run --function default::bitseed_runner::run --json" + # process bitseed inscription event + Then cmd: "move run --function 0xa::inscribe_factory::process_bitseed_event --args u64:10 --json" Then assert: "{{$.move[-1].execution_info.status.type}} == executed" # Check mint generator validity @@ -46,7 +42,7 @@ Feature: Rooch CLI bitseed tests Then sleep: "10" # Sync bitseed - Then cmd: "move run --function default::bitseed_runner::run --json" + Then cmd: "move run --function 0xa::inscribe_factory::process_bitseed_event --args u64:10 --json" Then assert: "{{$.move[-1].execution_info.status.type}} == executed" # Check deploy validity @@ -54,22 +50,47 @@ Feature: Rooch CLI bitseed tests Then assert: "{{$.move[-1].vm_status}} == Executed" Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.is_valid}} == true" - # mint + # mint 1 Then cmd: "bitseed mint --fee-rate 6000 --deploy-inscription-id {{$.bitseed[-1].inscriptions[0].Id}} --user-input test" Then assert: "'{{$.bitseed[-1]}}' not_contains error" + Then cmd bitcoin-cli: "generatetoaddress 1 {{$.account[-1].default.bitcoin_address}}" + Then sleep: "5" + + # mint 2 + Then cmd: "bitseed mint --fee-rate 7000 --deploy-inscription-id {{$.bitseed[-2].inscriptions[0].Id}} --user-input test2" + Then assert: "'{{$.bitseed[-1]}}' not_contains error" + # mine a block Then cmd bitcoin-cli: "generatetoaddress 1 {{$.account[-1].default.bitcoin_address}}" Then sleep: "10" # Sync bitseed - Then cmd: "move run --function default::bitseed_runner::run --json" + Then cmd: "move run --function 0xa::inscribe_factory::process_bitseed_event --args u64:10 --json" Then assert: "{{$.move[-1].execution_info.status.type}} == executed" # Check mint bits validity Then cmd: "move view --function 0x4::ord::view_validity --args string:{{$.bitseed[-1].inscriptions[0].Id}} " Then assert: "{{$.move[-1].vm_status}} == Executed" Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.is_valid}} == true" + + Then cmd: "move view --function 0x4::ord::view_validity --args string:{{$.bitseed[-2].inscriptions[0].Id}} " + Then assert: "{{$.move[-1].vm_status}} == Executed" + Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.is_valid}} == true" + + Then cmd: "bitseed merge --fee-rate 6000 --sft-inscription-ids {{$.bitseed[-1].inscriptions[0].Id}} --sft-inscription-ids {{$.bitseed[-2].inscriptions[0].Id}}" + Then assert: "'{{$.bitseed[-1]}}' not_contains error" + + # mine a block + Then cmd bitcoin-cli: "generatetoaddress 1 {{$.account[-1].default.bitcoin_address}}" + Then sleep: "10" + + Then cmd: "move run --function 0xa::inscribe_factory::process_bitseed_event --args u64:10 --json" + Then assert: "{{$.move[-1].execution_info.status.type}} == executed" + + Then cmd: "move view --function 0x4::ord::view_validity --args string:{{$.bitseed[-1].inscriptions[0].Id}} " + Then assert: "{{$.move[-1].vm_status}} == Executed" + Then assert: "{{$.move[-1].return_values[0].decoded_value.value.vec[0].value.is_valid}} == true" # release servers Then stop the server @@ -88,14 +109,10 @@ Feature: Rooch CLI bitseed tests # mint utxos Then cmd bitcoin-cli: "generatetoaddress 101 {{$.account[-1].default.bitcoin_address}}" - Then sleep: "10" # wait ord sync and index - - # publish bitseed runner - Then cmd: "move publish -p ../../examples/bitseed_runner --named-addresses rooch_examples=default --json" - Then assert: "{{$.move[-1].execution_info.status.type}} == executed" + Then sleep: "10" # wait ord sync and index # Sync bitseed - Then cmd: "move run --function default::bitseed_runner::run --json" + Then cmd: "move run --function 0xa::inscribe_factory::process_bitseed_event --args u64:10 --json" Then assert: "{{$.move[-1].execution_info.status.type}} == executed" # deploy @@ -107,7 +124,7 @@ Feature: Rooch CLI bitseed tests Then sleep: "10" # Sync bitseed - Then cmd: "move run --function default::bitseed_runner::run --json" + Then cmd: "move run --function 0xa::inscribe_factory::process_bitseed_event --args u64:10 --json" Then assert: "{{$.move[-1].execution_info.status.type}} == executed" # Check deploy validity diff --git a/examples/bitseed_runner/Move.toml b/examples/bitseed_runner/Move.toml deleted file mode 100644 index 943fa51ecd..0000000000 --- a/examples/bitseed_runner/Move.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "bitseed_runner" -version = "0.0.1" - -[dependencies] -MoveosStdlib = { local = "../../frameworks/moveos-stdlib" } -BitcoinMove = { local = "../../frameworks/bitcoin-move" } -RoochNursery = { local = "../../frameworks/rooch-nursery" } - -[addresses] -rooch_examples = "_" -moveos_std = "0x2" -rooch_framework = "0x3" -bitcoin_move = "0x4" -rooch_nursery = "0xa" - -[dev-addresses] -rooch_examples = "0x42" diff --git a/examples/bitseed_runner/readme.md b/examples/bitseed_runner/readme.md deleted file mode 100644 index 370bf7b173..0000000000 --- a/examples/bitseed_runner/readme.md +++ /dev/null @@ -1,7 +0,0 @@ -**A full workflow example:** - -1. add fixtures/config.yml to the ROOCH_CONFIG environment variable -2. Start a local server: -``` - rooch server start -``` diff --git a/examples/bitseed_runner/sources/bitseed.move b/examples/bitseed_runner/sources/bitseed.move deleted file mode 100644 index e10adde74d..0000000000 --- a/examples/bitseed_runner/sources/bitseed.move +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) RoochNetwork -// SPDX-License-Identifier: Apache-2.0 - -module rooch_examples::bitseed_runner { - - use std::option; - use moveos_std::object::{Self, Object}; - use moveos_std::event_queue::{Self, Subscriber}; - use bitcoin_move::ord::{Self, Inscription}; - use rooch_nursery::inscribe_factory; - use rooch_nursery::bitseed; - - struct BitseedRunnerStore has key { - subscriber: Object>, - } - - fun init() { - let subscriber = event_queue::subscribe(bitseed::metaprotocol()); - let store = BitseedRunnerStore { - subscriber, - }; - let store_obj = object::new_named_object(store); - object::to_shared(store_obj); - } - - public entry fun run() { - let object_id = object::named_object_id(); - let bitseed_runner_store = object::borrow_mut_object_shared(object_id); - let runner = object::borrow_mut(bitseed_runner_store); - - let event_opt = event_queue::consume(&mut runner.subscriber); - - if (option::is_some(&event_opt)){ - let event = option::destroy_some(event_opt); - let (_metaprotocol, _sequence_number, inscription_obj_id, event_type) = ord::unpack_inscription_event(event); - - let inscription_obj = object::borrow_object(inscription_obj_id); - let inscription = object::borrow(inscription_obj); - if (event_type == ord::inscription_event_type_new()){ - inscribe_factory::process_inscription(inscription); - }else { - //TODO handle burn event. - std::debug::print(&event); - }; - }; - } -} diff --git a/examples/bitseed_runner/web/README.md b/examples/bitseed_runner/web/README.md deleted file mode 100644 index 84b4cc3988..0000000000 --- a/examples/bitseed_runner/web/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Counter Web Example - -Please visit the following path to view the Counter Web Example project: - -- `sdk/typescript/examples/bitseed_runner` diff --git a/frameworks/rooch-nursery/doc/bitseed.md b/frameworks/rooch-nursery/doc/bitseed.md index 13452dfd67..bb05a0c56a 100644 --- a/frameworks/rooch-nursery/doc/bitseed.md +++ b/frameworks/rooch-nursery/doc/bitseed.md @@ -7,15 +7,26 @@ - [Resource `Bitseed`](#0xa_bitseed_Bitseed) - [Constants](#@Constants_0) -- [Function `metaprotocol`](#0xa_bitseed_metaprotocol) +- [Function `default_metaprotocol`](#0xa_bitseed_default_metaprotocol) - [Function `new`](#0xa_bitseed_new) - [Function `is_same_type`](#0xa_bitseed_is_same_type) - [Function `is_mergeable`](#0xa_bitseed_is_mergeable) - [Function `merge`](#0xa_bitseed_merge) - [Function `is_splitable`](#0xa_bitseed_is_splitable) - [Function `split`](#0xa_bitseed_split) +- [Function `burn`](#0xa_bitseed_burn) +- [Function `metaprotocol`](#0xa_bitseed_metaprotocol) +- [Function `amount`](#0xa_bitseed_amount) +- [Function `tick`](#0xa_bitseed_tick) +- [Function `bid`](#0xa_bitseed_bid) +- [Function `content_type`](#0xa_bitseed_content_type) +- [Function `body`](#0xa_bitseed_body) +- [Function `attributes`](#0xa_bitseed_attributes) +- [Function `content_attributes_hash`](#0xa_bitseed_content_attributes_hash) - [Function `seal_metaprotocol_validity`](#0xa_bitseed_seal_metaprotocol_validity) - [Function `add_metaprotocol_attachment`](#0xa_bitseed_add_metaprotocol_attachment) +- [Function `exists_metaprotocol_attachment`](#0xa_bitseed_exists_metaprotocol_attachment) +- [Function `remove_metaprotocol_attachment`](#0xa_bitseed_remove_metaprotocol_attachment)
use 0x1::option;
@@ -108,13 +119,13 @@ Bitseed is a SFT asset type.
 
 
 
-
+
 
-## Function `metaprotocol`
+## Function `default_metaprotocol`
 
 
 
-
public fun metaprotocol(): string::String
+
public fun default_metaprotocol(): string::String
 
@@ -189,6 +200,105 @@ Split the bitseed and return the new bitseed. + + +## Function `burn` + + + +
public(friend) fun burn(bitseed_obj: object::Object<bitseed::Bitseed>): u64
+
+ + + + + +## Function `metaprotocol` + + + +
public fun metaprotocol(bitseed: &bitseed::Bitseed): string::String
+
+ + + + + +## Function `amount` + + + +
public fun amount(bitseed: &bitseed::Bitseed): u64
+
+ + + + + +## Function `tick` + + + +
public fun tick(bitseed: &bitseed::Bitseed): string::String
+
+ + + + + +## Function `bid` + + + +
public fun bid(bitseed: &bitseed::Bitseed): address
+
+ + + + + +## Function `content_type` + + + +
public fun content_type(bitseed: &bitseed::Bitseed): &option::Option<string::String>
+
+ + + + + +## Function `body` + + + +
public fun body(bitseed: &bitseed::Bitseed): &vector<u8>
+
+ + + + + +## Function `attributes` + + + +
public fun attributes(bitseed: &bitseed::Bitseed): &simple_map::SimpleMap<string::String, copyable_any::Any>
+
+ + + + + +## Function `content_attributes_hash` + + + +
public fun content_attributes_hash(bitseed: &bitseed::Bitseed): address
+
+ + + ## Function `seal_metaprotocol_validity` @@ -208,3 +318,25 @@ Split the bitseed and return the new bitseed.
public(friend) fun add_metaprotocol_attachment(inscription_id: ord::InscriptionID, attachment: object::Object<bitseed::Bitseed>)
 
+ + + + + +## Function `exists_metaprotocol_attachment` + + + +
public(friend) fun exists_metaprotocol_attachment(inscription_id: ord::InscriptionID): bool
+
+ + + + + +## Function `remove_metaprotocol_attachment` + + + +
public(friend) fun remove_metaprotocol_attachment(inscription_id: ord::InscriptionID): object::Object<bitseed::Bitseed>
+
diff --git a/frameworks/rooch-nursery/doc/genesis.md b/frameworks/rooch-nursery/doc/genesis.md index 632393918a..d3ac12a9d8 100644 --- a/frameworks/rooch-nursery/doc/genesis.md +++ b/frameworks/rooch-nursery/doc/genesis.md @@ -10,6 +10,7 @@
use 0xa::ethereum;
+use 0xa::inscribe_factory;
 use 0xa::tick_info;
 
diff --git a/frameworks/rooch-nursery/doc/inscribe_factory.md b/frameworks/rooch-nursery/doc/inscribe_factory.md index dce0a7d107..8e6dec718f 100644 --- a/frameworks/rooch-nursery/doc/inscribe_factory.md +++ b/frameworks/rooch-nursery/doc/inscribe_factory.md @@ -6,13 +6,16 @@ Bitseed inscribe inscription factory +- [Struct `MergeState`](#0xa_inscribe_factory_MergeState) +- [Resource `BitseedEventStore`](#0xa_inscribe_factory_BitseedEventStore) - [Struct `InscribeGenerateArgs`](#0xa_inscribe_factory_InscribeGenerateArgs) - [Struct `InscribeGenerateOutput`](#0xa_inscribe_factory_InscribeGenerateOutput) - [Constants](#@Constants_0) +- [Function `genesis_init`](#0xa_inscribe_factory_genesis_init) - [Function `bitseed_deploy_key`](#0xa_inscribe_factory_bitseed_deploy_key) - [Function `bitseed_mint_key`](#0xa_inscribe_factory_bitseed_mint_key) - [Function `inscribe_verify`](#0xa_inscribe_factory_inscribe_verify) -- [Function `process_inscription`](#0xa_inscribe_factory_process_inscription) +- [Function `process_bitseed_event`](#0xa_inscribe_factory_process_bitseed_event)
use 0x1::bcs;
@@ -21,6 +24,7 @@ Bitseed inscribe inscription factory
 use 0x1::vector;
 use 0x2::address;
 use 0x2::cbor;
+use 0x2::event_queue;
 use 0x2::hash;
 use 0x2::hex;
 use 0x2::object;
@@ -37,6 +41,28 @@ Bitseed inscribe inscription factory
 
 
 
+
+
+## Struct `MergeState`
+
+
+
+
struct MergeState has store
+
+ + + + + +## Resource `BitseedEventStore` + + + +
struct BitseedEventStore has key
+
+ + + ## Struct `InscribeGenerateArgs` @@ -92,6 +118,17 @@ Bitseed inscribe inscription factory + + +## Function `genesis_init` + + + +
public(friend) fun genesis_init()
+
+ + + ## Function `bitseed_deploy_key` @@ -125,11 +162,11 @@ Bitseed inscribe inscription factory - + -## Function `process_inscription` +## Function `process_bitseed_event` -
public fun process_inscription(inscription: &ord::Inscription)
+
public entry fun process_bitseed_event(batch_size: u64)
 
diff --git a/frameworks/rooch-nursery/doc/tick_info.md b/frameworks/rooch-nursery/doc/tick_info.md index e1d716ae5c..cf93187743 100644 --- a/frameworks/rooch-nursery/doc/tick_info.md +++ b/frameworks/rooch-nursery/doc/tick_info.md @@ -13,6 +13,7 @@ - [Function `borrow_tick_info`](#0xa_tick_info_borrow_tick_info) - [Function `deploy_tick`](#0xa_tick_info_deploy_tick) - [Function `mint`](#0xa_tick_info_mint) +- [Function `burn`](#0xa_tick_info_burn) - [Function `mint_on_bitcoin`](#0xa_tick_info_mint_on_bitcoin) - [Function `metaprotocol`](#0xa_tick_info_metaprotocol) - [Function `tick`](#0xa_tick_info_tick) @@ -178,6 +179,17 @@ Check if the tick is deployed. + + +## Function `burn` + + + +
public fun burn(bitseed_obj: object::Object<bitseed::Bitseed>)
+
+ + + ## Function `mint_on_bitcoin` diff --git a/frameworks/rooch-nursery/sources/bitseed.move b/frameworks/rooch-nursery/sources/bitseed.move index 42dec83c0b..b570f0464e 100644 --- a/frameworks/rooch-nursery/sources/bitseed.move +++ b/frameworks/rooch-nursery/sources/bitseed.move @@ -49,7 +49,7 @@ module rooch_nursery::bitseed { content_attributes_hash: address, } - public fun metaprotocol(): String{ + public fun default_metaprotocol(): String{ string::utf8(METAPROTOCOL) } @@ -133,6 +133,49 @@ module rooch_nursery::bitseed { split_bitseed } + public(friend) fun burn(bitseed_obj: Object) : u64{ + let bitseed = object::remove(bitseed_obj); + let amount = bitseed.amount; + drop(bitseed); + amount + } + + // ==================== Get functions ==================== // + + public fun metaprotocol(bitseed: &Bitseed): String { + bitseed.metaprotocol + } + + public fun amount(bitseed: &Bitseed): u64 { + bitseed.amount + } + + public fun tick(bitseed: &Bitseed): String { + bitseed.tick + } + + public fun bid(bitseed: &Bitseed): address { + bitseed.bid + } + + public fun content_type(bitseed: &Bitseed): &Option { + &bitseed.content_type + } + + public fun body(bitseed: &Bitseed): &vector { + &bitseed.body + } + + public fun attributes(bitseed: &Bitseed): &SimpleMap { + &bitseed.attributes + } + + public fun content_attributes_hash(bitseed: &Bitseed): address { + bitseed.content_attributes_hash + } + + // ========= Metaprotocol delegate function ========= // + public(friend) fun seal_metaprotocol_validity(inscription_id: InscriptionID, is_valid: bool, invalid_reason: Option){ ord::seal_metaprotocol_validity(inscription_id, is_valid, invalid_reason) } @@ -141,6 +184,14 @@ module rooch_nursery::bitseed { ord::add_metaprotocol_attachment(inscription_id, attachment) } + public(friend) fun exists_metaprotocol_attachment(inscription_id: InscriptionID): bool{ + ord::exists_metaprotocol_attachment(inscription_id) + } + + public(friend) fun remove_metaprotocol_attachment(inscription_id: InscriptionID): Object{ + ord::remove_metaprotocol_attachment(inscription_id) + } + fun drop(bitseed: Bitseed) { let Bitseed { metaprotocol:_, diff --git a/frameworks/rooch-nursery/sources/genesis.move b/frameworks/rooch-nursery/sources/genesis.move index 72f2fbacc3..35ec9e578a 100644 --- a/frameworks/rooch-nursery/sources/genesis.move +++ b/frameworks/rooch-nursery/sources/genesis.move @@ -4,6 +4,7 @@ module rooch_nursery::genesis { use rooch_nursery::ethereum; use rooch_nursery::tick_info; + use rooch_nursery::inscribe_factory; const ErrorInvalidChainId: u64 = 1; @@ -13,6 +14,7 @@ module rooch_nursery::genesis { fun init(genesis_account: &signer){ ethereum::genesis_init(genesis_account); tick_info::genesis_init(); + inscribe_factory::genesis_init(); } #[test_only] diff --git a/frameworks/rooch-nursery/sources/inscribe_factory.move b/frameworks/rooch-nursery/sources/inscribe_factory.move index f7ffe41764..aa68ef886c 100644 --- a/frameworks/rooch-nursery/sources/inscribe_factory.move +++ b/frameworks/rooch-nursery/sources/inscribe_factory.move @@ -9,24 +9,51 @@ module rooch_nursery::inscribe_factory { use moveos_std::address; use moveos_std::hash; use moveos_std::hex; - use moveos_std::object::Object; + use moveos_std::object::{Self, Object}; use moveos_std::string_utils; use moveos_std::simple_map::{Self, SimpleMap}; - use rooch_nursery::wasm; + use moveos_std::result::{Self, Result, err_str, ok, is_err, as_err}; use moveos_std::cbor; + use moveos_std::event_queue::{Self, Subscriber}; use bitcoin_move::types; - use bitcoin_move::ord::{Self, Inscription}; + use bitcoin_move::ord::{Self, Inscription, InscriptionID}; use bitcoin_move::bitcoin; use rooch_nursery::bitseed::{Self, Bitseed}; use rooch_nursery::tick_info; - use moveos_std::result::{Self, Result, err_str, ok, is_err, as_err}; + use rooch_nursery::wasm; + + friend rooch_nursery::genesis; + const BIT_SEED_DEPLOY: vector = b"bitseed_deploy"; const BIT_SEED_MINT: vector = b"bitseed_mint"; const BIT_SEED_GENERATOR_TICK: vector = b"generator"; + struct MergeState has store { + inscription_id: InscriptionID, + merge_amount: u64, + txid: address, + burned_inscriptions: vector, + bitseeds: vector>, + } + + struct BitseedEventStore has key { + subscriber: Object>, + merge_state: Option, + } + + public(friend) fun genesis_init() { + let subscriber = event_queue::subscribe(bitseed::default_metaprotocol()); + let store = BitseedEventStore { + subscriber, + merge_state: option::none(), + }; + let store_obj = object::new_named_object(store); + object::to_shared(store_obj); + } + public fun bitseed_deploy_key(): vector { BIT_SEED_DEPLOY } @@ -37,7 +64,7 @@ module rooch_nursery::inscribe_factory { fun is_bitseed(inscription: &Inscription) : bool { let metaprotocol = ord::metaprotocol(inscription); - option::is_some(&metaprotocol) && option::borrow(&metaprotocol) == &bitseed::metaprotocol() + option::is_some(&metaprotocol) && option::borrow(&metaprotocol) == &bitseed::default_metaprotocol() } fun get_SFT_op(metadata: &SimpleMap>) : Option { @@ -259,7 +286,7 @@ module rooch_nursery::inscribe_factory { let deploy_args = get_SFT_bytes_attribute(&attributes, b"deploy_args"); - tick_info::deploy_tick(bitseed::metaprotocol(), tick, inscription_id_option, factory_option, max, repeat, has_user_input, deploy_args); + tick_info::deploy_tick(bitseed::default_metaprotocol(), tick, inscription_id_option, factory_option, max, repeat, has_user_input, deploy_args); (true, option::none()) } @@ -274,11 +301,11 @@ module rooch_nursery::inscribe_factory { let attributes = get_SFT_attributes(metadata); let amount = get_SFT_amount(metadata); - if (!tick_info::is_deployed(bitseed::metaprotocol(), tick)) { + if (!tick_info::is_deployed(bitseed::default_metaprotocol(), tick)) { return err_str(b"the tick is not deployed") }; - let tick_info = tick_info::borrow_tick_info(bitseed::metaprotocol(), tick); + let tick_info = tick_info::borrow_tick_info(bitseed::default_metaprotocol(), tick); let has_user_input = tick_info::has_user_input(tick_info); let deploy_args = option::destroy_with_default(tick_info::deploy_args(tick_info), vector::empty()); @@ -317,11 +344,29 @@ module rooch_nursery::inscribe_factory { return result::err(option::destroy_with_default(reason, utf8(b"inscribe verify fail"))) }; }; - let bitseed_result = tick_info::mint_on_bitcoin(bitseed::metaprotocol(), tick, amount); + let bitseed_result = tick_info::mint_on_bitcoin(bitseed::default_metaprotocol(), tick, amount); bitseed_result } + fun merge_bitseed(bitseeds: vector>): Result, vector>> { + if (vector::length(&bitseeds) == 0){ + return result::err(bitseeds) + }; + let bitseed = vector::pop_back(&mut bitseeds); + while(vector::length(&bitseeds) > 0){ + let bitseed_to_merge = vector::pop_back(&mut bitseeds); + if(!bitseed::is_mergeable(&bitseed, &bitseed_to_merge)){ + vector::push_back(&mut bitseeds, bitseed_to_merge); + vector::push_back(&mut bitseeds, bitseed); + return result::err(bitseeds) + }; + bitseed::merge(&mut bitseed, bitseed_to_merge); + }; + vector::destroy_empty(bitseeds); + ok(bitseed) + } + public fun inscribe_verify(wasm_bytes: vector, deploy_args: vector, seed: vector, user_input: String, metadata: &SimpleMap>, content_type: Option, body: vector): (bool, Option) { @@ -482,12 +527,58 @@ module rooch_nursery::inscribe_factory { } // ==== Process Bitseed Entry ==== // - public fun process_inscription(inscription: &Inscription) { - let txid = ord::txid(inscription); - let index = ord::index(inscription); - let inscription_id = ord::new_inscription_id(txid, index); - if (is_bitseed(inscription)) { + public entry fun process_bitseed_event(batch_size: u64) { + let store_obj_id = object::named_object_id(); + let event_store_obj = object::borrow_mut_object_shared(store_obj_id); + let event_store = object::borrow_mut(event_store_obj); + let count = 0; + while (count < batch_size) { + let event_opt = event_queue::consume(&mut event_store.subscriber); + + if (option::is_some(&event_opt)){ + let event = option::destroy_some(event_opt); + let (_metaprotocol, _sequence_number, inscription_obj_id, event_type) = ord::unpack_inscription_event(event); + + let inscription_obj = object::borrow_object(inscription_obj_id); + let inscription = object::borrow(inscription_obj); + if (event_type == ord::inscription_event_type_new()){ + if(option::is_some(&event_store.merge_state)){ + let merge_state = option::extract(&mut event_store.merge_state); + finish_merge(merge_state); + }; + process_inscription(inscription, event_store); + }else { + let inscription_id = *ord::id(inscription); + let location = ord::location(inscription); + let outpoint = ord::satpoint_outpoint(location); + let txid = types::outpoint_txid(outpoint); + if(option::is_some(&event_store.merge_state)) { + let merge_state = option::extract(&mut event_store.merge_state); + if(txid == merge_state.txid){ + vector::push_back(&mut merge_state.burned_inscriptions, inscription_id); + if(bitseed::exists_metaprotocol_attachment(inscription_id)){ + let bitseed_obj = bitseed::remove_metaprotocol_attachment(inscription_id); + vector::push_back(&mut merge_state.bitseeds, bitseed_obj); + }; + }; + if (can_finish_merge(&merge_state)) { + finish_merge(merge_state); + }else{ + option::fill(&mut event_store.merge_state, merge_state); + }; + }; + }; + }else{ + break + }; + count = count + 1; + }; + } + + fun process_inscription(inscription: &Inscription, event_store: &mut BitseedEventStore) { + if (is_bitseed(inscription)) { + let inscription_id = *ord::id(inscription); let metadata_bytes = ord::metadata(inscription); let metadata = cbor::to_map(metadata_bytes); @@ -529,15 +620,68 @@ module rooch_nursery::inscribe_factory { } else if (option::borrow(&op) == &string::utf8(b"split")) { bitseed::seal_metaprotocol_validity(inscription_id, true, option::none()); } else if (option::borrow(&op) == &string::utf8(b"merge")) { - bitseed::seal_metaprotocol_validity(inscription_id, true, option::none()); + let location = ord::location(inscription); + let outpoint = ord::satpoint_outpoint(location); + let txid = types::outpoint_txid(outpoint); + let merge_state = MergeState{ + inscription_id, + merge_amount: get_SFT_amount(&metadata), + txid: txid, + burned_inscriptions: vector::empty(), + bitseeds: vector::empty(), + }; + option::fill(&mut event_store.merge_state, merge_state); } else { bitseed::seal_metaprotocol_validity(inscription_id, false, option::some(string::utf8(b"invalid op"))); } } else { bitseed::seal_metaprotocol_validity(inscription_id, false, option::some(string::utf8(b"op not found"))); }; + }; + } + + fun can_finish_merge(merge_state: &MergeState) : bool { + let len = vector::length(&merge_state.bitseeds); + let index = 0; + let total_amount = 0; + while(index < len){ + let bitseed_obj = vector::borrow(&merge_state.bitseeds, index); + total_amount = total_amount + bitseed::amount(object::borrow(bitseed_obj)); + index = index + 1; + }; + total_amount >= merge_state.merge_amount + } - } + fun finish_merge(merge_state: MergeState){ + let MergeState{inscription_id, merge_amount, txid:_, burned_inscriptions:_, bitseeds} = merge_state; + + let merge_result = merge_bitseed(bitseeds); + let (o,e) = result::unpack(merge_result); + if(option::is_some(&o)){ + option::destroy_none(e); + let bitseed_obj = option::destroy_some(o); + let real_amount = bitseed::amount(object::borrow(&bitseed_obj)); + if (merge_amount == real_amount) { + bitseed::add_metaprotocol_attachment(inscription_id, bitseed_obj); + bitseed::seal_metaprotocol_validity(inscription_id, true, option::none()); + }else if (merge_amount < real_amount) { + let split_amount = real_amount - merge_amount; + let redundant_bitseed = bitseed::split(&mut bitseed_obj, split_amount); + tick_info::burn(redundant_bitseed); + bitseed::add_metaprotocol_attachment(inscription_id, bitseed_obj); + bitseed::seal_metaprotocol_validity(inscription_id, true, option::none()); + }else{ + tick_info::burn(bitseed_obj); + bitseed::seal_metaprotocol_validity(inscription_id, false, option::some(string::utf8(b"merge amount not match"))); + }; + }else{ + option::destroy_none(o); + let bitseeds = option::destroy_some(e); + vector::for_each(bitseeds, |bitseed_obj|{ + tick_info::burn(bitseed_obj); + }); + bitseed::seal_metaprotocol_validity(inscription_id, false, option::some(string::utf8(b"merge fail"))); + }; } #[test_only] @@ -545,7 +689,7 @@ module rooch_nursery::inscribe_factory { #[test(genesis_account=@0x4)] fun test_is_valid_bitseed_deploy_ok(genesis_account: &signer){ - let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::metaprotocol()); + let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::default_metaprotocol()); bitseed::seal_metaprotocol_validity(test_inscription_id, true, option::none()); let metadata_bytes = x"a4626f70666465706c6f79647469636b646d6f766566616d6f756e74016a61747472696275746573a16967656e657261746f72784f2f696e736372697074696f6e2f373764666332666535393834313962303036343163323936313831613936636631363934333639376635373334383062303233623737636365383261646132316930"; @@ -649,7 +793,7 @@ module rooch_nursery::inscribe_factory { #[test(genesis_account=@0x4)] fun test_is_valid_bitseed_deploy_fail_for_inscription_metaprotocol_validity_not_exists(genesis_account: &signer){ - let (_test_address, _test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::metaprotocol()); + let (_test_address, _test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::default_metaprotocol()); let metadata_bytes = x"a4626f70666465706c6f79647469636b646d6f766566616d6f756e74016a61747472696275746573a16967656e657261746f72784f2f696e736372697074696f6e2f373764666332666535393834313962303036343163323936313831613936636631363934333639376635373334383062303233623737636365383261646132316930"; let metadata = cbor::to_map(metadata_bytes); @@ -676,7 +820,7 @@ module rooch_nursery::inscribe_factory { #[test(genesis_account=@0x4)] fun test_is_valid_bitseed_deploy_fail_for_inscription_metaprotocol_validity_not_valid(genesis_account: &signer){ - let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::metaprotocol()); + let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::default_metaprotocol()); bitseed::seal_metaprotocol_validity(test_inscription_id, false, option::none()); let metadata_bytes = x"a4626f70666465706c6f79647469636b646d6f766566616d6f756e74016a61747472696275746573a16967656e657261746f72784f2f696e736372697074696f6e2f373764666332666535393834313962303036343163323936313831613936636631363934333639376635373334383062303233623737636365383261646132316930"; @@ -692,7 +836,7 @@ module rooch_nursery::inscribe_factory { fun test_deploy_tick_ok(genesis_account: &signer){ tick_info::init_for_testing(); - let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::metaprotocol()); + let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::default_metaprotocol()); bitseed::seal_metaprotocol_validity(test_inscription_id, true, option::none()); let metadata_bytes = x"a4626f70666465706c6f79647469636b646d6f766566616d6f756e74016a61747472696275746573a16967656e657261746f72784f2f696e736372697074696f6e2f373764666332666535393834313962303036343163323936313831613936636631363934333639376635373334383062303233623737636365383261646132316930"; @@ -703,9 +847,9 @@ module rooch_nursery::inscribe_factory { assert!(ok, 1); assert!(option::is_none(&reason), 1); - assert!(tick_info::is_deployed(bitseed::metaprotocol(), string::utf8(b"move")), 2); + assert!(tick_info::is_deployed(bitseed::default_metaprotocol(), string::utf8(b"move")), 2); - let tick_info = tick_info::borrow_tick_info(bitseed::metaprotocol(), string::utf8(b"move")); + let tick_info = tick_info::borrow_tick_info(bitseed::default_metaprotocol(), string::utf8(b"move")); // check tick let tick = tick_info::tick(tick_info); @@ -747,7 +891,7 @@ module rooch_nursery::inscribe_factory { fun test_is_valid_bitseed_mint_fail_with_tick_not_deploy(genesis_account: &signer){ tick_info::init_for_testing(); - let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::metaprotocol()); + let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::default_metaprotocol()); bitseed::seal_metaprotocol_validity(test_inscription_id, true, option::none()); let metadata_bytes = x"a4626f70666465706c6f79647469636b646d6f766566616d6f756e74016a61747472696275746573a16967656e657261746f72784f2f696e736372697074696f6e2f373764666332666535393834313962303036343163323936313831613936636631363934333639376635373334383062303233623737636365383261646132316930"; @@ -766,7 +910,7 @@ module rooch_nursery::inscribe_factory { fun test_is_valid_bitseed_mint_fail_with_maximum_supply_exceeded(genesis_account: &signer){ tick_info::init_for_testing(); - let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::metaprotocol()); + let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::default_metaprotocol()); bitseed::seal_metaprotocol_validity(test_inscription_id, true, option::none()); let metadata_bytes = x"a4626f70666465706c6f79647469636b646d6f766566616d6f756e74016a61747472696275746573a16967656e657261746f72784f2f696e736372697074696f6e2f373764666332666535393834313962303036343163323936313831613936636631363934333639376635373334383062303233623737636365383261646132316930"; @@ -800,7 +944,7 @@ module rooch_nursery::inscribe_factory { fun test_is_valid_bitseed_mint_fail_with_user_input_is_required(genesis_account: &signer){ tick_info::init_for_testing(); - let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::metaprotocol()); + let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::default_metaprotocol()); bitseed::seal_metaprotocol_validity(test_inscription_id, true, option::none()); let metadata_bytes = x"a4626f70666465706c6f79647469636b646d6f766566616d6f756e741927106a61747472696275746573a466726570656174056967656e657261746f72784f2f696e736372697074696f6e2f3737646663326665353938343139623030363431633239363138316139366366313639343336393766353733343830623032336237376363653832616461323169306e6861735f757365725f696e707574f56b6465706c6f795f617267738178377b22686569676874223a7b2274797065223a2272616e6765222c2264617461223a7b226d696e223a312c226d6178223a313030307d7d7d"; @@ -833,7 +977,7 @@ module rooch_nursery::inscribe_factory { features::init_and_enable_all_features_for_test(); tick_info::init_for_testing(); - let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::metaprotocol()); + let (_test_address, test_inscription_id) = ord::setup_inscription_for_test(genesis_account, bitseed::default_metaprotocol()); bitseed::seal_metaprotocol_validity(test_inscription_id, true, option::none()); let metadata_bytes = x"a4626f70666465706c6f79647469636b646d6f766566616d6f756e741927106a61747472696275746573a466726570656174056967656e657261746f72784f2f696e736372697074696f6e2f3737646663326665353938343139623030363431633239363138316139366366313639343336393766353733343830623032336237376363653832616461323169306e6861735f757365725f696e707574f56b6465706c6f795f617267738178377b22686569676874223a7b2274797065223a2272616e6765222c2264617461223a7b226d696e223a312c226d6178223a313030307d7d7d"; diff --git a/frameworks/rooch-nursery/sources/tick_info.move b/frameworks/rooch-nursery/sources/tick_info.move index f70176a237..dc285d7307 100644 --- a/frameworks/rooch-nursery/sources/tick_info.move +++ b/frameworks/rooch-nursery/sources/tick_info.move @@ -63,9 +63,9 @@ module rooch_nursery::tick_info { //u64max let max = 18_446_744_073_709_551_615u64; - deploy_tick(bitseed::metaprotocol(), tick, option::none(), option::none(), max, repeat, has_user_input, option::none()); + deploy_tick(bitseed::default_metaprotocol(), tick, option::none(), option::none(), max, repeat, has_user_input, option::none()); let module_signer = moveos_std::signer::module_signer(); - ord::register_metaprotocol_via_system(&module_signer, bitseed::metaprotocol()); + ord::register_metaprotocol_via_system(&module_signer, bitseed::default_metaprotocol()); } /// Check if the tick is deployed. @@ -162,6 +162,15 @@ module rooch_nursery::tick_info { bitseed } + public fun burn(bitseed_obj: Object){ + let bitseed = object::borrow(&bitseed_obj); + let metaprotocol = bitseed::metaprotocol(bitseed); + let tick = bitseed::tick(bitseed); + let tick_info = borrow_mut_tick_info(metaprotocol, tick); + let amount = bitseed::burn(bitseed_obj); + tick_info.supply = tick_info.supply - amount; + } + public(friend) fun mint_on_bitcoin(metaprotocol: String, tick: String, amount: u64) : Result,String>{ let tick = string_utils::to_lower_case(&tick); let tick_info = borrow_mut_tick_info(metaprotocol, tick);