Skip to content

Commit

Permalink
Use BitcoinSignVType instead of compress in bitcoin
Browse files Browse the repository at this point in the history
  • Loading branch information
joii2020 committed Oct 24, 2023
1 parent 05ebcd7 commit 81d6505
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 60 deletions.
2 changes: 1 addition & 1 deletion c/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ int validate_signature_eos(void *prefilled_data, const uint8_t *sig, size_t sig_
}
uint8_t out_pubkey[UNCOMPRESSED_SECP256K1_PUBKEY_SIZE];
size_t out_pubkey_size = UNCOMPRESSED_SECP256K1_PUBKEY_SIZE;
err = _recover_secp256k1_pubkey_btc(sig, sig_len, msg, msg_len, out_pubkey, &out_pubkey_size, false);
err = _recover_secp256k1_pubkey_btc(sig, sig_len, msg, msg_len, out_pubkey, &out_pubkey_size);
CHECK(err);

blake2b_state ctx;
Expand Down
100 changes: 60 additions & 40 deletions tests/auth_rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -903,29 +903,32 @@ impl Auth for EthereumAuth {
#[derive(Clone)]
pub struct EosAuth {
pub privkey: Privkey,
pub compress: bool,
pub v_type: BitcoinSignVType,
}
impl EosAuth {
fn new() -> Box<dyn Auth> {
let privkey = Generator::random_privkey();
Box::new(BitcoinAuth {
privkey,
compress: true,
v_type: BitcoinSignVType::default(),
})
}
}
impl Auth for EosAuth {
fn get_pub_key_hash(&self) -> Vec<u8> {
let pub_key = self.privkey.pubkey().expect("pubkey");
let pub_key_vec: Vec<u8>;
if self.compress {
pub_key_vec = pub_key.serialize();
} else {
let mut temp: BytesMut = BytesMut::with_capacity(65);
temp.put_u8(4);
temp.put(Bytes::from(pub_key.as_bytes().to_vec()));
pub_key_vec = temp.freeze().to_vec();
}
let pub_key_vec: Vec<u8> = match self.v_type {
BitcoinSignVType::P2PKHUncompressed => {
let mut temp: BytesMut = BytesMut::with_capacity(65);
temp.put_u8(4);
temp.put(Bytes::from(pub_key.as_bytes().to_vec()));
temp.freeze().to_vec()
}
BitcoinSignVType::P2PKHCompressed => pub_key.serialize(),
_ => {
panic!("Unsupport")
}
};

ckb_hash::blake2b_256(pub_key_vec)[..20].to_vec()
}
Expand All @@ -936,7 +939,7 @@ impl Auth for EosAuth {
H256::from(message.clone())
}
fn sign(&self, msg: &H256) -> Bytes {
BitcoinAuth::btc_sign(msg, &self.privkey, self.compress)
BitcoinAuth::btc_sign(msg, &self.privkey, self.v_type)
}
}

Expand Down Expand Up @@ -973,30 +976,46 @@ impl Auth for TronAuth {
}
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum BitcoinSignVType {
P2PKHUncompressed,
P2PKHCompressed,
SegwitP2SH,
SegwitBech32,
}
impl Default for BitcoinSignVType {
fn default() -> Self {
Self::P2PKHCompressed
}
}

#[derive(Clone)]
pub struct BitcoinAuth {
pub privkey: Privkey,
pub compress: bool,
pub v_type: BitcoinSignVType,
}
impl BitcoinAuth {
pub fn new() -> Box<BitcoinAuth> {
let privkey = Generator::random_privkey();
Box::new(BitcoinAuth {
privkey,
compress: true,
v_type: BitcoinSignVType::default(),
})
}
pub fn get_btc_pub_key_hash(privkey: &Privkey, compress: bool) -> Vec<u8> {
pub fn get_btc_pub_key_hash(privkey: &Privkey, v_type: BitcoinSignVType) -> Vec<u8> {
let pub_key = privkey.pubkey().expect("pubkey");
let pub_key_vec: Vec<u8>;
if compress {
pub_key_vec = pub_key.serialize();
} else {
let mut temp: BytesMut = BytesMut::with_capacity(65);
temp.put_u8(4);
temp.put(Bytes::from(pub_key.as_bytes().to_vec()));
pub_key_vec = temp.freeze().to_vec();
}
let pub_key_vec: Vec<u8> = match v_type {
BitcoinSignVType::P2PKHUncompressed => {
let mut temp: BytesMut = BytesMut::with_capacity(65);
temp.put_u8(4);
temp.put(Bytes::from(pub_key.as_bytes().to_vec()));
temp.freeze().to_vec()
}
BitcoinSignVType::P2PKHCompressed => pub_key.serialize(),
_ => {
panic!("Unsupport")
}
};

let pub_hash = calculate_sha256(&pub_key_vec);

Expand All @@ -1017,17 +1036,18 @@ impl BitcoinAuth {

H256::from(msg)
}
pub fn btc_sign(msg: &H256, privkey: &Privkey, compress: bool) -> Bytes {
pub fn btc_sign(msg: &H256, privkey: &Privkey, v_type: BitcoinSignVType) -> Bytes {
let sign = privkey.sign_recoverable(&msg).expect("sign").serialize();
assert_eq!(sign.len(), 65);
let recid = sign[64];

let mark: u8;
if compress {
mark = recid + 31;
} else {
mark = recid + 27;
let mark = match v_type {
BitcoinSignVType::P2PKHUncompressed => recid + 27,
BitcoinSignVType::P2PKHCompressed => recid + 31,
BitcoinSignVType::SegwitP2SH => recid + 35,
BitcoinSignVType::SegwitBech32 => recid + 39,
};

let mut ret = BytesMut::with_capacity(65);
ret.put_u8(mark);
ret.put(&sign[0..64]);
Expand All @@ -1036,7 +1056,7 @@ impl BitcoinAuth {
}
impl Auth for BitcoinAuth {
fn get_pub_key_hash(&self) -> Vec<u8> {
BitcoinAuth::get_btc_pub_key_hash(&self.privkey, self.compress)
BitcoinAuth::get_btc_pub_key_hash(&self.privkey, self.v_type)
}
fn get_algorithm_type(&self) -> u8 {
AlgorithmType::Bitcoin as u8
Expand All @@ -1045,27 +1065,27 @@ impl Auth for BitcoinAuth {
BitcoinAuth::btc_convert_message(message)
}
fn sign(&self, msg: &H256) -> Bytes {
BitcoinAuth::btc_sign(msg, &self.privkey, self.compress)
BitcoinAuth::btc_sign(msg, &self.privkey, self.v_type)
}
}

#[derive(Clone)]
pub struct DogecoinAuth {
pub privkey: Privkey,
pub compress: bool,
pub v_type: BitcoinSignVType,
}
impl DogecoinAuth {
pub fn new() -> Box<DogecoinAuth> {
let privkey = Generator::random_privkey();
Box::new(DogecoinAuth {
privkey,
compress: true,
v_type: BitcoinSignVType::default(),
})
}
}
impl Auth for DogecoinAuth {
fn get_pub_key_hash(&self) -> Vec<u8> {
BitcoinAuth::get_btc_pub_key_hash(&self.privkey, self.compress)
BitcoinAuth::get_btc_pub_key_hash(&self.privkey, self.v_type)
}
fn get_algorithm_type(&self) -> u8 {
AlgorithmType::Dogecoin as u8
Expand All @@ -1085,7 +1105,7 @@ impl Auth for DogecoinAuth {
H256::from(msg)
}
fn sign(&self, msg: &H256) -> Bytes {
BitcoinAuth::btc_sign(msg, &self.privkey, self.compress)
BitcoinAuth::btc_sign(msg, &self.privkey, self.v_type)
}
}

Expand All @@ -1095,7 +1115,7 @@ pub struct LitecoinAuth {
pub official: bool,
// Use raw [u8; 32] to easily convert this into Privkey and SecretKey
pub sk: [u8; 32],
pub compress: bool,
pub v_type: BitcoinSignVType,
pub network: bitcoin::Network,
}
impl LitecoinAuth {
Expand All @@ -1104,7 +1124,7 @@ impl LitecoinAuth {
Box::new(LitecoinAuth {
official: false,
sk,
compress: true,
v_type: BitcoinSignVType::default(),
network: bitcoin::Network::Testnet,
})
}
Expand All @@ -1123,7 +1143,7 @@ impl LitecoinAuth {
}
impl Auth for LitecoinAuth {
fn get_pub_key_hash(&self) -> Vec<u8> {
let hash = BitcoinAuth::get_btc_pub_key_hash(&self.get_privkey(), self.compress);
let hash = BitcoinAuth::get_btc_pub_key_hash(&self.get_privkey(), self.v_type);
hash
}
fn get_algorithm_type(&self) -> u8 {
Expand All @@ -1148,7 +1168,7 @@ impl Auth for LitecoinAuth {
}
fn sign(&self, msg: &H256) -> Bytes {
if !self.official {
return BitcoinAuth::btc_sign(msg, &self.get_privkey(), self.compress);
return BitcoinAuth::btc_sign(msg, &self.get_privkey(), self.v_type.clone());
}
let daemon = LitecoinDaemon::new();
let wallet_name = "ckb-auth-test-wallet";
Expand Down
50 changes: 31 additions & 19 deletions tests/auth_rust/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ use hex_literal::hex;
use crate::{
assert_script_error, auth_builder, auth_program::use_libecc, build_resolved_tx, debug_printer,
gen_args, gen_tx, gen_tx_scripts_verifier, gen_tx_with_grouped_args, sign_tx, AlgorithmType,
Auth, AuthErrorCodeType, BitcoinAuth, CKbAuth, CkbMultisigAuth, DogecoinAuth, DummyDataLoader,
EntryCategoryType, EosAuth, EthereumAuth, LitecoinAuth, SchnorrAuth, TestConfig, TronAuth,
MAX_CYCLES,
Auth, AuthErrorCodeType, BitcoinAuth, BitcoinSignVType, CKbAuth, CkbMultisigAuth, DogecoinAuth,
DummyDataLoader, EntryCategoryType, EosAuth, EthereumAuth, LitecoinAuth, SchnorrAuth,
TestConfig, TronAuth, MAX_CYCLES,
};

fn verify_unit(config: &TestConfig) -> Result<u64, ckb_error::Error> {
Expand Down Expand Up @@ -170,6 +170,11 @@ fn unit_test_common_with_runtype(
unit_test_common_with_auth(&auth, run_type);
}

fn unit_test_common_all_runtype(auth: &Box<dyn Auth>) {
unit_test_common_with_auth(auth, EntryCategoryType::DynamicLinking);
unit_test_common_with_auth(auth, EntryCategoryType::Spawn);
}

fn unit_test_common(algorithm_type: AlgorithmType) {
for t in [EntryCategoryType::DynamicLinking, EntryCategoryType::Spawn] {
unit_test_common_with_runtype(algorithm_type, t, false);
Expand Down Expand Up @@ -208,12 +213,11 @@ fn bitcoin_verify() {
}

#[test]
fn bitcoin_uncompress_verify() {
fn bitcoin_v_type_verify() {
let mut auth = crate::BitcoinAuth::new();
auth.compress = false;
auth.v_type = BitcoinSignVType::P2PKHUncompressed;
let auth: Box<dyn Auth> = auth;
unit_test_common_with_auth(&auth, EntryCategoryType::DynamicLinking);
unit_test_common_with_auth(&auth, EntryCategoryType::Spawn);
unit_test_common_all_runtype(&auth);
}

#[test]
Expand All @@ -222,7 +226,7 @@ fn bitcoin_pubkey_recid_verify() {
pub struct BitcoinFailedAuth(BitcoinAuth);
impl Auth for BitcoinFailedAuth {
fn get_pub_key_hash(&self) -> Vec<u8> {
BitcoinAuth::get_btc_pub_key_hash(&self.0.privkey, self.0.compress)
BitcoinAuth::get_btc_pub_key_hash(&self.0.privkey, self.0.v_type)
}
fn get_algorithm_type(&self) -> u8 {
AlgorithmType::Bitcoin as u8
Expand All @@ -245,7 +249,7 @@ fn bitcoin_pubkey_recid_verify() {
recid = rng.gen_range(0, 4);
}
let mut mark: u8 = sign[64];
if self.0.compress {
if self.0.v_type == BitcoinSignVType::P2PKHCompressed {
mark = mark | 4;
}
let mut ret = BytesMut::with_capacity(65);
Expand All @@ -259,7 +263,7 @@ fn bitcoin_pubkey_recid_verify() {
let auth: Box<dyn Auth> = Box::new(BitcoinFailedAuth {
0: BitcoinAuth {
privkey,
compress: true,
v_type: BitcoinSignVType::default(),
},
});

Expand Down Expand Up @@ -400,7 +404,7 @@ fn convert_btc_error() {
struct BtcConverFaileAuth(BitcoinAuth);
impl Auth for BtcConverFaileAuth {
fn get_pub_key_hash(&self) -> Vec<u8> {
BitcoinAuth::get_btc_pub_key_hash(&self.0.privkey, self.0.compress)
BitcoinAuth::get_btc_pub_key_hash(&self.0.privkey, self.0.v_type)
}
fn get_algorithm_type(&self) -> u8 {
AlgorithmType::Bitcoin as u8
Expand All @@ -420,15 +424,15 @@ fn convert_btc_error() {
H256::from(msg)
}
fn sign(&self, msg: &H256) -> Bytes {
BitcoinAuth::btc_sign(msg, &self.0.privkey, self.0.compress)
BitcoinAuth::btc_sign(msg, &self.0.privkey, self.0.v_type)
}
}

let privkey = Generator::random_privkey();
let auth: Box<dyn Auth> = Box::new(BtcConverFaileAuth {
0: BitcoinAuth {
privkey,
compress: true,
v_type: BitcoinSignVType::default(),
},
});

Expand All @@ -449,7 +453,7 @@ fn convert_doge_error() {
struct DogeConverFaileAuth(DogecoinAuth);
impl Auth for DogeConverFaileAuth {
fn get_pub_key_hash(&self) -> Vec<u8> {
BitcoinAuth::get_btc_pub_key_hash(&self.0.privkey, self.0.compress)
BitcoinAuth::get_btc_pub_key_hash(&self.0.privkey, self.0.v_type)
}
fn get_algorithm_type(&self) -> u8 {
AlgorithmType::Bitcoin as u8
Expand All @@ -469,15 +473,15 @@ fn convert_doge_error() {
H256::from(msg)
}
fn sign(&self, msg: &H256) -> Bytes {
BitcoinAuth::btc_sign(msg, &self.0.privkey, self.0.compress)
BitcoinAuth::btc_sign(msg, &self.0.privkey, self.0.v_type)
}
}

let privkey = Generator::random_privkey();
let auth: Box<dyn Auth> = Box::new(DogeConverFaileAuth {
0: DogecoinAuth {
privkey,
compress: true,
v_type: BitcoinSignVType::default(),
},
});

Expand All @@ -498,7 +502,7 @@ fn convert_lite_error() {
struct LiteConverFaileAuth(LitecoinAuth);
impl Auth for LiteConverFaileAuth {
fn get_pub_key_hash(&self) -> Vec<u8> {
BitcoinAuth::get_btc_pub_key_hash(&self.0.get_privkey(), self.0.compress)
BitcoinAuth::get_btc_pub_key_hash(&self.0.get_privkey(), self.0.v_type)
}
fn get_algorithm_type(&self) -> u8 {
AlgorithmType::Bitcoin as u8
Expand All @@ -518,7 +522,7 @@ fn convert_lite_error() {
H256::from(msg)
}
fn sign(&self, msg: &H256) -> Bytes {
BitcoinAuth::btc_sign(msg, &self.0.get_privkey(), self.0.compress)
BitcoinAuth::btc_sign(msg, &self.0.get_privkey(), self.0.v_type)
}
}

Expand All @@ -527,7 +531,7 @@ fn convert_lite_error() {
0: LitecoinAuth {
official: false,
sk,
compress: true,
v_type: BitcoinSignVType::default(),
network: bitcoin::Network::Testnet,
},
});
Expand Down Expand Up @@ -698,3 +702,11 @@ fn abnormal_algorithm_type() {
);
}
}

#[test]
fn ethereum_recid() {
// TODO
let auth = crate::EthereumAuth::new();
let auth: Box<dyn Auth> = auth;
unit_test_common_all_runtype(&auth);
}

0 comments on commit 81d6505

Please sign in to comment.