Skip to content

Commit e9fbb4c

Browse files
authored
Merge pull request #1461 from plebhash/dont-assume-script-sig-bip34
remove assumption that coinbase scriptSig prefix contains only BIP34
2 parents 631a0a1 + 55c01d2 commit e9fbb4c

File tree

2 files changed

+34
-72
lines changed

2 files changed

+34
-72
lines changed

protocols/v2/roles-logic-sv2/src/errors.rs

-3
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,6 @@ pub enum Error {
101101
InvalidExtranonceSize(u16, u16),
102102
/// Poison Lock
103103
PoisonLock(String),
104-
/// Invalid BIP34 bytes
105-
InvalidBip34Bytes(Vec<u8>),
106104
/// Channel Factory did not update job. Params: (downstream_job_id, upstream_job_id)
107105
JobNotUpdated(u32, u32),
108106
/// Impossible to get Target
@@ -206,7 +204,6 @@ impl Display for Error {
206204
NoTemplateForId => write!(f, "Impossible to retrieve a template for the required job id"),
207205
NoValidTemplate(e) => write!(f, "Impossible to retrieve a template for the required template id: {}", e),
208206
PoisonLock(e) => write!(f, "Poison lock: {}", e),
209-
InvalidBip34Bytes(e) => write!(f, "Invalid Bip34 bytes {:?}", e),
210207
JobNotUpdated(ds_job_id, us_job_id) => write!(f, "Channel Factory did not update job: Downstream job id = {}, Upstream job id = {}", ds_job_id, us_job_id),
211208
TargetError(e) => write!(f, "Impossible to get Target: {:?}", e),
212209
HashrateError(e) => write!(f, "Impossible to get Hashrate: {:?}", e),

protocols/v2/roles-logic-sv2/src/job_creator.rs

+34-69
Original file line numberDiff line numberDiff line change
@@ -204,18 +204,18 @@ fn new_extended_job(
204204
.try_into()
205205
.map_err(|_| Error::TxVersionTooBig)?;
206206

207-
let bip34_bytes = get_bip_34_bytes(new_template, tx_version)?;
208-
let script_prefix_len = bip34_bytes.len() + additional_coinbase_script_data.len();
207+
let script_sig_prefix = new_template.coinbase_prefix.to_vec();
208+
let script_sig_prefix_len = script_sig_prefix.len() + additional_coinbase_script_data.len();
209209

210210
let coinbase = coinbase(
211-
bip34_bytes,
211+
script_sig_prefix,
212212
tx_version,
213213
new_template.coinbase_tx_locktime,
214214
new_template.coinbase_tx_input_sequence,
215215
coinbase_outputs,
216216
additional_coinbase_script_data,
217217
extranonce_len,
218-
);
218+
)?;
219219

220220
let min_ntime = binary_sv2::Sv2Option::new(if new_template.future_template {
221221
None
@@ -230,8 +230,8 @@ fn new_extended_job(
230230
version: new_template.version,
231231
version_rolling_allowed,
232232
merkle_path: new_template.merkle_path.clone().into_static(),
233-
coinbase_tx_prefix: coinbase_tx_prefix(&coinbase, script_prefix_len)?,
234-
coinbase_tx_suffix: coinbase_tx_suffix(&coinbase, extranonce_len, script_prefix_len)?,
233+
coinbase_tx_prefix: coinbase_tx_prefix(&coinbase, script_sig_prefix_len)?,
234+
coinbase_tx_suffix: coinbase_tx_suffix(&coinbase, extranonce_len, script_sig_prefix_len)?,
235235
};
236236

237237
debug!(
@@ -245,12 +245,12 @@ fn new_extended_job(
245245
// so the extranonce search space can be introduced
246246
fn coinbase_tx_prefix(
247247
coinbase: &Transaction,
248-
script_prefix_len: usize,
248+
script_sig_prefix_len: usize,
249249
) -> Result<B064K<'static>, Error> {
250250
let encoded = consensus::serialize(coinbase);
251251
// If script_prefix_len is not 0 we are not in a test environment and the coinbase will have the
252252
// 0 witness
253-
let segwit_bytes = match script_prefix_len {
253+
let segwit_bytes = match script_sig_prefix_len {
254254
0 => 0,
255255
_ => 2,
256256
};
@@ -260,7 +260,7 @@ fn coinbase_tx_prefix(
260260
+ 32 // prev OutPoint
261261
+ 4 // index
262262
+ 1 // bytes in script TODO can be also 3
263-
+ script_prefix_len; // bip34_bytes
263+
+ script_sig_prefix_len; // script_sig_prefix
264264
let r = encoded[0..index].to_vec();
265265
r.try_into().map_err(Error::BinarySv2Error)
266266
}
@@ -270,12 +270,12 @@ fn coinbase_tx_prefix(
270270
fn coinbase_tx_suffix(
271271
coinbase: &Transaction,
272272
extranonce_len: u8,
273-
script_prefix_len: usize,
273+
script_sig_prefix_len: usize,
274274
) -> Result<B064K<'static>, Error> {
275275
let encoded = consensus::serialize(coinbase);
276-
// If script_prefix_len is not 0 we are not in a test environment and the coinbase have the 0
277-
// witness
278-
let segwit_bytes = match script_prefix_len {
276+
// If script_sig_prefix_len is not 0 we are not in a test environment and the coinbase have the
277+
// 0 witness
278+
let segwit_bytes = match script_sig_prefix_len {
279279
0 => 0,
280280
_ => 2,
281281
};
@@ -285,78 +285,43 @@ fn coinbase_tx_suffix(
285285
+ 32 // prev OutPoint
286286
+ 4 // index
287287
+ 1 // bytes in script TODO can be also 3
288-
+ script_prefix_len // bip34_bytes
288+
+ script_sig_prefix_len // script_sig_prefix
289289
+ (extranonce_len as usize)..]
290290
.to_vec();
291291
r.try_into().map_err(Error::BinarySv2Error)
292292
}
293293

294-
// Just double check if received coinbase_prefix is the right one can be removed or used only for
295-
// tests
296-
fn get_bip_34_bytes(new_template: &NewTemplate, tx_version: i32) -> Result<Vec<u8>, Error> {
297-
#[cfg(test)]
298-
if tx_version == 1 {
299-
return Ok(vec![]);
300-
};
301-
302-
let script_prefix = &new_template.coinbase_prefix.to_vec()[..];
303-
304-
// Is ok to panic here cause condition will be always true when not in a test chain
305-
// (regtest ecc ecc)
306-
#[cfg(not(test))]
307-
assert!(
308-
script_prefix.len() > 2,
309-
"Bitcoin blockchain should be at least 16 block long"
310-
);
311-
312-
// Txs version lower or equal to 1 are not allowed in new blocks we need it only to test the
313-
// JobCreator against old bitcoin blocks
314-
#[cfg(not(test))]
315-
if tx_version <= 1 {
316-
return Err(Error::TxVersionTooLow);
317-
};
318-
319-
// add 1 cause 0 is push 1 2 is 1 is push 2 ecc ecc
320-
// add 1 cause in the len there is also the op code itself
321-
let bip34_len = script_prefix[0] as usize + 2;
322-
if bip34_len == script_prefix.len() {
323-
Ok(script_prefix[0..bip34_len].to_vec())
324-
} else {
325-
Err(Error::InvalidBip34Bytes(script_prefix.to_vec()))
326-
}
327-
}
328-
329-
// coinbase_tx_input_script_prefix: extranonce prefix (script length + bip34 block height) provided
330-
// by the node It assume that NewTemplate.coinbase_tx_outputs == 0
294+
// try to build a Transaction coinbase
331295
fn coinbase(
332-
mut bip34_bytes: Vec<u8>,
296+
script_sig_prefix: Vec<u8>,
333297
version: i32,
334298
lock_time: u32,
335299
sequence: u32,
336300
coinbase_outputs: &[TxOut],
337301
additional_coinbase_script_data: Vec<u8>,
338302
extranonce_len: u8,
339-
) -> Transaction {
340-
// If script_prefix_len is not 0 we are not in a test environment and the coinbase have the 0
341-
// witness
342-
let witness = match bip34_bytes.len() {
303+
) -> Result<Transaction, Error> {
304+
// If script_sig_prefix_len is not 0 we are not in a test environment and the coinbase have the
305+
// 0 witness
306+
let witness = match script_sig_prefix.len() {
343307
0 => Witness::from(vec![] as Vec<Vec<u8>>),
344308
_ => Witness::from(vec![vec![0; 32]]),
345309
};
346-
bip34_bytes.extend_from_slice(&additional_coinbase_script_data);
347-
bip34_bytes.extend_from_slice(&vec![0; extranonce_len as usize]);
310+
let mut script_sig = script_sig_prefix;
311+
script_sig.extend_from_slice(&additional_coinbase_script_data);
312+
script_sig.extend_from_slice(&vec![0; extranonce_len as usize]);
348313
let tx_in = TxIn {
349314
previous_output: OutPoint::null(),
350-
script_sig: bip34_bytes.into(),
315+
script_sig: script_sig.into(),
351316
sequence: bitcoin::Sequence(sequence),
352317
witness,
353318
};
354-
Transaction {
319+
Ok(Transaction {
355320
version: Version::non_standard(version),
356321
lock_time: LockTime::from_consensus(lock_time),
357322
input: vec![tx_in],
358323
output: coinbase_outputs.to_vec(),
359-
}
324+
})
360325
}
361326

362327
/// Helper type to strip a segwit data from the coinbase_tx_prefix and coinbase_tx_suffix
@@ -428,7 +393,7 @@ impl StrippedCoinbaseTx {
428393
}
429394

430395
// The coinbase tx prefix is the LE bytes concatenation of the tx version and all
431-
// of the tx inputs minus the 32 bytes after the bip34 bytes in the script
396+
// of the tx inputs minus the 32 bytes after the script_sig_prefix bytes
432397
// and the last input's sequence (used as the first entry in the coinbase tx suffix).
433398
// The last 32 bytes after the bip34 bytes in the script will be used to allow extranonce
434399
// space for the miner. We remove the bip141 marker and flag since it is only used for
@@ -493,13 +458,13 @@ pub mod tests {
493458
let mut coinbase_prefix_gen = Gen::new(255);
494459
let mut coinbase_prefix: vec::Vec<u8> = vec::Vec::new();
495460

496-
let max_num_for_script_prefix = 253;
461+
let max_num_for_script_sig_prefix = 253;
497462
let prefix_len = cmp::min(u8::arbitrary(&mut coinbase_prefix_gen), 6);
498463
coinbase_prefix.push(prefix_len);
499464
coinbase_prefix.resize_with(prefix_len as usize + 2, || {
500465
cmp::min(
501466
u8::arbitrary(&mut coinbase_prefix_gen),
502-
max_num_for_script_prefix,
467+
max_num_for_script_sig_prefix,
503468
)
504469
});
505470
let coinbase_prefix: binary_sv2::B0255 = coinbase_prefix.try_into().unwrap();
@@ -539,8 +504,8 @@ pub mod tests {
539504
pub fn new_pub_key() -> PublicKey {
540505
let priv_k = PrivateKey::from_slice(&PRIVATE_KEY_BTC, NETWORK).unwrap();
541506
let secp = Secp256k1::default();
542-
let pub_k = PublicKey::from_private_key(&secp, &priv_k);
543-
pub_k
507+
508+
PublicKey::from_private_key(&secp, &priv_k)
544509
}
545510

546511
#[cfg(feature = "prop_test")]
@@ -698,7 +663,7 @@ pub mod tests {
698663
encoded.append(&mut encoded1.clone());
699664
encoded.append(&mut encoded2.clone());
700665
let outs = tx_outputs_to_costum_scripts(&encoded[..]);
701-
assert!(&outs[0] == &tx1);
666+
assert!(outs[0] == tx1);
702667
assert!(outs[1] == tx2);
703668
}
704669

@@ -753,10 +718,10 @@ pub mod tests {
753718
65, 241, 216, 46, 82, 223, 150, 0, 97, 103, 2, 82, 186, 233, 145, 90, 210, 231, 35,
754719
100, 107, 52, 171, 233, 50, 200, 0, 0, 0, 0,
755720
];
756-
let extranonce = vec![0_u8; 15]; // braiins pool requires 15 bytes for extranonce
721+
let extranonce = [0_u8; 15]; // braiins pool requires 15 bytes for extranonce
757722
encoded.extend_from_slice(coinbase_prefix);
758723
let mut encoded_clone = encoded.clone();
759-
encoded_clone.extend_from_slice(&extranonce[..]);
724+
encoded_clone.extend_from_slice(&extranonce);
760725
encoded_clone.extend_from_slice(coinbase_suffix);
761726
// let mut i = 1;
762727
// while let Err(_) = Transaction::deserialize(&encoded_clone) {

0 commit comments

Comments
 (0)