Skip to content

Commit

Permalink
verify slashed btc del
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianElvis committed Sep 12, 2024
1 parent 372487f commit e583df0
Show file tree
Hide file tree
Showing 39 changed files with 194 additions and 158 deletions.
9 changes: 7 additions & 2 deletions contracts/btc-staking/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,10 @@ pub(crate) mod tests {
};
use cw_controllers::AdminResponse;
use hex::ToHex;
use k256::schnorr::Signature;
use k256::schnorr::{Signature, SigningKey};
use test_utils::{
get_btc_del_unbonding_sig_bytes, get_btc_delegation, get_finality_provider,
get_pub_rand_commit,
get_fp_sk_bytes, get_pub_rand_commit,
};

pub(crate) const CREATOR: &str = "creator";
Expand Down Expand Up @@ -432,6 +432,11 @@ pub(crate) mod tests {
new_finality_provider(fp)
}

pub(crate) fn create_new_fp_sk(id: i32) -> SigningKey {
let fp_sk_bytes = get_fp_sk_bytes(id);
SigningKey::from_bytes(&fp_sk_bytes).unwrap()
}

#[test]
fn instantiate_without_admin() {
let mut deps = mock_dependencies();
Expand Down
2 changes: 1 addition & 1 deletion contracts/btc-staking/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ mod tests {
use cosmwasm_std::testing::message_info;
use cosmwasm_std::testing::{mock_dependencies, mock_env};
use cosmwasm_std::StdError::NotFound;
use cosmwasm_std::{from_json, Binary, Storage};
use cosmwasm_std::{from_json, Storage};

use babylon_apis::btc_staking_api::{FinalityProvider, UnbondedBtcDelegation};

Expand Down
23 changes: 11 additions & 12 deletions contracts/btc-staking/src/staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,8 @@ fn handle_slashed_delegation(
}

// verify the slashed delegation (full or lite)
verify_slashed_delegation(height, delegation)?;
let recovered_fp_sk_hex = delegation.recovered_fp_btc_sk.clone();
verify_slashed_delegation(&btc_del, recovered_fp_sk_hex)?;

// Discount the voting power from the affected finality providers
let affected_fps = DELEGATION_FPS.load(storage, staking_tx_hash.as_ref())?;
Expand Down Expand Up @@ -416,13 +417,12 @@ pub(crate) fn slash_finality_provider(
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use cosmwasm_std::Binary;

use cosmwasm_std::testing::{message_info, mock_dependencies, mock_env};

use crate::contract::tests::{
create_new_finality_provider, get_active_btc_delegation, get_btc_del_unbonding_sig,
get_derived_btc_delegation, get_params, CREATOR, INIT_ADMIN,
create_new_finality_provider, create_new_fp_sk, get_active_btc_delegation,
get_btc_del_unbonding_sig, get_derived_btc_delegation, get_params, CREATOR, INIT_ADMIN,
};
use crate::contract::{execute, instantiate};
use crate::msg::{ExecuteMsg, InstantiateMsg};
Expand Down Expand Up @@ -696,14 +696,11 @@ pub(crate) mod tests {
let params = get_params();
PARAMS.save(deps.as_mut().storage, &params).unwrap();

// Build valid active delegation
let active_delegation = get_active_btc_delegation();

// Register one FP first
let mut new_fp = create_new_finality_provider(1);
new_fp
.btc_pk_hex
.clone_from(&active_delegation.fp_btc_pk_list[0]);
let new_fp = create_new_finality_provider(1);

// Build valid active delegation
let active_delegation = get_derived_btc_delegation(1, &[1]);

let msg = ExecuteMsg::BtcStaking {
new_fp: vec![new_fp.clone()],
Expand All @@ -730,9 +727,11 @@ pub(crate) mod tests {
assert_eq!(fp.power, btc_del.total_sat);

// Now send the slashed delegation message
let fp_sk = create_new_fp_sk(1);
let fp_sk_hex = hex::encode(fp_sk.to_bytes());
let slashed = SlashedBtcDelegation {
staking_tx_hash: staking_tx_hash_hex.clone(),
recovered_fp_btc_sk: "deadbeef".to_string(), // Currently unused
recovered_fp_btc_sk: fp_sk_hex,
};

let msg = ExecuteMsg::BtcStaking {
Expand Down
36 changes: 27 additions & 9 deletions contracts/btc-staking/src/validation/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use crate::state::config::Params;
use crate::{error::ContractError, state::staking::BtcDelegation};
use babylon_apis::btc_staking_api::{
ActiveBtcDelegation, NewFinalityProvider, SlashedBtcDelegation, UnbondedBtcDelegation,
};
use babylon_apis::btc_staking_api::{ActiveBtcDelegation, NewFinalityProvider};
use bitcoin::Transaction;
use cosmwasm_std::Binary;

Expand All @@ -13,7 +11,7 @@ use {
bitcoin::{consensus::deserialize, Address},
cosmwasm_std::CanonicalAddr,
hex::ToHex,
k256::schnorr::{Signature, VerifyingKey},
k256::schnorr::{Signature, SigningKey, VerifyingKey},
k256::sha2::{Digest, Sha256},
std::str::FromStr,
};
Expand Down Expand Up @@ -269,7 +267,9 @@ pub fn verify_undelegation(
// TODO: fix contract size when full-validation is enabled
#[cfg(feature = "full-validation")]
{
// TODO: Verify the signature on the unbonding tx is from the delegator
/*
Verify the signature on the unbonding tx is from the delegator
*/

// get keys
let (staker_pk, fp_pks, cov_pks) = get_pks(
Expand Down Expand Up @@ -315,14 +315,14 @@ pub fn verify_undelegation(

// make static analyser happy with unused parameters
#[cfg(not(feature = "full-validation"))]
let _ = (height, undelegation);
let _ = (params, btc_del, sig);

Ok(())
}

pub fn verify_slashed_delegation(
height: u64,
delegation: &SlashedBtcDelegation,
active_delegation: &BtcDelegation,
slashed_fp_sk_hex: String,
) -> Result<(), ContractError> {
// The following code is marked with `#[cfg(feature = "full-validation")]`
// so that it is included in the build if the `full-validation` feature is
Expand All @@ -331,11 +331,29 @@ pub fn verify_slashed_delegation(
#[cfg(feature = "full-validation")]
{
// TODO: check if the SK corresponds to a FP PK that the delegation restakes to

// get the slashed FP's SK
let slashed_fp_sk = hex::decode(&slashed_fp_sk_hex)
.map_err(|e| ContractError::SecP256K1Error(e.to_string()))?;
let slashed_fp_sk = SigningKey::from_bytes(&slashed_fp_sk)
.map_err(|e| ContractError::SecP256K1Error(e.to_string()))?;

// calculate the corresponding VerifyingKey
let slashed_fp_pk = slashed_fp_sk.verifying_key();
let slashed_fp_pk_hex = hex::encode(slashed_fp_pk.to_bytes());

// check if the PK corresponds to a FP PK that the delegation restakes to
if !active_delegation
.fp_btc_pk_list
.contains(&slashed_fp_pk_hex)
{
return Err(ContractError::FinalityProviderNotRegistered);
}
}

// make static analyser happy with unused parameters
#[cfg(not(feature = "full-validation"))]
let _ = (height, delegation);
let _ = (active_delegation, slashed_fp_sk_hex);

Ok(())
}
8 changes: 8 additions & 0 deletions datagen/utils/btcstaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

const (
FP_FILENAME = "finality_provider_%d.dat"
FP_SK_FILENAME = "fp_sk_%d.dat"
BTC_DEL_FILENAME = "btc_delegation_%d_{%s}.dat"
BTC_DEL_UNBONDING_SIG_FILENAME = "btc_unbonding_sig_%d_{%s}.dat"
BTCSTAKING_PARAMS_FILENAME = "btcstaking_params.dat"
Expand Down Expand Up @@ -89,6 +90,13 @@ func GenFinalityProviders(dir string, numFPs int) {
fpPath := filepath.Join(dir, fileName)
err = os.WriteFile(fpPath, fpBytes, 0644)
require.NoError(t, err)

// write FP's BTC SK to file
fpSKBytes := fpBTCSK.Serialize()
fileName = fmt.Sprintf(FP_SK_FILENAME, i)
fpSKPath := filepath.Join(dir, fileName)
err = os.WriteFile(fpSKPath, fpSKBytes, 0644)
require.NoError(t, err)
}
}

Expand Down
7 changes: 7 additions & 0 deletions packages/test-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const BTC_TIMESTAMP_HEADER1: &str = "btc_timestamp_header1.dat";

const PARAMS_DATA: &str = "btcstaking_params.dat";
const FINALITY_PROVIDER_DATA: &str = "finality_provider_{}.dat";
const FP_SK_DATA: &str = "fp_sk_{}.dat";
const BTC_DELEGATION_DATA: &str = "btc_delegation_{idx}_{fp_idx_list}.dat";
const BTC_DEL_UNBONDING_SIG_DATA: &str = "btc_unbonding_sig_{idx}_{fp_idx_list}.dat";
const COMMIT_PUB_RAND_DATA: &str = "commit_pub_rand_msg.dat";
Expand Down Expand Up @@ -154,6 +155,12 @@ pub fn get_finality_provider(id: i32) -> FinalityProvider {
FinalityProvider::decode(fp_data).unwrap()
}

pub fn get_fp_sk_bytes(id: i32) -> Vec<u8> {
let fp_sk_path = find_testdata_path().join(FP_SK_DATA.replace("{}", &id.to_string()));
let fp_sk_data: &[u8] = &fs::read(fp_sk_path).unwrap();
fp_sk_data.to_vec()
}

pub fn get_btc_delegation(idx: i32, fp_idx_list: Vec<i32>) -> BtcDelegation {
let fp_idx_list_str = format!(
"{{{}}}",
Expand Down
6 changes: 2 additions & 4 deletions packages/test-utils/testdata/add_finality_sig_1_msg.dat
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@

*bbn1ezu88z9qu0fq7rjtqpk22sw4qq2hu98qxw8kqr
�k
k����> �c�{����[�rB��Ne" ��vMU��j�g��3?�uki�D�#I�_�V�*�
 �����\s3�DC��p�):U�4I��" G�>�W�4�'�Nd�)e��>�զA�d��/E" ��Q�R~���(�F۾{���K�i��y1s" 𳝴�[�>(�D���{[�'�G���.�+pM=" n�h2�#�%�Fz�]C;���I_�(aG�=�2 _l�Ưq[A�� �" ef����x{�)��: �����RQ�IX�=ӳ���k�͹Rn?e]L��
*bbn1rggrk4pamnrhfekez578gulthsaxfkhy9f6hm5 Fha��D�)��TE�?���dSiȎ�?%�xGg&e" ݤ������a��b���_�]��,/2��B�*�
 � ��!%���+�h�w�KX���nK/�݉z�" h:X&��uhH:���M6kb�<�\U�D�SN��Z" \uNJ���%V#"���И�^c�#��>�0" ��J%�|MqJ�g���1�����ҝ�*/!��8" �z�����j�=�Hn���b,u���I:2 I��VXp�q^ ԂY�ot�7y[i:�b<uY#�: 6F�첟x��윦��Y�Sw��G�/���>
Expand Down
6 changes: 2 additions & 4 deletions packages/test-utils/testdata/add_finality_sig_2_msg.dat
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@

*bbn1tlwp2ppp0ket9uh8lj7czzfsll9hkwcfjzqj8v
�k
k����> �c�{����[�rB��Ne" ��vMU��j�g��3?�uki�D�#I�_�V�*�
 �����\s3�DC��p�):U�4I��" G�>�W�4�'�Nd�)e��>�զA�d��/E" ��Q�R~���(�F۾{���K�i��y1s" 𳝴�[�>(�D���{[�'�G���.�+pM=" n�h2�#�%�Fz�]C;���I_�(aG�=�2 �2���i��}��]� )�RLn��������z: �m��Z�������i��z�Yc�t[;��D��X
*bbn1e22tjgpyuhwh0fqcqqpxpjwkywej02wcf7qut4 Fha��D�)��TE�?���dSiȎ�?%�xGg&e" ݤ������a��b���_�]��,/2��B�*�
 � ��!%���+�h�w�KX���nK/�݉z�" h:X&��uhH:���M6kb�<�\U�D�SN��Z" \uNJ���%V#"���И�^c�#��>�0" ��J%�|MqJ�g���1�����ҝ�*/!��8" �z�����j�=�Hn���b,u���I:2 � 2-9�k�`�1wA�|�_�c}(�Ő����: ���Vn���X�� Л�Y�le�%���3M�)����
Expand Down
Binary file modified packages/test-utils/testdata/btc_delegation_1_{1,3}.dat
Binary file not shown.
Binary file modified packages/test-utils/testdata/btc_delegation_1_{1}.dat
Binary file not shown.
Binary file modified packages/test-utils/testdata/btc_delegation_1_{2}.dat
Binary file not shown.
Binary file modified packages/test-utils/testdata/btc_delegation_2_{1}.dat
Binary file not shown.
Binary file modified packages/test-utils/testdata/btc_delegation_2_{2}.dat
Binary file not shown.
Binary file modified packages/test-utils/testdata/btc_delegation_3_{1}.dat
Binary file not shown.
Binary file modified packages/test-utils/testdata/btc_delegation_3_{2}.dat
Binary file not shown.
Loading

0 comments on commit e583df0

Please sign in to comment.