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

omnilock support coubuild and transaction #114

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
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
81 changes: 41 additions & 40 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: CI workflow

on:
pull_request:
types: [ opened, synchronize, reopened ]
types: [opened, synchronize, reopened]
push:
branches:
- "develop"
Expand All @@ -18,63 +18,64 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, macos-latest, windows-2019 ]
os: [ubuntu-latest, macos-latest, windows-2019]
steps:
- uses: actions/checkout@v2
- if: matrix.os == 'windows-2019'
name: Windows Dependencies
run: |
iwr -useb get.scoop.sh -outfile 'install-scoop.ps1'
.\install-scoop.ps1 -RunAsAdmin
echo "LIBCLANG_PATH=$($HOME)/scoop/apps/llvm/current/bin" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "$env:USERPROFILE\scoop\shims" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
scoop install llvm yasm
- name: UnitTest
run: make test
- uses: actions/checkout@v2
- if: matrix.os == 'windows-2019'
name: Windows Dependencies
run: |
iwr -useb get.scoop.sh -outfile 'install-scoop.ps1'
.\install-scoop.ps1 -RunAsAdmin
echo "LIBCLANG_PATH=$($HOME)/scoop/apps/llvm/current/bin" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "$env:USERPROFILE\scoop\shims" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
scoop install llvm yasm
- name: UnitTest
run: make test

build-examples:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, macos-latest, windows-2019 ]
os: [ubuntu-latest, macos-latest, windows-2019]
steps:
- uses: actions/checkout@v2
- if: matrix.os == 'windows-2019'
name: Windows Dependencies
run: |
iwr -useb get.scoop.sh -outfile 'install-scoop.ps1'
.\install-scoop.ps1 -RunAsAdmin
echo "LIBCLANG_PATH=$($HOME)/scoop/apps/llvm/current/bin" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "$env:USERPROFILE\scoop\shims" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
scoop install llvm yasm
- name: Build Cargo Examples
run: cargo build --examples
- uses: actions/checkout@v2
- if: matrix.os == 'windows-2019'
name: Windows Dependencies
run: |
iwr -useb get.scoop.sh -outfile 'install-scoop.ps1'
.\install-scoop.ps1 -RunAsAdmin
echo "LIBCLANG_PATH=$($HOME)/scoop/apps/llvm/current/bin" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "$env:USERPROFILE\scoop\shims" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
scoop install llvm yasm
- name: Build Cargo Examples
run: cargo build --examples

linters:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v2
- name: Linters
run: |
cargo fmt --version || rustup component add rustfmt
cargo clippy --version || rustup component add clippy
make fmt
make clippy
- uses: actions/checkout@v2
- name: Linters
run: |
cargo fmt --version || rustup component add rustfmt
cargo clippy --version || rustup component add clippy
make fmt
make clippy

security-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Security Audit & Licenses
run: |
rustup toolchain install stable --profile minimal
cargo deny --version || cargo install cargo-deny --locked
make security-audit
make check-crates
make check-licenses
- uses: actions/checkout@v2
- name: Security Audit & Licenses
run: |
rustup toolchain install stable --profile minimal
rm rust-toolchain.toml
cargo deny --version || cargo install cargo-deny --locked
make security-audit
make check-crates
make check-licenses

ci-success:
name: ci
Expand Down
26 changes: 21 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
[package]
name = "ckb-sdk"
version = "3.5.0"
authors = [ "Linfeng Qian <thewawar@gmail.com>", "Nervos Core Dev <dev@nervos.org>" ]
authors = [
"Linfeng Qian <thewawar@gmail.com>",
"Nervos Core Dev <dev@nervos.org>",
]


edition = "2018"
license = "MIT"
description = "Rust SDK for CKB"
homepage = "https://github.com/nervosnetwork/ckb-sdk-rust"
repository = "https://github.com/nervosnetwork/ckb-sdk-rust"
exclude = ["/test-data"]

[dependencies]
serde = { version = "1.0", features = ["derive"] }
Expand All @@ -17,7 +23,10 @@ anyhow = "1.0.63"
bech32 = "0.8.1"
derive-getters = "0.2.1"
log = "0.4.6"
reqwest = { version = "0.11", default-features = false, features = [ "json", "blocking" ] }
reqwest = { version = "0.11", default-features = false, features = [
"json",
"blocking",
] }
secp256k1 = { version = "0.29.0", features = ["recovery"] }
tokio-util = { version = "0.7.7", features = ["codec"] }
tokio = { version = "1" }
Expand All @@ -28,6 +37,10 @@ parking_lot = "0.12"
lru = "0.7.1"
dashmap = "5.4"
dyn-clone = "1.0"
faster-hex = "0.9.0"
ripemd = "0.1.3"
sha2 = "0.10.6"
ed25519-dalek = "2.1.1"

ckb-types = "0.119.0"
ckb-dao-utils = "0.119.0"
Expand All @@ -42,7 +55,7 @@ sha3 = "0.10.1"
enum-repr-derive = "0.2.0"

# for feature test
rand = { version = "0.7.3", optional = true }
rand = { version = "0.7.3" }
ckb-mock-tx-types = { version = "0.119.0" }
ckb-chain-spec = "0.119.0"

Expand All @@ -57,7 +70,10 @@ rustls-tls = ["reqwest/rustls-tls"]
test = []

[dev-dependencies]
clap = { version = "=4.4.18", features = [ "derive" ] } # TODO clap v4.5 requires rustc v1.74.0+
clap = { version = "4.4.18", features = ["derive"] }
httpmock = "0.6"
async-global-executor = "2.3.1"
hex = "0.4"


[target.'cfg(unix)'.dev-dependencies]
openssl = "0.10"
7 changes: 4 additions & 3 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ ignore = [
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate"
"RUSTSEC-2024-0370" # proc-macro-error's maintainer seems to be unreachable, ignore this
"RUSTSEC-2024-0370", # proc-macro-error's maintainer seems to be unreachable, ignore this
"RUSTSEC-2024-0384", # instant is no longer maintained, ignore this
]
# If this is true, then cargo deny will use the git executable to fetch advisory database.
# If this is false, then it uses a built-in git library.
Expand All @@ -97,8 +98,8 @@ allow = [
"ISC",
"MIT",
"Unicode-DFS-2016",
"BSL-1.0", # xxhash-rust 0.8.10

"BSL-1.0", # xxhash-rust 0.8.10
"Unicode-3.0",
#"MIT",
#"Apache-2.0",
#"Apache-2.0 WITH LLVM-exception",
Expand Down
68 changes: 68 additions & 0 deletions examples/omnilock_examples.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use ckb_sdk::{
constants::ONE_CKB,
transaction::{
builder::{CkbTransactionBuilder, SimpleTransactionBuilder},
handler::{omnilock, HandlerContexts},
input::InputIterator,
signer::{SignContexts, TransactionSigner},
TransactionBuilderConfiguration,
},
unlock::OmniLockConfig,
Address, CkbRpcClient, NetworkInfo,
};
use ckb_types::{
h256,
packed::CellOutput,
prelude::{Builder, Entity, Pack},
};
use std::{error::Error as StdErr, str::FromStr};

fn main() -> Result<(), Box<dyn StdErr>> {
let network_info = NetworkInfo::testnet();
let sender = Address::from_str("ckt1qrejnmlar3r452tcg57gvq8patctcgy8acync0hxfnyka35ywafvkqgqgpy7m88v3gxnn3apazvlpkkt32xz3tg5qq3kzjf3")?;
let receiver = Address::from_str("ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqv5dsed9par23x4g58seaw58j3ym5ml2hs8ztche")?;

let configuration = TransactionBuilderConfiguration::new_with_network(network_info.clone())?;

let iterator = InputIterator::new_with_address(&[sender.clone()], configuration.network_info());
let mut builder = SimpleTransactionBuilder::new(configuration, iterator);

let output = CellOutput::new_builder()
.capacity((128 * ONE_CKB).pack())
.lock((&receiver).into())
.build();
builder.add_output_and_data(output.clone(), ckb_types::packed::Bytes::default());
builder.set_change_lock((&sender).into());

let omni_cfg = OmniLockConfig::from_addr(&sender).unwrap();
let context = omnilock::OmnilockScriptContext::new(omni_cfg.clone(), network_info.url.clone());

let mut contexts = HandlerContexts::default();
contexts.add_context(Box::new(context) as Box<_>);

let mut tx_with_groups = builder.build(&contexts)?;

let json_tx = ckb_jsonrpc_types::TransactionView::from(tx_with_groups.get_tx_view().clone());
println!("tx: {}", serde_json::to_string_pretty(&json_tx).unwrap());

let private_key = h256!("0x6c9ed03816e3111e49384b8d180174ad08e29feb1393ea1b51cef1c505d4e36a");
TransactionSigner::new(&network_info).sign_transaction(
&mut tx_with_groups,
&SignContexts::new_omnilock(
[secp256k1::SecretKey::from_slice(private_key.as_bytes())?].to_vec(),
omni_cfg,
ckb_sdk::unlock::OmniUnlockMode::Normal,
),
)?;

let json_tx = ckb_jsonrpc_types::TransactionView::from(tx_with_groups.get_tx_view().clone());
println!("tx: {}", serde_json::to_string_pretty(&json_tx).unwrap());

let tx_hash = CkbRpcClient::new(network_info.url.as_str())
.send_transaction(json_tx.inner, None)
.expect("send transaction");
// example tx: 0xc0c9954a3299b540e63351146a301438372abf93682d96c7cce691c334dd5757
println!(">>> tx {} sent! <<<", tx_hash);

Ok(())
}
88 changes: 88 additions & 0 deletions examples/omnilock_multisig_example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use ckb_sdk::{
constants::ONE_CKB,
transaction::{
builder::{CkbTransactionBuilder, SimpleTransactionBuilder},
handler::{omnilock, HandlerContexts},
input::InputIterator,
signer::{SignContexts, TransactionSigner},
TransactionBuilderConfiguration,
},
unlock::{MultisigConfig, OmniLockConfig},
Address, CkbRpcClient, NetworkInfo,
};
use ckb_types::{
h160, h256,
packed::CellOutput,
prelude::{Builder, Entity, Pack},
};
use std::{error::Error as StdErr, str::FromStr};

fn main() -> Result<(), Box<dyn StdErr>> {
let network_info = NetworkInfo::testnet();
let sender = Address::from_str("ckt1qrejnmlar3r452tcg57gvq8patctcgy8acync0hxfnyka35ywafvkqgxhjvp3k9pf88upngryvuxc346q7fq5qmlqqlrhr0p")?;
let receiver = Address::from_str("ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqv5dsed9par23x4g58seaw58j3ym5ml2hs8ztche")?;

let configuration = TransactionBuilderConfiguration::new_with_network(network_info.clone())?;

let iterator = InputIterator::new_with_address(&[sender.clone()], configuration.network_info());
let mut builder = SimpleTransactionBuilder::new(configuration, iterator);

let output = CellOutput::new_builder()
.capacity((128 * ONE_CKB).pack())
.lock((&receiver).into())
.build();
builder.add_output_and_data(output.clone(), ckb_types::packed::Bytes::default());
builder.set_change_lock((&sender).into());

let mut omni_cfg = OmniLockConfig::from_addr(&sender).unwrap();
let multisig_config = MultisigConfig::new_with(
vec![
h160!("0x7336b0ba900684cb3cb00f0d46d4f64c0994a562"),
h160!("0x5724c1e3925a5206944d753a6f3edaedf977d77f"),
],
0,
2,
)
.unwrap();
omni_cfg.set_multisig_config(Some(multisig_config));
let context = omnilock::OmnilockScriptContext::new(omni_cfg.clone(), network_info.url.clone());

let mut contexts = HandlerContexts::default();
contexts.add_context(Box::new(context) as Box<_>);

let mut tx_with_groups = builder.build(&contexts)?;

let json_tx = ckb_jsonrpc_types::TransactionView::from(tx_with_groups.get_tx_view().clone());
println!("tx: {}", serde_json::to_string_pretty(&json_tx).unwrap());

let signer = TransactionSigner::new(&network_info);
let private_key = h256!("0x7438f7b35c355e3d2fb9305167a31a72d22ddeafb80a21cc99ff6329d92e8087");
signer.sign_transaction(
&mut tx_with_groups,
&SignContexts::new_omnilock(
[secp256k1::SecretKey::from_slice(private_key.as_bytes())?].to_vec(),
omni_cfg.clone(),
ckb_sdk::unlock::OmniUnlockMode::Normal,
),
)?;
let private_key = h256!("0x4fd809631a6aa6e3bb378dd65eae5d71df895a82c91a615a1e8264741515c79c");
signer.sign_transaction(
&mut tx_with_groups,
&SignContexts::new_omnilock(
[secp256k1::SecretKey::from_slice(private_key.as_bytes())?].to_vec(),
omni_cfg,
ckb_sdk::unlock::OmniUnlockMode::Normal,
),
)?;

let json_tx = ckb_jsonrpc_types::TransactionView::from(tx_with_groups.get_tx_view().clone());
println!("tx: {}", serde_json::to_string_pretty(&json_tx).unwrap());

let tx_hash = CkbRpcClient::new(network_info.url.as_str())
.send_transaction(json_tx.inner, None)
.expect("send transaction");
// example tx: 3c5062f75f8c9dc799a3286ebef070cd3aa1b51575244c912076b90cb915a374
println!(">>> tx {} sent! <<<", tx_hash);

Ok(())
}
File renamed without changes.
1 change: 0 additions & 1 deletion rust-toolchain

This file was deleted.

2 changes: 2 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
channel = "1.75.0"
5 changes: 5 additions & 0 deletions src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ pub const ACP_TYPE_HASH_AGGRON: H256 =
/// cheque withdraw since value
pub const CHEQUE_CELL_SINCE: u64 = 0xA000000000000006;

pub const COMMON_PREFIX: &str = "CKB transaction: 0x";
pub const BTC_PREFIX: &str = "CKB (Bitcoin Layer) transaction: 0x";

pub const SECP256K1_TAG_PUBKEY_UNCOMPRESSED: u8 = 0x04;

#[cfg(test)]
mod test {
use super::*;
Expand Down
Loading
Loading