1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
b0VIM 8.2 �f�, tom parksr-ThinkPad-T14-Gen-2i ~tom/compressed_transactions/src/compressed_transaction.rs utf-8
U3210 #"! U tp H
* R m 5 � � J � T
} � ] ] ad | � � v K � l Z M 7 �
�
�
�
�
w
u
t
Z
� � � � � � � � p 7 � � � � � 5 / . �
�
q
U
,
"
� � � � � � � w > � � � � � � � k i h R � � � � : � � � R � � � J � � � C � � � � W � � � � � � q p I � � � VarInt::from(txin.script_sig.len() as u64).consensus_encode(&mut signature)?; if !compressed_signature { } _ => {} }, //let signature: Signature = Signature::from_der(signature_der)?; let signature_der: Vec<u8> = txin.witness.to_vec()[0].clone(); script if script.is_p2wpkh() => { }, } compressed_signature = true; } is_hash_standard = hash_type == 0x00; hash_type = signature.pop().unwrap(); if signature.len() == 65 { signature = stack[0].clone(); if stack.len() == 1 && (stack[0].len() == 64 || stack[0].len() == 65) { let stack = txin.witness.to_vec(); script if script.is_p2tr() => { match &input.script_pubkey { if txin.script_sig.len() > 0 || !txin.witness.is_empty() { let mut compressed_signature: bool = false; let mut is_hash_standard: bool = true; let mut hash_type: u8 = 0; let mut pubkey_hash: Vec<u8> = vec![]; let mut signature: Vec<u8> = vec![]; let outpoint: Option<OutPoint> = input.outpoint; let compressed_outpoint: Option<CompressedOutPoint> = input.compressed_outpoint.clone(); pub fn compress(txin: &TxIn, input: &CompressedInput) -> Result<Self, Error> { } self.compressed_outpoint.is_some() pub fn outpoint_is_compressed(&self) -> bool{ impl CompressedTxIn { } pub sequence: u32, pub compressed_signature: bool, pub is_hash_standard: bool, pub hash_type: u8, pub pubkey_hash: Vec<u8>, pub signature: Vec<u8>, pub outpoint: Option<OutPoint>, pub compressed_outpoint: Option<CompressedOutPoint>, pub struct CompressedTxIn { #[non_exhaustive] #[derive(Debug, Clone)] } } self.compressed_outpoint.is_some() pub fn is_compressed(&self) -> bool { } } script_pubkey: script_pubkey outpoint: None, compressed_outpoint: Some(compressed_outpoint), CompressedInput { pub fn new_compressed(compressed_outpoint: CompressedOutPoint, script_pubkey: ScriptBuf) -> Self { } CompressedInput{compressed_outpoint: None, outpoint: Some(outpoint), script_pubkey} pub fn new(outpoint: OutPoint, script_pubkey: ScriptBuf) -> Self { impl CompressedInput { } pub script_pubkey: ScriptBuf pub outpoint: Option<OutPoint>, pub compressed_outpoint: Option<CompressedOutPoint>, pub struct CompressedInput { #[non_exhaustive] #[derive(Debug, Clone)] } } CompressedOutPoint{block_height, pub fn block_index(&self) -> u32 {self.block_index} pub fn block_height(&self) -> u32 {self.block_height} impl CompressedOutPoint { } block_index: u32, block_height: u32, pub struct CompressedOutPoint { #[derive(Debug, Clone, PartialEq)] use crate::{encode_varint, decode_varint}; use bitcoin::sighash::SighashCache; use std::io::BufRead; use std::io; use crate::Error; use bitcoin::consensus::{Decodable, Encodable, encode}; use bitcoin::blockdata::opcodes::all::{OP_PUSHBYTES_65, OP_PUSHBYTES_33, OP_PUSHBYTES_32, OP_PUSHBYTES_20, OP_DUP, OP_HASH160, OP_EQUAL, OP_EQUALVERIFY, OP_CHECKSIG}; use bitcoin::absolute::{LockTime, Height}; use bitcoin::transaction::Version; use bitcoin::{Txid, TxIn, ScriptBuf, OutPoint, Transaction, TxOut, Amount, VarInt, Sequence, Witness}; ad � 4 � � � � � < 6 4 � Q � � } } Ok(CompressedTransaction{version, input, output, lock_} } Ok(CompressedTransaction{version, input, output, lock_time, minimum_height}) let mut output: Vec<CompressedTxOut> = vec![]; let mut input: Vec<CompressedTxIn> = vec![]; ad � T � R � S �
�
P
O
� � V < & � � � � � = 3 + �
�
e
d
C
� � � � � a � Z � � � � b - # � � � � S R : $ � � y K # � � � � l 8 * � z h U � � � � � � � � let version: i32 = if (control l let bits_index: usize if i >= bits.len() { bits.len()-1 } else { i }; for (i, d) in data.iter().enume let bits_in let bits_i let bits_index: usize if i >= bits.len() { bits.len() let bits_index: usize if i >= bits.len() { bits.len()-1 } else { i }; } } Ok(len) // } // } // i += CompressedTxIn::METADATA_SIZE; // n += m << i; // } else { // i = overflow; // n = m >> overflow; // let overflow = CompressedTxIn::METADATA_SIZE-slice; // n.consensus_encode(w)?; // n += (m & (m::MAX >> slice)); // let slice = n::BITS-i; // if i+CompressedTxIn::METADATA_SIZE > n::BITS { // let m: u8 = txin.metadata() // for txin in self.input { // let mut i: 0; // let mut n: u64; len += encode_bits(w, metadata, metadata_size)?; } metadata_size.push(txout::METADATA_SIZE); metadata.push(txin.metadata() as u64); for txout in self.output { } metadata_size.push(txin::METADATA_SIZE); metadata.push(txin.metadata() as u64); for txin in self.input { let mut metadata_size: Vec<u8> = vec![]; let mut metadata: Vec<(u64, u8)> = vec![]; len += encode_varint(w, self.minimum_height as u64)?; if (control & 0xc0) > 0 { len += encode_varint(w, self.lock_time as u64)?; } if (control & 0x30) == 0 { len += encode_varint(w, self.output.len() as u64)?; } if (control & 0x0c) == 0 { len += encode_varint(w, self.input.len() as u64)?; } if (control & 0x03) == 0 { len += encode_varint(w, self.version as u64)?; } len += control.consensus_encode(w)?; if self.lock_time > 0 { control |= 0b01000000 } if self.output.len() < 4 && !self.output.is_empty() { control |= (self.output.len() as u8) << 4 } if self.input.len() < 4 && !self.input.is_empty() { control |= (self.input.len() as u8) << 2 } if self.version < 4 && self.version > 0 { control = self.version as u8 } let mut control: u8 = 0; let mut len: usize = 0; fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> { impl Encodable for CompressedTransaction { } } Ok(result) } input.push(TxIn{previous_output: *prevout, script_sig, sequence: Sequence::from_consensus(ctxin.sequence), witness}); } } _ => {} }, // } // } // } // vin[index].scriptWitness.stack = stack; // stack.push_back(p_vec); // stack.push_back(sig_vec); // std::vector<std::vector<unsigned char>> stack; // copy(pub.begin(), pub.end(), p_vec.begin()); // std::vector<unsigned char> p_vec(p_size); // size_t p_size = pub.size(); // sig_vec[sig_size] = hash_type; // sig_vec.resize(sig_size+1); // secp256k1_ecdsa_signature_serialize_der(secp256k1_context_static, &sig_vec[0], &sig_size, &sig); // std::vector<unsigned char> sig_vec(sig_size); // size_t sig_size = 71; // secp256k1_ecdsa_signature_parse_compact(secp256k1_context_static, &sig, &input.signature()[0]); ad �
� � v C � � p ? - �
�
>
8
6
5
� � � � � � � � � � ~ l O . � � � � � r = �
�
1
� - � ) � � � � m g f + � � $ � ; p � m ? 3 2 }); _ => ctxout.script_pubkey.clone() ScriptType::P2PK if ctxout.script_pubkey.len() == 33 => [[vec![OP_PUSHBYTES_33.to_u8()], ctxout.script_pubkey.clone()].concat(), vec![OP_CHECKSIG.to_u8()]].concat(), ScriptType::P2PK if ctxout.script_pubkey.len() == 65 => [[vec![OP_PUSHBYTES_65.to_u8()], ctxout.script_pubkey.clone()].concat(), vec![OP_CHECKSIG.to_u8()]].concat(), ScriptType::P2SH => [[vec![OP_HASH160.to_u8(), OP_PUSHBYTES_20.to_u8()], ctxout.script_pubkey.clone()].concat(), vec![OP_EQUAL.to_u8()]].concat(), ScriptType::P2PKH => [[vec![OP_DUP.to_u8(), OP_HASH160.to_u8(), OP_PUSHBYTES_20.to_u8()], ctxout.script_pubkey.clone()].concat(), vec![OP_EQUALVERIFY.to_u8(), OP_CHECKSIG.to_u8()]].concat(), ScriptType::P2WSH => [[0x00, OP_PUSHBYTES_32.to_u8()].to_vec(), ctxout.script_pubkey.clone()].concat(), ScriptType::P2WPKH => [[0x00, OP_PUSHBYTES_20.to_u8()].to_vec(), ctxout.script_pubkey.clone()].concat(), ScriptType::P2TR => [[0x51, OP_PUSHBYTES_32.to_u8()].to_vec(), ctxout.script_pubkey.clone()].concat(), let script_pubkey: ScriptBuf = ScriptBuf::from_bytes(match ctxout.script_type { let value: Amount = Amount::from_sat(ctxout.value); pub fn decompress(ctxout: &CompressedTxOut) -> TxOut { } CompressedTxOut{script_type, script_pubkey, value} } script => { script_pubkey = script.to_bytes(); } script if script.is_p2pk() && script.len() == 1+33+1 => { script_pubkey = script.to_bytes()[1..33+1].to_vec(); script_type = ScriptType::P2PK; } script if script.is_p2pk() && script.len() == 1+65+1 => { script_pubkey = script.to_bytes()[1..65+1].to_vec(); script_type = ScriptType::P2PK; } script if script.is_p2sh() => { script_pubkey = script.to_bytes()[2..22].to_vec(); script_type = ScriptType::P2SH; } script if script.is_p2pkh() => { script_pubkey = script.to_bytes()[3..23].to_vec(); script_type = ScriptType::P2PKH; } script if script.is_p2wsh() => { script_pubkey = script.to_bytes()[2..].to_vec(); script_type = ScriptType::P2WSH; } script if script.is_p2wpkh() => { script_pubkey = script.to_bytes()[2..].to_vec(); script_type = ScriptType::P2WPKH; } script if script.is_p2tr() => { script_pubkey = script.to_bytes()[2..].to_vec(); script_type = ScriptType::P2TR; } match &txout.script_pubkey { println!("{}", txout.script_pubkey.is_p2wpkh()); let value: u64 = txout.value.to_sat(); let mut script_pubkey: Vec<u8> = Vec::new(); let mut script_type: ScriptType = ScriptType::NonStandard; pub fn compress(txout: &TxOut) -> Self { impl CompressedTxOut{ } pub value: u64 pub script_pubkey: Vec<u8>, pub script_type: ScriptType, pub struct CompressedTxOut { #[non_exhaustive] #[derive(Debug, Clone)] } P2TR = 6 P2WSH = 5, P2WPKH = 4, P2SH = 3, P2PKH = 2, P2PK = 1, NonS#[derive(Debug, Clone,Part#[derive(Debug, Clone, PartialEq)] } } Ok(CompressedTxIn{compressed_outpoint, outpoint, signature, pubkey_hash, hash_type, is_hash_standard, compressed_signature, sequence}) let sequence: u32 = txin.sequence.to_consensus_u32(); } } } signature.append(&mut item); VarInt::from(item.len() as u64).consensus_encode(&mut signature)?; for mut item in stack { VarInt::from(stack.len() as u64).consensus_encode(&mut signature)?; let stack = txin.witness.to_vec(); } signature.append(&mut txin.script_sig.to_bytes()); if !txin.script_sig.is_empty() { ad A
�
� � � � � � � r Y G 3 � � � � � d 0 �
�
�
�
�
p
#
� � � � v ; 1 ( � � � Q �
�
P
O
"
� � � � ] \ 1 � � � n F & % � � � � l - � � � S � y @ � w � � K � � t � � // // secp256k1_ecdsa_signature sig; // if (output.scriptPubKey == script_pubkey) { // CScript script_pubkey = GetScriptForDestination(WitnessV0KeyHash(pub)); // if (pub.RecoverCompact(hash, vch_sig)) { // CPubKey pub; // vch_sig[0] = recoveryId+27; // for (int recoveryId = 4; recoveryId < 8; recoveryId++) { // copy(input.signature().begin(), input.signature().end(), vch_sig.begin()+1); // std::vector<unsigned char> vch_sig(CPubKey::COMPACT_SIGNATURE_SIZE); // uint256 hash = SignatureHash(scriptCode, *this, index, hash_type, output.nValue, SigVersion::WITNESS_V0); // CScript scriptCode = GetScriptForDestination(destination); // BuildDestination(vSolutions, TxoutType::PUBKEYHASH, destination); // CTxDestination destination; // Solver(output.scriptPubKey, vSolutions); // std::vector<std::vector<unsigned char>> vSolutions; // uint8_t hash_type = input.isHashStandard() ? 0x01 : input.hashType(); let cache = SighashCache::new(&result); script if script.is_p2wpkh() => { }, } witness.push([ctxin.signature.clone(), vec![ctxin.hash_type]].concat()); } else { witness.push(ctxin.signature.clone()); if ctxin.is_hash_standard { script if script.is_p2tr() => { match &out.script_pubkey { if ctxin.compressed_signature { let out = &outs[i]; let prevout = &prevouts[i]; let ctxin = &ctx.input[i]; let mut witness: Witness = Witness::new(); let mut script_sig: ScriptBuf = ScriptBuf::new(); for i in 0..ctx.input.len() { let mut input: Vec<TxIn> = vec![]; let result: Transaction = Transaction{version, lock_time, output, input: vec![]}; } output.push(CompressedTxOut::decompress(txout)); for txout in &ctx.output { let mut output: Vec<TxOut> = vec![]; let mut lock_time: LockTime = LockTime::Blocks(Height::from_consensus(lock_time_u32)?); if ctx.lock_time > 0 {lock_time_u32 += ctx.minimum_height;} let mut lock_time_u32: u32 = 0; let version: Version = Version(ctx.version); pub fn decompress(ctx: &CompressedTransaction, prevouts: &[OutPoint], outs: &[TxOut]) -> Result<Transaction, Error> { } Ok(CompressedTransaction{ minimum_height, version, lock_time, input, output}) } output.push(CompressedTxOut::compress(txout)); for txout in &tx.output { let mut output: Vec<CompressedTxOut> = vec![]; } input.push(CompressedTxIn::compress(&tx.input[i], cinput)?); for (i, cinput) in cinputs.iter().enumerate().take(tx.input.len()) { let mut input: Vec<CompressedTxIn> = v pub fn output(&self) -> &Vec<CompressedTxOut> {&self.output} pub fn input(&self) -> &Vec<CompressedTxIn> {&self.input} pub fn lock_time(&self) -> u32 {self.lock_time} pub fn version(&self) -> i32 {self.version} pub fn minimum_height(&self) -> u32 {self.minimum_height} impl CompressedTransaction { } output: Vec<CompressedTxOut>