Skip to content

Instantly share code, notes, and snippets.

@gavinandresen
Created June 15, 2017 15:15
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gavinandresen/2a7474a3dd5b834ed3a7d10c74ec84c5 to your computer and use it in GitHub Desktop.
Save gavinandresen/2a7474a3dd5b834ed3a7d10c74ec84c5 to your computer and use it in GitHub Desktop.
OP_RETURN replay protection patch
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index ec398f662..6724399c0 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -117,6 +117,10 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnes
return false;
}
+ if (tx.ReplayProtected()) {
+ return false;
+ }
+
return true;
}
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 28ef1fb46..8dad091a8 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -145,3 +145,14 @@ int64_t GetTransactionWeight(const CTransaction& tx)
{
return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR -1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
}
+
+bool CTransaction::ReplayProtected() const
+{
+ CScript noReplay = CScript() << OP_RETURN << ParseHex("217365677769743278"); // "!segwit2x" in hex
+ for (const auto& txout : this->vout) {
+ if (txout.scriptPubKey == noReplay) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index af2986a41..4ea1475c3 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -400,6 +400,8 @@ public:
}
return false;
}
+
+ bool ReplayProtected() const;
};
/** A mutable version of CTransaction. */
diff --git a/src/validation.cpp b/src/validation.cpp
index 9ebce7708..4076c6c2c 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -2891,10 +2891,13 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
return state.DoS(100, false, REJECT_INVALID, "bad-cb-multiple", false, "more than one coinbase");
// Check transactions
- for (const auto& tx : block.vtx)
+ for (const auto& tx : block.vtx) {
if (!CheckTransaction(*tx, state, false))
return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
strprintf("Transaction check failed (tx hash %s) %s", tx->GetHash().ToString(), state.GetDebugMessage()));
+ if (/* TODO: hard fork condition... && */ tx->ReplayProtected())
+ return state.DoS(0, false, REJECT_INVALID, "bad-blk-replay", false, "!segwit2x transaction in block");
+ }
unsigned int nSigOps = 0;
for (const auto& tx : block.vtx)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment