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

Spv #42

Open
wants to merge 58 commits into
base: master
Choose a base branch
from
Open

Spv #42

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
d3559c4
feat(MintXT): finish verify data
Aug 19, 2020
b528e6e
feat(MintXT): add makefile to generate types
Aug 19, 2020
3857bd3
refactor: use int_enum crate replace template code
Aug 19, 2020
a0ac696
Merge branch 'int_enum' into spv
Aug 19, 2020
bde44bd
feat(MintXT): finish main logics
Aug 20, 2020
e4cb5f1
Merge branch 'master' into spv
Aug 20, 2020
8a62700
fix: ambiguous name error
Aug 20, 2020
1e943d8
Merge branch 'fix-ambiguous-name' into spv
Aug 20, 2020
769ff27
fix: merge error
Aug 20, 2020
cb6781b
chore: update makefile
Aug 20, 2020
12c6dfb
chore: remove useless refactor
Aug 21, 2020
e6acecb
fix: change udt amount unit to u128
Aug 21, 2020
b24a0b9
refactor: split mol to multiple files
Aug 21, 2020
79b148d
refactor: split mol to multiple files 2
Aug 21, 2020
9608be1
fix: btc p2wpkh addr check
Aug 21, 2020
f528747
Merge branch 'master' into spv
Aug 24, 2020
83ce8a3
fix: errors after merge
Aug 24, 2020
9bdbed0
fix: mint udt amount
Aug 25, 2020
1144abc
chore: update bitcoin spv dep
Aug 26, 2020
e17104e
test: finish spv verify
Aug 26, 2020
c264716
test: add normal test
Aug 27, 2020
acd5475
Merge branch 'master' into spv
Aug 27, 2020
37f1d3e
fix: fix tests
Aug 27, 2020
3f85dc7
test: add more test code
Aug 28, 2020
4f6ded8
Update contracts/toCKB-typescript/src/switch/mint_xt/mod.rs
Aug 28, 2020
2626718
Update contracts/toCKB-typescript/src/switch/mint_xt/mod.rs
Aug 28, 2020
a36d3fe
chore: add comment
Aug 28, 2020
72d3096
Update contracts/toCKB-typescript/src/switch/mint_xt/mod.rs
Aug 28, 2020
a65bb20
Update contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_wit…
Aug 28, 2020
5347014
Merge branch 'master' into spv
Aug 28, 2020
38471c5
Merge branch 'spv' of github.com:huwenchao/toCKB into spv
Aug 28, 2020
48e70ee
fix: type infer bug
Aug 28, 2020
0cf7fc7
Merge branch 'master' into spv
Aug 28, 2020
2fb847d
chore: fix typo
Aug 31, 2020
993d065
Update contracts/toCKB-typescript/src/switch/mint_xt/mod.rs
Aug 31, 2020
5a864be
Merge branch 'spv' of github.com:huwenchao/toCKB into spv
Aug 31, 2020
96b8150
chore: move simple_udt
Aug 31, 2020
25d340e
fix: add capacity check
Aug 31, 2020
a3b8194
fix: check toCKB cell capacity
Aug 31, 2020
0f05457
Update contracts/toCKB-typescript/src/switch/mint_xt/mod.rs
Sep 1, 2020
81dfe58
Update contracts/toCKB-typescript/src/utils/config.rs
Sep 1, 2020
c69d9b1
fix tests
Sep 1, 2020
62fb93d
feat(MintXT): support eth
LeonLi000 Sep 2, 2020
36edad1
feat(MintXT): add eth-spv testcase for mintXT
LeonLi000 Sep 7, 2020
2617497
minor change
LeonLi000 Sep 8, 2020
2a23a95
rename testcase
LeonLi000 Sep 8, 2020
e88fde1
Merge remote-tracking branch 'upstream/spv' into spv
LeonLi000 Sep 8, 2020
0a3a34b
bugfix
LeonLi000 Sep 8, 2020
097ab56
rebase: rebase from remote
LeonLi000 Sep 17, 2020
938bc14
1. finish mint_xt for eth.
LeonLi000 Sep 26, 2020
bed3173
fmt code
LeonLi000 Sep 26, 2020
992b5ba
remove unused code
LeonLi000 Sep 26, 2020
6fda519
add comment
LeonLi000 Sep 28, 2020
f700492
fix: use nervos cdk-std
LeonLi000 Sep 28, 2020
24e77d0
format code
LeonLi000 Sep 28, 2020
59df51e
fmt code
LeonLi000 Sep 28, 2020
211a4bf
Merge remote-tracking branch 'upstream/master' into spv
LeonLi000 Sep 28, 2020
4a157d2
add xt amount verify
LeonLi000 Oct 22, 2020
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
3,122 changes: 1,648 additions & 1,474 deletions Cargo.lock

Large diffs are not rendered by default.

357 changes: 260 additions & 97 deletions contracts/toCKB-typescript/Cargo.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions contracts/toCKB-typescript/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ bitcoin-spv = { git = "https://github.com/summa-tx/bitcoin-spv.git", branch = "r
bech32 = { git = "https://github.com/reuvenpo/rust-bech32.git", branch = "support-no_std", default-features = false }
primitive-types = { version = "0.7.2", default-features = false }
hex = { version = "0.4", default-features = false }
eth-spv-lib = { git = "https://github.com/LeonLi000/eth-spv-lib.git" }
rlp = {version = "0.4.5", default-features = false }
tockb-types = { path = "../../types", default-features = false, features = ["contract"] }
#ethabi = {version = "12.0.0", default-features = false}
ethereum-types = {version = "0.9.2", default-features = false }

[profile.release]
overflow-checks = true
Expand Down
22 changes: 12 additions & 10 deletions contracts/toCKB-typescript/src/switch/mint_xt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::switch::ToCKBCellDataTuple;
use crate::utils::{
config::{PLEDGE, SIGNER_FEE_RATE, SUDT_CODE_HASH, XT_CELL_CAPACITY},
tools::{is_XT_typescript, verify_btc_witness, XChainKind},
tools::{
get_xchain_kind, is_XT_typescript, verify_btc_witness, verify_eth_witness, XChainKind,
},
types::{mint_xt_witness::MintXTWitnessReader, Error, ToCKBCellDataView, XExtraView},
};
use ckb_std::{
Expand Down Expand Up @@ -59,18 +61,14 @@ fn verify_witness(data: &ToCKBCellDataView) -> Result<XExtraView, Error> {
)?;
Ok(XExtraView::Btc(btc_extra))
}
XChainKind::Eth => todo!(),
XChainKind::Eth => {
let eth_extra = verify_eth_witness(data, proof, cell_dep_index_list)?;
Ok(XExtraView::Eth(eth_extra))
}
}
}

fn verify_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> {
match data.get_xchain_kind() {
XChainKind::Btc => verify_btc_xt_issue(data),
XChainKind::Eth => todo!(),
}
}

fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> {
let lock_hash = load_cell_lock_hash(0, Source::GroupInput)?;
debug!("lockscript hash: {:?}", hex::encode(lock_hash));
let input_xt_num = QueryIter::new(load_cell_type, Source::Input)
Expand All @@ -90,7 +88,11 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> {
if output_xt_num != 2 {
return Err(Error::InvalidXTInInputOrOutput);
}
let xt_amount = data.get_btc_lot_size()?.get_sudt_amount();
let xt_amount = match get_xchain_kind()? {
XChainKind::Btc => data.get_btc_lot_size()?.get_sudt_amount(),
XChainKind::Eth => data.get_eth_lot_size()?.get_sudt_amount(),
};
// data.get_btc_lot_size()?.get_sudt_amount();
debug!("xt_amount: {}", xt_amount);
// fixed order of output cells is required
// user-sudt-cell should be outputs[1]
Expand Down
1 change: 1 addition & 0 deletions contracts/toCKB-typescript/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod tools;

pub use tockb_types as types;
pub use tockb_types::config;
157 changes: 154 additions & 3 deletions contracts/toCKB-typescript/src/utils/tools.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::utils::{
config::{SUDT_CODE_HASH, TX_PROOF_DIFFICULTY_FACTOR, UDT_LEN},
types::{
btc_difficulty::BTCDifficultyReader, mint_xt_witness::BTCSPVProofReader, BtcExtraView,
Error, ToCKBCellDataView, XExtraView,
btc_difficulty::BTCDifficultyReader, mint_xt_witness::BTCSPVProofReader,
mint_xt_witness::ETHSPVProofReader, BtcExtraView, Error, EthExtraView, ToCKBCellDataView,
XExtraView,
},
};
use alloc::{string::String, vec::Vec};
use alloc::{string::String, vec, vec::Vec};

use bech32::ToBase32;
use bitcoin_spv::{
Expand All @@ -20,9 +21,12 @@ use ckb_std::{
high_level::{load_cell_capacity, load_cell_data, load_cell_type, load_script},
};
use core::{convert::From, result::Result};
use eth_spv_lib::{eth_types::*, ethspv};
use hex;
use molecule::prelude::Reader;
use primitive_types::U256;
use tockb_types::generated::basic::OutPoint;
use tockb_types::generated::eth_header_cell_data::{EthCellDataReader, HeaderInfoReader};
pub use tockb_types::tockb_cell::{ToCKBTypeArgsView, XChainKind};

pub fn get_toCKB_type_args() -> Result<ToCKBTypeArgsView, Error> {
Expand Down Expand Up @@ -191,6 +195,153 @@ pub fn verify_btc_witness(
}
}

/// Verify that the header of the user's cross-chain tx is on the main chain.
pub fn verify_eth_header_on_main_chain(
header: &BlockHeader,
cell_dep_index_list: &[u8],
) -> Result<(), Error> {
let dep_data = load_cell_data(cell_dep_index_list[0].into(), Source::CellDep)?;
debug!("dep data is {:?}", &dep_data);
if EthCellDataReader::verify(&dep_data, false).is_err() {
return Err(Error::InvalidWitness);
}
let eth_cell_data_reader = EthCellDataReader::new_unchecked(&dep_data);
debug!("eth_cell_data_reader: {:?}", eth_cell_data_reader);
let tail_raw = eth_cell_data_reader
.headers()
.main()
.get_unchecked(eth_cell_data_reader.headers().main().len() - 1)
.raw_data();
if HeaderInfoReader::verify(&tail_raw, false).is_err() {
return Err(Error::EthHeadersDataInvalid);
}
let tail_info_reader = HeaderInfoReader::new_unchecked(tail_raw);
let tail_info_raw = tail_info_reader.header().raw_data();
let tail: BlockHeader =
rlp::decode(tail_info_raw.to_vec().as_slice()).expect("invalid tail info.");
if header.number > tail.number {
return Err(Error::HeaderIsNotOnMainChain);
}
let offset = (tail.number - header.number) as usize;
if offset > eth_cell_data_reader.headers().main().len() - 1 {
return Err(Error::HeaderIsNotOnMainChain);
}
let target_raw = eth_cell_data_reader
.headers()
.main()
.get_unchecked(eth_cell_data_reader.headers().main().len() - 1 - offset)
.raw_data();
let target_info_reader = HeaderInfoReader::new_unchecked(target_raw);
debug!(
"main chain hash: {:?}, witness header hash: {:?}",
hex::encode(target_info_reader.hash().raw_data()),
hex::encode(header.hash.expect("invalid hash").0.as_bytes())
);
if target_info_reader.hash().raw_data() != header.hash.expect("invalid hash").0.as_bytes() {
return Err(Error::HeaderIsNotOnMainChain);
}
Ok(())
}

/// Verify eth witness data.
/// 1. Verify that the header of the user's cross-chain tx is on the main chain.
/// 2. Verify that the user's cross-chain transaction is legal and really exists (based spv proof).
/// @param data is used to get the real lock address.
/// @param proof is the spv proof data for cross-chain tx.
/// @param cell_dep_index_list is used to get the headers oracle information to verify the cross-chain tx is really exists on the main chain.
///
pub fn verify_eth_witness(
data: &ToCKBCellDataView,
proof: &[u8],
cell_dep_index_list: &[u8],
) -> Result<EthExtraView, Error> {
Comment on lines +253 to +257
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two questions here:

  1. Miss lock amount verification?
  2. Dose eth-transfer tx have a receipt?
    If dosen't, we should verify the tx-structure rather than receipt

if ETHSPVProofReader::verify(proof, false).is_err() {
return Err(Error::InvalidWitness);
}
let proof_reader = ETHSPVProofReader::new_unchecked(proof);
let header_data = proof_reader.header_data().raw_data().to_vec();
let header: BlockHeader = rlp::decode(header_data.as_slice()).expect("invalid header data");
debug!("the witness header data: {:?}", header);
//verify the header is on main chain.
verify_eth_header_on_main_chain(&header, cell_dep_index_list)?;

let mut log_index = [0u8; 8];
log_index.copy_from_slice(proof_reader.log_index().raw_data());
debug!("log_index is {:?}", &log_index);
let log_entry_data = proof_reader.log_entry_data().raw_data().to_vec();
debug!(
"log_entry_data is {:?}",
hex::encode(&log_entry_data.as_slice())
);
let receipt_data = proof_reader.receipt_data().raw_data().to_vec();
debug!(
"receipt_data is {:?}",
hex::encode(&receipt_data.as_slice())
);
let mut receipt_index = [0u8; 8];
receipt_index.copy_from_slice(proof_reader.receipt_index().raw_data());
debug!("receipt_index is {:?}", &receipt_index);
let mut proof = vec![];
for i in 0..proof_reader.proof().len() {
proof.push(proof_reader.proof().get_unchecked(i).raw_data().to_vec());
}
debug!("proof: {:?}", hex::encode(proof[0].clone()));
let log_entry: LogEntry =
rlp::decode(log_entry_data.as_slice()).map_err(|_e| Error::LogEntryInvalid)?;
debug!("log_entry is {:?}", &log_entry);
let receipt: Receipt =
rlp::decode(receipt_data.as_slice()).map_err(|_e| Error::ReceiptInvalid)?;
debug!("receipt_data is {:?}", &receipt);
let log_data = log_entry.data.clone();
let slices = slice_data(log_data.as_slice())?;
debug!("log data slice: {:?}", slices);
let xt_amount:U256 = U256::from(slices[0]);
debug!("log data xt_amount: {:?}", xt_amount);
let expect_value = data.get_eth_lot_size()?.get_sudt_amount();
debug!("expect_value: {:?}", expect_value);
//FIXME: verify xt amount.
let locker_address = (log_entry.address.clone().0).0;
debug!(
"addr: {:?}, x_lock_address: {}",
hex::encode(locker_address.to_vec()),
String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap()
);
if hex::encode(locker_address.to_vec())
!= String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap()
{
return Err(Error::WrongFundingAddr);
}
// verify the spv proof is valid.
if !ethspv::verify_log_entry(
u64::from_le_bytes(log_index),
log_entry_data,
u64::from_le_bytes(receipt_index),
receipt_data,
header.receipts_root,
proof,
) {
return Err(Error::BadMerkleProof);
}
Ok(EthExtraView {})
}

/// Converts a vector of bytes with len equal n * 32, to a vector of slices.
pub fn slice_data(data: &[u8]) -> Result<Vec<[u8;32]>, Error> {
if data.len() % 32 != 0 {
return Err(Error::Encoding);
}

let times = data.len() / 32;
let mut result = Vec::with_capacity(times);
for i in 0..times {
let mut slice = [0u8; 32];
let offset = 32 * i;
slice.copy_from_slice(&data[offset..offset + 32]);
result.push(slice);
}
Ok(result)
}

pub fn verify_btc_faulty_witness(
data: &ToCKBCellDataView,
proof: &[u8],
Expand Down
2 changes: 2 additions & 0 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ serde_json = "1.0"
hex = "0.4"
primitive-types = { version = "0.7.2", default-features = false }
tockb-types = { path = "../types" }
rlp = {version = "0.4.5", default-features = false }
eth-spv-lib = { git = "https://github.com/LeonLi000/eth-spv-lib.git" }
Loading