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

πŸ—οΈ Implement operator and comittee behavior with singing of all transactions #28

Open
wants to merge 9 commits into
base: main
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
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ members = [
"bitcoin-winternitz",
"bitcoin-scriptexec",
"bitcoin-testscripts",
"core",
"nero-core",
"bitcoin-utils",
"nero-cli",
# "nero-cli",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove if not needed

]
resolver = "2"

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Compile `nero-cli`:
```shell
cargo install --path ./nero-cli
```

Generate random pair of keys for payout path spending:

```shell
Expand Down
4 changes: 2 additions & 2 deletions bitcoin-splitter/src/split/intermediate_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ impl IntermediateState {

/// Creates a new instance of the IntermediateState based on the given
/// script and the stack and altstack after the execution of the script
pub fn from_inject_script(inject_script: &Script) -> Self {
let result = execute_script(inject_script.clone());
pub fn from_inject_script(inject_script: Script) -> Self {
let result = execute_script(inject_script);

Self {
stack: result.main_stack.clone(),
Expand Down
2 changes: 1 addition & 1 deletion bitcoin-testscripts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ bitcoin = { workspace = true, features = ["rand-std"]}
bitcoin-script = { git = "https://github.com/BitVM/rust-bitcoin-script" }

# BitVM scripts
bitcoin-window-mul = { git = "https://github.com/distributed-lab/bitcoin-window-mul.git" }
bitcoin-window-mul = { workspace = true }
# bitcoin-window-mul = { path = "../../../alpen/bitcoin-window-mul" }
bitcoin-splitter = { path = "../bitcoin-splitter" }
bitcoin-utils = { path = "../bitcoin-utils" }
Expand Down
6 changes: 5 additions & 1 deletion bitcoin-utils/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ impl fmt::Display for ExecuteInfo {
/// Executes the given script and returns the result of the execution
/// (success, error, stack, etc.)
pub fn execute_script(script: ScriptBuf) -> ExecuteInfo {
execute_script_with_leaf(script, TapLeafHash::all_zeros())
}

pub fn execute_script_with_leaf(script: ScriptBuf, leaf_hash: TapLeafHash) -> ExecuteInfo {
let mut exec = Exec::new(
ExecCtx::Tapscript,
Options {
Expand All @@ -63,7 +67,7 @@ pub fn execute_script(script: ScriptBuf) -> ExecuteInfo {
},
prevouts: vec![],
input_idx: 0,
taproot_annex_scriptleaf: Some((TapLeafHash::all_zeros(), None)),
taproot_annex_scriptleaf: Some((leaf_hash, None)),
},
script,
vec![],
Expand Down
43 changes: 43 additions & 0 deletions bitcoin-utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
use bitcoin::{
key::{Keypair, Parity, Secp256k1},
secp256k1::{All, SecretKey},
sighash::{Prevouts, SighashCache},
taproot::{LeafVersion, Signature},
TapLeafHash, TapSighashType, Transaction, TxOut,
};
use bitcoin_scriptexec::Stack;
use treepp::*;

Expand All @@ -23,3 +30,39 @@ pub fn stack_to_script(stack: &Stack) -> Script {
}
}
}

pub fn comittee_signature(
disprove_script: &Script,
secp_ctx: &Secp256k1<All>,
mut seckey: SecretKey,
) -> Signature {
let tx = Transaction {
version: bitcoin::transaction::Version::TWO,
lock_time: bitcoin::locktime::absolute::LockTime::ZERO,
input: vec![],
output: vec![],
};

let sighash = SighashCache::new(tx)
.taproot_script_spend_signature_hash(
0,
&Prevouts::<&TxOut>::All(&[]),
TapLeafHash::from_script(disprove_script, LeafVersion::TapScript),
TapSighashType::All,
)
.unwrap();

if seckey.public_key(secp_ctx).x_only_public_key().1 == Parity::Even {
seckey = seckey.negate();
}

let signature = secp_ctx.sign_schnorr(
&sighash.into(),
&Keypair::from_secret_key(secp_ctx, &seckey),
);

Signature {
signature,
sighash_type: TapSighashType::All,
}
}
46 changes: 42 additions & 4 deletions bitcoin-winternitz/src/u32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub const N: usize = N0 + N1;

/// Secret key is array of $N$ chunks by $D$ bits, where the whole number
/// of bits is equal to $v$.
#[derive(Clone, Debug, Copy)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct SecretKey([Hash160; N]);

impl SecretKey {
Expand Down Expand Up @@ -94,7 +94,7 @@ impl SecretKey {

/// Public key is a hashed $D$ times each of the $n$ parts of the
/// [`SecretKey`].
#[derive(Clone, Copy, Debug)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct PublicKey([Hash160; N]);

impl PublicKey {
Expand All @@ -121,9 +121,15 @@ impl PublicKey {
let skip = msg.count_zero_limbs_from_left();
checksig_verify_script_compact(skip, self)
}

/// Construct `script_pubkey` signature verification which uses
/// full encoding.
pub fn checksig_verify_script(&self) -> Script {
checksig_verify_script(self)
}
}

#[derive(Clone, Copy, Debug, Default)]
#[derive(Debug, Clone, Hash, PartialEq, Eq, Default, Copy)]
pub struct Message([u8; N]);

impl Message {
Expand Down Expand Up @@ -243,7 +249,7 @@ impl Message {
}

/// Winternitz signature. The array of intermidiate hashes of secret key.
#[derive(Clone, Copy, Debug)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Signature {
sig: [Hash160; N],
msg: Message,
Expand All @@ -256,6 +262,38 @@ impl Signature {
self.to_script_sig_skipping(0)
}

/// The same as [`Signature::to_script_sig`], but converts signature to
/// witness stack elements instead of script.
pub fn to_witness_stack_elements(self) -> Vec<Vec<u8>> {
self.to_witness_stack_elements_skipping(0)
}

fn to_witness_stack_elements_skipping(self, skipping: usize) -> Vec<Vec<u8>> {
let mut elements = Vec::new();

// TODO(Velnbur): later let's move it somewhere else
fn push_element(idx: usize, elements: &mut Vec<Vec<u8>>, sig: &Signature) {
elements.push(sig.sig[idx].to_byte_array().to_vec());
let msg_byte = sig.msg.0[idx];
if msg_byte == 0 {
elements.push(Vec::new());
} else {
elements.push(msg_byte.to_le_bytes().to_vec());
}
}

// Keep all the elements of the checksum.
for idx in (N0..(N0 + N1)).rev() {
push_element(idx, &mut elements, &self);
}
// Push the stack element limbs skipping some of them.
for idx in (0..N0).rev().skip(skipping) {
push_element(idx, &mut elements, &self);
}

elements
}

/// The same as [`Self::to_script_sig`], but skips `skipping` number of
/// limbs and sigs for zero limbs.
fn to_script_sig_skipping(self, skipping: usize) -> Script {
Expand Down
Loading
Loading