uahf: OP_RETURN replay protection
This commit is contained in:
parent
6110d94544
commit
d6b9445344
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"chain 0.1.0",
|
||||
"db 0.1.0",
|
||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"network 0.1.0",
|
||||
"parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -2,25 +2,6 @@ use std::cmp::max;
|
|||
use hash::H256;
|
||||
use {Magic, Deployment};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
/// Concurrent consensus rule forks.
|
||||
pub enum ConsensusFork {
|
||||
/// No fork.
|
||||
NoFork,
|
||||
/// SegWit2x (aka The New York Agreement).
|
||||
/// Briefly: SegWit + blocks up to 2MB.
|
||||
/// Technical specification:
|
||||
/// Segregated Witness (Consensus layer) - https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki
|
||||
/// Block size increase to 2MB - https://github.com/bitcoin/bips/blob/master/bip-0102.mediawiki
|
||||
SegWit2x(u32),
|
||||
/// Bitcoin Cash (aka UAHF).
|
||||
/// Briefly: no SegWit + blocks up to 8MB + replay protection.
|
||||
/// Technical specification:
|
||||
/// UAHF Technical Specification - https://github.com/Bitcoin-UAHF/spec/blob/master/uahf-technical-spec.md
|
||||
/// BUIP-HF Digest for replay protected signature verification across hard forks - https://github.com/Bitcoin-UAHF/spec/blob/master/replay-protected-sighash.md
|
||||
BitcoinCash(u32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Parameters that influence chain consensus.
|
||||
pub struct ConsensusParams {
|
||||
|
@ -50,6 +31,25 @@ pub struct ConsensusParams {
|
|||
pub segwit_deployment: Option<Deployment>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
/// Concurrent consensus rule forks.
|
||||
pub enum ConsensusFork {
|
||||
/// No fork.
|
||||
NoFork,
|
||||
/// SegWit2x (aka The New York Agreement).
|
||||
/// Briefly: SegWit + blocks up to 2MB.
|
||||
/// Technical specification:
|
||||
/// Segregated Witness (Consensus layer) - https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki
|
||||
/// Block size increase to 2MB - https://github.com/bitcoin/bips/blob/master/bip-0102.mediawiki
|
||||
SegWit2x(u32),
|
||||
/// Bitcoin Cash (aka UAHF).
|
||||
/// Briefly: no SegWit + blocks up to 8MB + replay protection.
|
||||
/// Technical specification:
|
||||
/// UAHF Technical Specification - https://github.com/Bitcoin-UAHF/spec/blob/master/uahf-technical-spec.md
|
||||
/// BUIP-HF Digest for replay protected signature verification across hard forks - https://github.com/Bitcoin-UAHF/spec/blob/master/replay-protected-sighash.md
|
||||
BitcoinCash(u32),
|
||||
}
|
||||
|
||||
impl ConsensusParams {
|
||||
pub fn new(magic: Magic, fork: ConsensusFork) -> Self {
|
||||
match magic {
|
||||
|
|
|
@ -126,4 +126,9 @@ impl Builder {
|
|||
pub fn into_script(self) -> Script {
|
||||
Script::new(self.data)
|
||||
}
|
||||
|
||||
/// Builds final script bytes
|
||||
pub fn into_bytes(self) -> Bytes {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ authors = ["Nikolay Volf <nikvolf@gmail.com>"]
|
|||
|
||||
[dependencies]
|
||||
time = "0.1"
|
||||
lazy_static = "0.2"
|
||||
log = "0.3"
|
||||
rayon = "0.7"
|
||||
parking_lot = "0.4"
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use primitives::hash::H256;
|
||||
use primitives::bytes::Bytes;
|
||||
use db::{TransactionMetaProvider, TransactionOutputProvider, BlockHeaderProvider};
|
||||
use network::ConsensusParams;
|
||||
use network::{ConsensusParams, ConsensusFork};
|
||||
use script::{Script, verify_script, VerificationFlags, TransactionSignatureChecker, TransactionInputSigner};
|
||||
use duplex_store::DuplexTransactionOutputProvider;
|
||||
use deployments::Deployments;
|
||||
use script::Builder;
|
||||
use sigops::transaction_sigops;
|
||||
use canon::CanonTransaction;
|
||||
use constants::{COINBASE_MATURITY};
|
||||
|
@ -15,6 +17,7 @@ pub struct TransactionAcceptor<'a> {
|
|||
pub maturity: TransactionMaturity<'a>,
|
||||
pub overspent: TransactionOverspent<'a>,
|
||||
pub double_spent: TransactionDoubleSpend<'a>,
|
||||
pub return_replay_protection: TransactionReturnReplayProtection<'a>,
|
||||
pub eval: TransactionEval<'a>,
|
||||
}
|
||||
|
||||
|
@ -41,6 +44,7 @@ impl<'a> TransactionAcceptor<'a> {
|
|||
maturity: TransactionMaturity::new(transaction, meta_store, height),
|
||||
overspent: TransactionOverspent::new(transaction, output_store),
|
||||
double_spent: TransactionDoubleSpend::new(transaction, output_store),
|
||||
return_replay_protection: TransactionReturnReplayProtection::new(transaction, consensus, height),
|
||||
eval: TransactionEval::new(transaction, output_store, consensus, height, time, deployments, headers),
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +55,7 @@ impl<'a> TransactionAcceptor<'a> {
|
|||
try!(self.maturity.check());
|
||||
try!(self.overspent.check());
|
||||
try!(self.double_spent.check());
|
||||
try!(self.return_replay_protection.check());
|
||||
try!(self.eval.check());
|
||||
Ok(())
|
||||
}
|
||||
|
@ -62,6 +67,7 @@ pub struct MemoryPoolTransactionAcceptor<'a> {
|
|||
pub overspent: TransactionOverspent<'a>,
|
||||
pub sigops: TransactionSigops<'a>,
|
||||
pub double_spent: TransactionDoubleSpend<'a>,
|
||||
pub return_replay_protection: TransactionReturnReplayProtection<'a>,
|
||||
pub eval: TransactionEval<'a>,
|
||||
}
|
||||
|
||||
|
@ -87,6 +93,7 @@ impl<'a> MemoryPoolTransactionAcceptor<'a> {
|
|||
overspent: TransactionOverspent::new(transaction, output_store),
|
||||
sigops: TransactionSigops::new(transaction, output_store, consensus, max_block_sigops, time),
|
||||
double_spent: TransactionDoubleSpend::new(transaction, output_store),
|
||||
return_replay_protection: TransactionReturnReplayProtection::new(transaction, consensus, height),
|
||||
eval: TransactionEval::new(transaction, output_store, consensus, height, time, deployments, headers),
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +106,7 @@ impl<'a> MemoryPoolTransactionAcceptor<'a> {
|
|||
try!(self.overspent.check());
|
||||
try!(self.sigops.check());
|
||||
try!(self.double_spent.check());
|
||||
try!(self.return_replay_protection.check());
|
||||
try!(self.eval.check());
|
||||
Ok(())
|
||||
}
|
||||
|
@ -363,3 +371,39 @@ impl<'a> TransactionDoubleSpend<'a> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TransactionReturnReplayProtection<'a> {
|
||||
transaction: CanonTransaction<'a>,
|
||||
consensus: &'a ConsensusParams,
|
||||
height: u32,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref BITCOIN_CASH_RETURN_REPLAY_PROTECTION_SCRIPT: Bytes = Builder::default()
|
||||
.return_bytes(b"Bitcoin: A Peer-to-Peer Electronic Cash System") // TODO: check that data.size() == 46
|
||||
.into_bytes();
|
||||
}
|
||||
|
||||
impl<'a> TransactionReturnReplayProtection<'a> {
|
||||
fn new(transaction: CanonTransaction<'a>, consensus: &'a ConsensusParams, height: u32) -> Self {
|
||||
TransactionReturnReplayProtection {
|
||||
transaction: transaction,
|
||||
consensus: consensus,
|
||||
height: height,
|
||||
}
|
||||
}
|
||||
|
||||
fn check(&self) -> Result<(), TransactionError> {
|
||||
if let ConsensusFork::BitcoinCash(fork_block) = self.consensus.fork {
|
||||
// Transactions with such OP_RETURNs shall be considered valid again for block 530,001 and onwards
|
||||
if self.height >= fork_block && self.height <= 530_000 {
|
||||
if (*self.transaction).raw.outputs.iter()
|
||||
.any(|out| out.script_pubkey == *BITCOIN_CASH_RETURN_REPLAY_PROTECTION_SCRIPT) {
|
||||
return Err(TransactionError::ReturnReplayProtection)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,5 +93,7 @@ pub enum TransactionError {
|
|||
UnspentTransactionWithTheSameHash,
|
||||
/// Using output that is surely spent
|
||||
UsingSpentOutput(H256, u32),
|
||||
/// Transaction, protected using BitcoinCash OP_RETURN replay protection (REQ-6-1).
|
||||
ReturnReplayProtection,
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
|
||||
extern crate time;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate parking_lot;
|
||||
extern crate rayon;
|
||||
|
|
Loading…
Reference in New Issue