Skip to content

Commit

Permalink
[rooch-networkgh-2295] from verify_with_pk to verify_bitcoin_address_…
Browse files Browse the repository at this point in the history
…with_public_key.
  • Loading branch information
Feliciss committed Jul 31, 2024
1 parent 69400c4 commit dd2606f
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 27 deletions.
2 changes: 1 addition & 1 deletion crates/rooch-types/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ impl BitcoinAddress {
pub fn new_witness_program(witness_program: &bitcoin::WitnessProgram) -> Self {
// First byte is BitcoinAddress Payload type
let mut bytes = vec![BitcoinAddressPayloadType::WitnessProgram.to_num()];
// Third byte represents Version 0 or PUSHNUM_1-PUSHNUM_16
// Second byte represents Version 0 or PUSHNUM_1-PUSHNUM_16
bytes.push(witness_program.version().to_num());
// Remain are Program data
bytes.extend_from_slice(witness_program.program().as_bytes());
Expand Down
24 changes: 24 additions & 0 deletions frameworks/rooch-framework/doc/bitcoin_address.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
- [Function `from_string`](#0x3_bitcoin_address_from_string)
- [Function `verify_with_public_key`](#0x3_bitcoin_address_verify_with_public_key)
- [Function `to_rooch_address`](#0x3_bitcoin_address_to_rooch_address)
- [Function `verify_bitcoin_address_with_public_key`](#0x3_bitcoin_address_verify_bitcoin_address_with_public_key)
- [Function `derive_multi_sign_address`](#0x3_bitcoin_address_derive_multi_sign_address)


<pre><code><b>use</b> <a href="">0x1::string</a>;
Expand Down Expand Up @@ -271,3 +273,25 @@ Empty address is a special address that is used to if we parse address failed fr

<pre><code><b>public</b> <b>fun</b> <a href="bitcoin_address.md#0x3_bitcoin_address_to_rooch_address">to_rooch_address</a>(addr: &<a href="bitcoin_address.md#0x3_bitcoin_address_BitcoinAddress">bitcoin_address::BitcoinAddress</a>): <b>address</b>
</code></pre>



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

## Function `verify_bitcoin_address_with_public_key`



<pre><code><b>public</b> <b>fun</b> <a href="bitcoin_address.md#0x3_bitcoin_address_verify_bitcoin_address_with_public_key">verify_bitcoin_address_with_public_key</a>(bitcoin_addr: &<a href="bitcoin_address.md#0x3_bitcoin_address_BitcoinAddress">bitcoin_address::BitcoinAddress</a>, pk: &<a href="">vector</a>&lt;u8&gt;): bool
</code></pre>



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

## Function `derive_multi_sign_address`



<pre><code><b>public</b> <b>fun</b> <a href="bitcoin_address.md#0x3_bitcoin_address_derive_multi_sign_address">derive_multi_sign_address</a>(public_keys: &<a href="">vector</a>&lt;<a href="">vector</a>&lt;u8&gt;&gt;, threshold: u64): <a href="bitcoin_address.md#0x3_bitcoin_address_BitcoinAddress">bitcoin_address::BitcoinAddress</a>
</code></pre>
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,23 @@ module rooch_framework::bitcoin_address {
}

public fun verify_with_public_key(addr: &String, pk: &vector<u8>): bool {
let raw_bytes = string::bytes(addr);
verify_with_pk(raw_bytes, pk)
let bitcoin_addr = from_string(addr);
verify_bitcoin_address_with_public_key(&bitcoin_addr, pk)
}

public fun to_rooch_address(addr: &BitcoinAddress): address{
let hash = moveos_std::hash::blake2b256(&addr.bytes);
moveos_std::bcs::to_address(hash)
}

// verify bitcoin address according to the pk bytes
public native fun verify_bitcoin_address_with_public_key(bitcoin_addr: &BitcoinAddress, pk: &vector<u8>): bool;

// derive multi signature address from public keys
public native fun derive_multi_sign_address(public_keys: &vector<vector<u8>>, threshold: u64): BitcoinAddress;

/// Parse the Bitcoin address string bytes to Move BitcoinAddress
native fun parse(raw_addr: &vector<u8>): BitcoinAddress;
native fun verify_with_pk (addr: &vector<u8>, pk: &vector<u8>): bool;

#[test_only]
public fun random_address_for_testing(): BitcoinAddress {
Expand All @@ -116,7 +121,7 @@ module rooch_framework::bitcoin_address {
}

#[test]
fun test_verify_with_pk_success() {
fun test_verify_with_public_key_success() {
// p2tr
let addr = string::utf8(b"bc1p8xpjpkc9uzj2dexcxjg9sw8lxje85xa4070zpcys589e3rf6k20qm6gjrt");
let pk = x"038e3d29b653e40f5b620f9443ee05222d1e40be58f544b6fed3d464edd54db883";
Expand All @@ -141,8 +146,8 @@ module rooch_framework::bitcoin_address {

#[test]
fun test_validate_signature_fail() {
let addr = string::utf8(b"ac1p8xpjpkc9uzj2dexcxjg9sw8lxje85xa4070zpcys589e3rf6k20qm6gjrt");
let pk = x"038e3d29b653e40f5b620f9443ee05222d1e40be58f544b6fed3d464edd54db883";
let addr = string::utf8(b"bc1p8xpjpkc9uzj2dexcxjg9sw8lxje85xa4070zpcys589e3rf6k20qm6gjrt");
let pk = x"038e3d29b653e40f5b620f9443ee05222d1e40be58f544b6fed3d464edd54db884";
assert!(!verify_with_public_key(&addr, &pk), 1004);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::natives::gas_parameter::native::MUL;
use crate::natives::rooch_framework::bitcoin_address::GasParameters;

crate::natives::gas_parameter::native::define_gas_parameters_for_natives!(GasParameters, "bitcoin_address", [
[.verify_with_pk.base, "verify_with_pk.base", 1000 * MUL],
[.verify_with_pk.per_byte, "verify_with_pk.per_byte", 30 * MUL],
[.verify_bitcoin_address_with_public_key.base, "verify_bitcoin_address_with_public_key.base", 1000 * MUL],
[.verify_bitcoin_address_with_public_key.per_byte, "verify_bitcoin_address_with_public_key.per_byte", 30 * MUL],
[.new.base, "parse.base", 1000 * MUL],
[.new.per_byte, "parse.per_byte", 30 * MUL],
]);
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ use bitcoin::{
secp256k1::Secp256k1,
PublicKey, XOnlyPublicKey,
};
use move_binary_format::errors::PartialVMResult;
use move_core_types::gas_algebra::{InternalGas, InternalGasPerByte, NumBytes};
use move_binary_format::errors::{PartialVMError, PartialVMResult};
use move_core_types::{
gas_algebra::{InternalGas, InternalGasPerByte, NumBytes},
vm_status::StatusCode,
};
use move_vm_runtime::native_functions::{NativeContext, NativeFunction};
use move_vm_types::{
loaded_data::runtime_types::Type,
natives::function::NativeResult,
pop_arg,
values::{Value, VectorRef},
values::{StructRef, Value, VectorRef},
};
use moveos_stdlib::natives::helpers::{make_module_natives, make_native};
use moveos_types::state::MoveStructState;
use moveos_types::state::{MoveState, MoveStructState};
use rooch_types::address::BitcoinAddress;
use smallvec::smallvec;
use std::{collections::VecDeque, str::FromStr};
Expand Down Expand Up @@ -51,31 +54,34 @@ pub fn parse(
))
}

/// Returns true if the given pubkey is directly related to the address payload.
pub fn verify_with_pk(
/// Returns true if the given pubkey's bitcoin address is equal to the input bitcoin address.
pub fn verify_bitcoin_address_with_public_key(
gas_params: &FromBytesGasParameters,
_context: &mut NativeContext,
_ty_args: Vec<Type>,
mut args: VecDeque<Value>,
) -> PartialVMResult<NativeResult> {
let pk_bytes = pop_arg!(args, VectorRef);
let addr_bytes = pop_arg!(args, VectorRef);
let addr_bytes = pop_arg!(args, StructRef);

let pk_ref = pk_bytes.as_bytes_ref();
let addr_ref = addr_bytes.as_bytes_ref();
let addr_value = addr_bytes.read_ref()?;

let bitcoin_addr = BitcoinAddress::from_runtime_value(addr_value).map_err(|e| {
PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR)
.with_message(format!("Failed to parse bitcoin address: {}", e))
})?;
let cost = gas_params.base
+ gas_params.per_byte * NumBytes::new((pk_ref.len() + addr_ref.len()) as u64);
+ gas_params.per_byte
* NumBytes::new((pk_ref.len() + bitcoin_addr.to_bytes().len()) as u64);

// TODO: convert to internal rooch public key and to bitcoin address?
let Ok(pk) = PublicKey::from_slice(&pk_ref) else {
return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)]));
};

let Ok(addr_str) = std::str::from_utf8(&addr_ref) else {
return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)]));
};

let addr = match Address::from_str(addr_str) {
// TODO: compare the input bitcoin address with the converted bitcoin address
let addr = match Address::from_str(&bitcoin_addr.to_string()) {
Ok(addr) => addr.assume_checked(),
Err(_) => {
return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)]));
Expand Down Expand Up @@ -117,14 +123,14 @@ impl FromBytesGasParameters {
#[derive(Debug, Clone)]
pub struct GasParameters {
pub new: FromBytesGasParameters,
pub verify_with_pk: FromBytesGasParameters,
pub verify_bitcoin_address_with_public_key: FromBytesGasParameters,
}

impl GasParameters {
pub fn zeros() -> Self {
Self {
new: FromBytesGasParameters::zeros(),
verify_with_pk: FromBytesGasParameters::zeros(),
verify_bitcoin_address_with_public_key: FromBytesGasParameters::zeros(),
}
}
}
Expand All @@ -133,8 +139,11 @@ pub fn make_all(gas_params: GasParameters) -> impl Iterator<Item = (String, Nati
let natives = [
("parse", make_native(gas_params.new, parse)),
(
"verify_with_pk",
make_native(gas_params.verify_with_pk, verify_with_pk),
"verify_bitcoin_address_with_public_key",
make_native(
gas_params.verify_bitcoin_address_with_public_key,
verify_bitcoin_address_with_public_key,
),
),
];

Expand Down

0 comments on commit dd2606f

Please sign in to comment.