Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/cargo/miniscript-12.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
popcnt1 authored Aug 12, 2024
2 parents 1064117 + 4e7f069 commit a788e57
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 111 deletions.
53 changes: 36 additions & 17 deletions crates/rooch-framework-tests/src/tests/multisign_account_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@

use crate::binding_test;
use moveos_types::module_binding::MoveFunctionCaller;
use rooch_key::keystore::account_keystore::AccountKeystore;
use rooch_key::keystore::memory_keystore::InMemKeystore;
use rooch_types::nursery::multisign_account::{self, MultisignAccountModule};
use rooch_types::{
crypto::RoochKeyPair,
nursery::multisign_account::{self, MultisignAccountModule},
transaction::RoochTransactionData,
};

#[test]
fn test_multisign_account() {
let _ = tracing_subscriber::fmt::try_init();
let binding_test = binding_test::RustBindingTest::new().unwrap();
let mut binding_test = binding_test::RustBindingTest::new().unwrap();

let keystore = InMemKeystore::new_insecure_for_tests(3);
let kp1 = RoochKeyPair::generate_secp256k1();
let kp2 = RoochKeyPair::generate_secp256k1();
let kp3 = RoochKeyPair::generate_secp256k1();

let u1 = keystore.addresses()[0];
let u2 = keystore.addresses()[1];
let u3 = keystore.addresses()[2];
let u1 = kp1.public().bitcoin_address().unwrap().to_rooch_address();
let u2 = kp2.public().bitcoin_address().unwrap().to_rooch_address();
let u3 = kp3.public().bitcoin_address().unwrap().to_rooch_address();

// println!("u1: {:?}", u1);
// println!("u2: {:?}", u2);
// println!("u3: {:?}", u3);

let kp1 = keystore.get_key_pair(&u1, None).unwrap();
let kp2 = keystore.get_key_pair(&u2, None).unwrap();
let kp3 = keystore.get_key_pair(&u3, None).unwrap();

let pubkeys = vec![
kp1.bitcoin_public_key().unwrap(),
kp2.bitcoin_public_key().unwrap(),
Expand All @@ -44,11 +44,30 @@ fn test_multisign_account() {
multisign_account::generate_multisign_address(2, pubkeys.clone()).unwrap();
//println!("bitcoin_address_from_rust: {}", bitcoin_address_from_rust);

let account_module = binding_test.as_module_binding::<MultisignAccountModule>();
let multisign_address = {
let account_module = binding_test.as_module_binding::<MultisignAccountModule>();

let bitcoin_address_from_move = account_module
.generate_multisign_address(2, pubkeys.clone())
.unwrap();

let bitcoin_address_from_move = account_module
.generate_multisign_address(2, pubkeys)
.unwrap();
assert_eq!(bitcoin_address_from_rust, bitcoin_address_from_move);
bitcoin_address_from_move.to_rooch_address()
};

assert_eq!(bitcoin_address_from_rust, bitcoin_address_from_move);
let action = MultisignAccountModule::initialize_multisig_account_action(2, pubkeys);
let tx_data = RoochTransactionData::new_for_test(u1, 0, action);
let tx = tx_data.sign(&kp1);
binding_test.execute(tx).unwrap();

let account_module = binding_test.as_module_binding::<MultisignAccountModule>();
assert!(account_module
.is_participant(multisign_address.into(), u1.into())
.unwrap());
assert!(account_module
.is_participant(multisign_address.into(), u2.into())
.unwrap());
assert!(account_module
.is_participant(multisign_address.into(), u3.into())
.unwrap());
}
51 changes: 39 additions & 12 deletions crates/rooch-types/src/nursery/multisign_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,9 @@ pub const MODULE_NAME: &IdentStr = ident_str!("multisign_account");

pub fn generate_multisign_address(
threshold: usize,
mut public_keys: Vec<Vec<u8>>,
public_keys: Vec<Vec<u8>>,
) -> Result<BitcoinAddress> {
// Sort public keys to ensure the same script is generated for the same set of keys
//TODO: we should sort on the x-only public key
//FIX the Move code version then fix this
public_keys.sort();

let public_keys = public_keys
let mut x_only_public_keys = public_keys
.into_iter()
.map(|pk| {
let x_only_pk = if pk.len() == SCHNORR_PUBLIC_KEY_SIZE {
Expand All @@ -40,12 +35,16 @@ pub fn generate_multisign_address(
})
.collect::<Result<Vec<_>>>()?;

let multisig_script = create_multisig_script(threshold, &public_keys);
// Sort public keys to ensure the same script is generated for the same set of keys
// Note: we sort on the x-only public key
x_only_public_keys.sort();

let multisig_script = create_multisig_script(threshold, &x_only_public_keys);

let builder = TaprootBuilder::new().add_leaf(0, multisig_script)?;
let secp = Secp256k1::verification_only();
//Use the first public key after sorted as the internal key
let internal_key = public_keys[0];
let internal_key = x_only_public_keys[0];

let spend_info = builder.finalize(&secp, internal_key).unwrap();

Expand Down Expand Up @@ -85,15 +84,18 @@ pub struct MultisignAccountModule<'a> {
impl<'a> MultisignAccountModule<'a> {
const INITIALIZE_MULTISIG_ACCOUNT_ENTRY_FUNCTION_NAME: &'static IdentStr =
ident_str!("initialize_multisig_account_entry");
const GENERATE_MULTISIGN_ADDRESS_FUNCTION_NAME: &'static IdentStr =
ident_str!("generate_multisign_address");
const IS_PARTICIPANT_FUNCTION_NAME: &'static IdentStr = ident_str!("is_participant");

pub fn initialize_multisig_account_action(
public_keys: Vec<Vec<u8>>,
threshold: u64,
public_keys: Vec<Vec<u8>>,
) -> MoveAction {
Self::create_move_action(
Self::INITIALIZE_MULTISIG_ACCOUNT_ENTRY_FUNCTION_NAME,
vec![],
vec![public_keys.to_move_value(), threshold.to_move_value()],
vec![threshold.to_move_value(), public_keys.to_move_value()],
)
}

Expand All @@ -103,7 +105,7 @@ impl<'a> MultisignAccountModule<'a> {
public_keys: Vec<Vec<u8>>,
) -> Result<BitcoinAddress> {
let function_call = Self::create_function_call(
ident_str!("generate_multisign_address"),
Self::GENERATE_MULTISIGN_ADDRESS_FUNCTION_NAME,
vec![],
vec![threshold.to_move_value(), public_keys.to_move_value()],
);
Expand All @@ -119,6 +121,31 @@ impl<'a> MultisignAccountModule<'a> {
})?;
Ok(address)
}

pub fn is_participant(
&self,
multisign_address: AccountAddress,
participant_address: AccountAddress,
) -> Result<bool> {
let function_call = Self::create_function_call(
Self::IS_PARTICIPANT_FUNCTION_NAME,
vec![],
vec![
multisign_address.to_move_value(),
participant_address.to_move_value(),
],
);
let ctx = TxContext::new_readonly_ctx(AccountAddress::ZERO);
let is_participant = self
.caller
.call_function(&ctx, function_call)?
.into_result()
.map(|mut values| {
let value = values.pop().expect("should have one return value");
bcs::from_bytes::<bool>(&value.value).expect("should be a valid bool")
})?;
Ok(is_participant)
}
}

impl<'a> ModuleBinding<'a> for MultisignAccountModule<'a> {
Expand Down
18 changes: 18 additions & 0 deletions frameworks/rooch-nursery/doc/multisign_account.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ Bitcoin multisign account module



<a name="0xa_multisign_account_BITCOIN_COMPRESSED_PUBLIC_KEY_LEN"></a>



<pre><code><b>const</b> <a href="multisign_account.md#0xa_multisign_account_BITCOIN_COMPRESSED_PUBLIC_KEY_LEN">BITCOIN_COMPRESSED_PUBLIC_KEY_LEN</a>: u64 = 33;
</code></pre>



<a name="0xa_multisign_account_ErrorInvalidParticipant"></a>


Expand Down Expand Up @@ -204,6 +213,15 @@ Bitcoin multisign account module



<a name="0xa_multisign_account_X_ONLY_PUBLIC_KEY_LEN"></a>



<pre><code><b>const</b> <a href="multisign_account.md#0xa_multisign_account_X_ONLY_PUBLIC_KEY_LEN">X_ONLY_PUBLIC_KEY_LEN</a>: u64 = 32;
</code></pre>



<a name="0xa_multisign_account_initialize_multisig_account_entry"></a>

## Function `initialize_multisig_account_entry`
Expand Down
40 changes: 21 additions & 19 deletions frameworks/rooch-nursery/doc/result.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- [Function `is_ok`](#0xa_result_is_ok)
- [Function `get`](#0xa_result_get)
- [Function `err`](#0xa_result_err)
- [Function `err_string`](#0xa_result_err_string)
- [Function `err_str`](#0xa_result_err_str)
- [Function `is_err`](#0xa_result_is_err)
- [Function `get_err`](#0xa_result_get_err)
- [Function `as_err`](#0xa_result_as_err)
Expand All @@ -38,7 +38,7 @@ Most of the time, we do not need the Result type in smart contract, we can direc
But in some cases, we need to return a result to ensure the caller can handle the error.


<pre><code><b>struct</b> <a href="result.md#0xa_result_Result">Result</a>&lt;T&gt; <b>has</b> <b>copy</b>, drop
<pre><code><b>struct</b> <a href="result.md#0xa_result_Result">Result</a>&lt;T, E&gt; <b>has</b> <b>copy</b>, drop
</code></pre>


Expand Down Expand Up @@ -74,7 +74,7 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_ok">ok</a>&lt;T&gt;(value: T): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_ok">ok</a>&lt;T, E&gt;(value: T): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;
</code></pre>


Expand All @@ -85,7 +85,7 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_is_ok">is_ok</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): bool
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_is_ok">is_ok</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): bool
</code></pre>


Expand All @@ -96,7 +96,7 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_get">get</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): &<a href="_Option">option::Option</a>&lt;T&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_get">get</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): &<a href="_Option">option::Option</a>&lt;T&gt;
</code></pre>


Expand All @@ -107,18 +107,20 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_err">err</a>&lt;T&gt;(err: <a href="">vector</a>&lt;u8&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_err">err</a>&lt;T, E&gt;(err: E): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;
</code></pre>



<a name="0xa_result_err_string"></a>
<a name="0xa_result_err_str"></a>

## Function `err_string`
## Function `err_str`

A shortcut to create a Result<T, String> with an error String with
err_str(b"msg").


<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_err_string">err_string</a>&lt;T&gt;(err: <a href="_String">string::String</a>): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_err_str">err_str</a>&lt;T&gt;(err: <a href="">vector</a>&lt;u8&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, <a href="_String">string::String</a>&gt;
</code></pre>


Expand All @@ -129,7 +131,7 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_is_err">is_err</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): bool
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_is_err">is_err</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): bool
</code></pre>


Expand All @@ -140,7 +142,7 @@ Expected the result is ok but the result is err.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_get_err">get_err</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): <a href="_Option">option::Option</a>&lt;<a href="_String">string::String</a>&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_get_err">get_err</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: &<a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): &<a href="_Option">option::Option</a>&lt;E&gt;
</code></pre>


Expand All @@ -149,10 +151,10 @@ Expected the result is ok but the result is err.

## Function `as_err`

Convert an error Result<T> to error Result<U>.
Convert an error Result<T, String> to error Result<U, String>.


<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_as_err">as_err</a>&lt;U, T&gt;(self: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;U&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_as_err">as_err</a>&lt;U, T&gt;(self: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, <a href="_String">string::String</a>&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;U, <a href="_String">string::String</a>&gt;
</code></pre>


Expand All @@ -163,7 +165,7 @@ Convert an error Result<T> to error Result<U>.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unpack">unpack</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): (<a href="_Option">option::Option</a>&lt;T&gt;, <a href="_Option">option::Option</a>&lt;<a href="_String">string::String</a>&gt;)
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unpack">unpack</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): (<a href="_Option">option::Option</a>&lt;T&gt;, <a href="_Option">option::Option</a>&lt;E&gt;)
</code></pre>


Expand All @@ -174,7 +176,7 @@ Convert an error Result<T> to error Result<U>.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_and_then">and_then</a>&lt;U, T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;U&gt;, f: |U|<a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_and_then">and_then</a>&lt;U, T, E&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;U, E&gt;, f: |U|<a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;
</code></pre>


Expand All @@ -185,7 +187,7 @@ Convert an error Result<T> to error Result<U>.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unwrap">unwrap</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): T
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unwrap">unwrap</a>&lt;T, E: drop&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): T
</code></pre>


Expand All @@ -196,7 +198,7 @@ Convert an error Result<T> to error Result<U>.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unwrap_err">unwrap_err</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;): <a href="_String">string::String</a>
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_unwrap_err">unwrap_err</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;): E
</code></pre>


Expand All @@ -211,7 +213,7 @@ This function is inline, so it will be expanded in the caller.
This ensures the abort_code is the caller's location.


<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_assert_ok">assert_ok</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;, abort_code: u64): T
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_assert_ok">assert_ok</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;, abort_code: u64): T
</code></pre>


Expand All @@ -222,5 +224,5 @@ This ensures the abort_code is the caller's location.



<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_assert_err">assert_err</a>&lt;T&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T&gt;, abort_code: u64): <a href="_String">string::String</a>
<pre><code><b>public</b> <b>fun</b> <a href="result.md#0xa_result_assert_err">assert_err</a>&lt;T, E&gt;(<a href="result.md#0xa_result">result</a>: <a href="result.md#0xa_result_Result">result::Result</a>&lt;T, E&gt;, abort_code: u64): E
</code></pre>
2 changes: 1 addition & 1 deletion frameworks/rooch-nursery/doc/tick_info.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ Check if the tick is deployed.



<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="tick_info.md#0xa_tick_info_mint_on_bitcoin">mint_on_bitcoin</a>(metaprotocol: <a href="_String">string::String</a>, tick: <a href="_String">string::String</a>, amount: u64): <a href="result.md#0xa_result_Result">result::Result</a>&lt;<a href="_Object">object::Object</a>&lt;<a href="bitseed.md#0xa_bitseed_Bitseed">bitseed::Bitseed</a>&gt;&gt;
<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="tick_info.md#0xa_tick_info_mint_on_bitcoin">mint_on_bitcoin</a>(metaprotocol: <a href="_String">string::String</a>, tick: <a href="_String">string::String</a>, amount: u64): <a href="result.md#0xa_result_Result">result::Result</a>&lt;<a href="_Object">object::Object</a>&lt;<a href="bitseed.md#0xa_bitseed_Bitseed">bitseed::Bitseed</a>&gt;, <a href="_String">string::String</a>&gt;
</code></pre>


Expand Down
Loading

0 comments on commit a788e57

Please sign in to comment.