Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bitcoin] Brc20 utxo trace #1271

Merged
merged 4 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions crates/rooch-framework-tests/src/tests/brc20_test.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use crate::binding_test;
use bitcoin::consensus::Decodable;
use hex::FromHex;
use rooch_types::bitcoin::brc20::Op;
use tracing::debug;

fn decode_ops(btx_tx_hex: &str) -> Vec<Op> {
fn decode_tx(btx_tx_hex: &str) {
let btc_tx_bytes = Vec::from_hex(btx_tx_hex).unwrap();
let btc_tx: bitcoin::Transaction =
Decodable::consensus_decode(&mut btc_tx_bytes.as_slice()).unwrap();
Expand All @@ -27,12 +25,12 @@ fn decode_ops(btx_tx_hex: &str) -> Vec<Op> {
for (i, inscription) in inscriptions.iter().enumerate() {
debug!("{}. inscription: {:?}", i, inscription);
}
let binding_test = binding_test::RustBindingTest::new().unwrap();
let brc20_module = binding_test.as_module_bundle::<rooch_types::bitcoin::brc20::BRC20Module>();
let move_btc_tx: rooch_types::bitcoin::types::Transaction = btc_tx.into();
let ops_from_move = brc20_module.from_transaction(&move_btc_tx).unwrap();
debug!("ops_from_move: {:?}", ops_from_move);
ops_from_move
//let binding_test = binding_test::RustBindingTest::new().unwrap();
//let brc20_module = binding_test.as_module_bundle::<rooch_types::bitcoin::brc20::BRC20Module>();
//let move_btc_tx: rooch_types::bitcoin::types::Transaction = btc_tx.into();
//let ops_from_move = brc20_module.get_tick_info(&move_btc_tx).unwrap();
//debug!("ops_from_move: {:?}", ops_from_move);
//ops_from_move
}

#[test]
Expand All @@ -49,7 +47,7 @@ fn test_from_transaction() {
// "amt": "1000"
// }
let btc_tx_hex = "0100000000010168fc0bd080cf62a7bb04a5e3fc1140df4dd34c244edf23e9027d3966f086f25f0000000000fdffffff01102700000000000022512037679ea62eab55ebfd442c53c4ad46b6b75e45d8a8fa9cb31a87d0df268b029a03409baed731180a79d18ac9f54d2ab448e3c1c78df128ba71f471cf75ed5be4db6431d824a1c254bede0d7482ad05a53468b3c737e9f6b4bfe90ba0c064166dd3188d205f308d3670e9d71da3c2d913a44fa0f6daa57f07263b25a23dd3124832753263ac0063036f7264010118746578742f706c61696e3b636861727365743d7574662d3800477b200a20202270223a20226272632d3230222c0a2020226f70223a20226d696e74222c0a2020227469636b223a20226f726469222c0a202022616d74223a202231303030220a7d6821c15f308d3670e9d71da3c2d913a44fa0f6daa57f07263b25a23dd312483275326300000000";
let _ops_from_move = decode_ops(btc_tx_hex);
let _ops_from_move = decode_tx(btc_tx_hex);

//inscribe transfer
//https://ordinals.com/inscription/885441055c7bb5d1c54863e33f5c3a06e5a14cc4749cb61a9b3ff1dbe52a5bbbi0
Expand All @@ -63,12 +61,12 @@ fn test_from_transaction() {
// "fee": "1337"
// }
let btc_tx_hex = "01000000000101eb9aadb9ece84438be35112b4681d1001206a504fd28b17a620fc719429eb1230000000000fdffffff01102700000000000022512037679ea62eab55ebfd442c53c4ad46b6b75e45d8a8fa9cb31a87d0df268b029a034091a14e1b53acfec21ea0d3ea0ce6562435e50a20255c73a7234b44c3d6914fc1fc772b481349d20abba86de21420ebb511db9ba12dbaba24cd727677305434edd02052885ab09f6495885e6a1d6cb51e691e3469f1c2e86d8d2442fb44c22253b637ac0063036f7264010118746578742f706c61696e3b636861727365743d7574662d38004c897b200a20202270223a20226272632d3230222c0a2020226f70223a20227472616e73666572222c0a2020227469636b223a20226f726469222c0a202022616d74223a2022313030222c0a202022746f223a20223141317a5031655035514765666932444d505466544c35534c6d7637446976664e61222c0a202022666565223a202231333337220a7d6821c152885ab09f6495885e6a1d6cb51e691e3469f1c2e86d8d2442fb44c22253b63700000000";
let _ops_from_move = decode_ops(btc_tx_hex);
let _ops_from_move = decode_tx(btc_tx_hex);

//transfer
//https://ordinals.com/inscription/885441055c7bb5d1c54863e33f5c3a06e5a14cc4749cb61a9b3ff1dbe52a5bbbi0
//https://mempool.space/api/tx/628f019c4e3c30ccc0fd9aae872cb3720294a255127292bf61c38fbee39462fe/hex

let btc_tx_hex = "02000000000102bb5b2ae5dbf13f9b1ab69c74c44ca1e5063a5c3fe36348c5d1b57b5c054154880000000000ffffffff8eca9f7d2e369e650f439153f503e81dd9960f1030bfb54f9043884a4c63c8bc11000000171600141c6e0ecb1a039c8df94a664ddf130f6e3be90ba5ffffffff0210270000000000001976a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac073d0f000000000017a9142b5fd9fed263646d296cb196bc07747b4c41fdc787014091e2afbe0bf24467275bf90b2fa281e105c6cd0344cd1f0846a89a5369246634d12476f579271a7cadbf918f73de306486f70cc2368274740ea7779a9de4e6c402473044022024e761eeaf29864b4b9bef52f457d2c0302fa5c6b4003c67681cdb006d118404022023aef89d49e6700bca374d2059509cdcacba213c0b8b77a635095c79a63a124f012103b06845003ff20c9e8a1c529003fb32edb1a9d8894e7f2cd37a192c0cbd76fb8f00000000";
let _ops_from_move = decode_ops(btc_tx_hex);
let _ops_from_move = decode_tx(btc_tx_hex);
}
6 changes: 4 additions & 2 deletions crates/rooch-framework-tests/src/tests/ord_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
use crate::binding_test;
use bitcoin::consensus::Decodable;
use hex::FromHex;
use rooch_types::bitcoin::ord::InscriptionRecord;
use tracing::debug;

fn decode_inscription(btx_tx_hex: &str) {
Expand Down Expand Up @@ -36,7 +35,10 @@ fn decode_inscription(btx_tx_hex: &str) {
.enumerate()
{
debug!("{}. inscription: {:?}", i, inscription);
assert_eq!(InscriptionRecord::from(inscription), inscription_from_move);
assert_eq!(
inscription.body.unwrap_or_default(),
inscription_from_move.body
);
}
}

Expand Down
64 changes: 46 additions & 18 deletions crates/rooch-types/src/bitcoin/brc20.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use super::types::Transaction;
use crate::addresses::BITCOIN_MOVE_ADDRESS;
use anyhow::Result;
use move_core_types::{
account_address::AccountAddress, ident_str, identifier::IdentStr, value::MoveValue,
account_address::AccountAddress, ident_str, identifier::IdentStr, u256::U256, value::MoveValue,
};
use moveos_types::{
module_binding::{ModuleBinding, MoveFunctionCaller},
move_std::string::MoveString,
move_std::{option::MoveOption, string::MoveString},
moveos_std::{
object::{self, ObjectID},
simple_map::SimpleMap,
Expand All @@ -21,11 +20,17 @@ use serde::{Deserialize, Serialize};

pub const MODULE_NAME: &IdentStr = ident_str!("brc20");

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BRC20CoinInfo {
pub tick: MoveString,
pub max: U256,
pub lim: U256,
pub dec: u64,
pub supply: U256,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BRC20Store {
/// The latest inscription index has been processed
pub next_inscription_index: u64,
/// The coins id
pub coins: ObjectID,
}

Expand All @@ -43,10 +48,7 @@ impl MoveStructType for BRC20Store {

impl MoveStructState for BRC20Store {
fn struct_layout() -> move_core_types::value::MoveStructLayout {
move_core_types::value::MoveStructLayout::new(vec![
u64::type_layout(),
ObjectID::type_layout(),
])
move_core_types::value::MoveStructLayout::new(vec![ObjectID::type_layout()])
}
}

Expand Down Expand Up @@ -75,25 +77,51 @@ pub struct BRC20Module<'a> {
}

impl<'a> BRC20Module<'a> {
pub const FROM_TRANSACTION_FUNCTION_NAME: &'static IdentStr =
ident_str!("from_transaction_bytes");
pub const GET_TICK_INFO_FUNCTION_NAME: &'static IdentStr = ident_str!("get_tick_info");
pub const GET_BALANCE_FUNCTION_NAME: &'static IdentStr = ident_str!("get_balance");

pub fn get_tick_info(&self, tick: String) -> Result<Option<BRC20CoinInfo>> {
let call = Self::create_function_call(
Self::GET_TICK_INFO_FUNCTION_NAME,
vec![],
vec![
MoveValue::Address(BRC20Store::object_id().into()),
MoveValue::vector_u8(MoveString::from(tick).to_bytes()),
],
);
let ctx = TxContext::new_readonly_ctx(AccountAddress::ONE);
let result = self
.caller
.call_function(&ctx, call)?
.into_result()
.map(|mut values| {
let value = values.pop().expect("should have one return value");
bcs::from_bytes::<MoveOption<BRC20CoinInfo>>(&value.value)
.expect("should be a valid MoveOption<BRC20CoinInfo>")
})?;
Ok(result.into())
}

pub fn from_transaction(&self, tx: &Transaction) -> Result<Vec<Op>> {
pub fn get_balance(&self, tick: String, addr: AccountAddress) -> Result<U256> {
let call = Self::create_function_call(
Self::FROM_TRANSACTION_FUNCTION_NAME,
Self::GET_BALANCE_FUNCTION_NAME,
vec![],
vec![MoveValue::vector_u8(tx.to_bytes())],
vec![
MoveValue::Address(BRC20Store::object_id().into()),
MoveValue::vector_u8(MoveString::from(tick).to_bytes()),
MoveValue::Address(addr),
],
);
let ctx = TxContext::new_readonly_ctx(AccountAddress::ONE);
let ops = self
let result = self
.caller
.call_function(&ctx, call)?
.into_result()
.map(|mut values| {
let value = values.pop().expect("should have one return value");
bcs::from_bytes::<Vec<Op>>(&value.value).expect("should be a valid Vec<Op>")
bcs::from_bytes::<U256>(&value.value).expect("should be a valid u256")
})?;
Ok(ops)
Ok(result)
}
}

Expand Down
13 changes: 9 additions & 4 deletions crates/rooch-types/src/bitcoin/ord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use moveos_types::{
move_std::{option::MoveOption, string::MoveString},
moveos_std::{
object::{self, ObjectID},
simple_map::SimpleMap,
tx_context::TxContext,
},
state::{MoveState, MoveStructState, MoveStructType},
Expand Down Expand Up @@ -51,13 +52,15 @@ impl MoveStructState for InscriptionID {
pub struct Inscription {
pub txid: AccountAddress,
pub index: u32,
pub input: u32,
pub body: Vec<u8>,
pub content_encoding: MoveOption<MoveString>,
pub content_type: MoveOption<MoveString>,
pub metadata: Vec<u8>,
pub metaprotocol: MoveOption<MoveString>,
pub parent: MoveOption<ObjectID>,
pub pointer: MoveOption<u64>,
pub json_body: SimpleMap<MoveString, MoveString>,
}

impl MoveStructType for Inscription {
Expand All @@ -71,13 +74,15 @@ impl MoveStructState for Inscription {
move_core_types::value::MoveStructLayout::new(vec![
AccountAddress::type_layout(),
u32::type_layout(),
u32::type_layout(),
Vec::<u8>::type_layout(),
MoveOption::<MoveString>::type_layout(),
MoveOption::<MoveString>::type_layout(),
Vec::<u8>::type_layout(),
MoveOption::<MoveString>::type_layout(),
MoveOption::<ObjectID>::type_layout(),
MoveOption::<u64>::type_layout(),
SimpleMap::<MoveString, MoveString>::type_layout(),
])
}
}
Expand Down Expand Up @@ -160,23 +165,23 @@ impl<'a> OrdModule<'a> {
pub const FROM_TRANSACTION_FUNCTION_NAME: &'static IdentStr =
ident_str!("from_transaction_bytes");

pub fn from_transaction(&self, tx: &Transaction) -> Result<Vec<InscriptionRecord>> {
pub fn from_transaction(&self, tx: &Transaction) -> Result<Vec<Inscription>> {
let call = Self::create_function_call(
Self::FROM_TRANSACTION_FUNCTION_NAME,
vec![],
vec![MoveValue::vector_u8(tx.to_bytes())],
);
let ctx = TxContext::new_readonly_ctx(AccountAddress::ONE);
let inscription_key =
let inscriptions =
self.caller
.call_function(&ctx, call)?
.into_result()
.map(|mut values| {
let value = values.pop().expect("should have one return value");
bcs::from_bytes::<Vec<InscriptionRecord>>(&value.value)
bcs::from_bytes::<Vec<Inscription>>(&value.value)
.expect("should be a valid Vec<Inscription>")
})?;
Ok(inscription_key)
Ok(inscriptions)
}
}

Expand Down
Loading
Loading