Created
October 12, 2017 04:06
-
-
Save achow101/86a4fdcb3cebc1a57968715f34d66e0a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp | |
index 6b68f0679e8..c4c81715e48 100644 | |
--- a/src/script/ismine.cpp | |
+++ b/src/script/ismine.cpp | |
@@ -145,6 +145,27 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& | |
return ISMINE_SPENDABLE; | |
break; | |
} | |
+ | |
+ case TX_CLTV_MULTISIG: | |
+ { | |
+ // Only consider transactions "mine" if we own ALL the | |
+ // keys involved. Multi-signature transactions that are | |
+ // partially owned (somebody else has a key that can spend | |
+ // them) enable spend-out-from-under-you attacks, especially | |
+ // in shared-wallet situations. | |
+ std::vector<valtype> keys(vSolutions.begin()+2, vSolutions.begin()+vSolutions.size()-1); | |
+ if (sigversion != SIGVERSION_BASE) { | |
+ for (size_t i = 0; i < keys.size(); i++) { | |
+ if (keys[i].size() != 33) { | |
+ isInvalid = true; | |
+ return ISMINE_NO; | |
+ } | |
+ } | |
+ } | |
+ if (HaveKeys(keys, keystore) == keys.size()) | |
+ return ISMINE_SPENDABLE; | |
+ break; | |
+ } | |
} | |
if (keystore.HaveWatchOnly(scriptPubKey)) { | |
diff --git a/src/script/script.h b/src/script/script.h | |
index 2a920605433..bc8a1fadb2c 100644 | |
--- a/src/script/script.h | |
+++ b/src/script/script.h | |
@@ -183,6 +183,7 @@ enum opcodetype | |
// template matching params | |
+ OP_PUSHEDDATA = 0xf0, | |
OP_SMALLINTEGER = 0xfa, | |
OP_PUBKEYS = 0xfb, | |
OP_PUBKEYHASH = 0xfd, | |
diff --git a/src/script/sign.cpp b/src/script/sign.cpp | |
index ac58b690a2f..ed88dbf8702 100644 | |
--- a/src/script/sign.cpp | |
+++ b/src/script/sign.cpp | |
@@ -106,6 +106,13 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP | |
ret.push_back(valtype()); // workaround CHECKMULTISIG bug | |
return (SignN(vSolutions, creator, scriptPubKey, ret, sigversion)); | |
+ case TX_CLTV_MULTISIG: | |
+ { | |
+ ret.push_back(valtype()); // workaround CHECKMULTISIG bug | |
+ std::vector<valtype> vSolutions2(vSolutions.begin()+1, vSolutions.end()); | |
+ return (SignN(vSolutions2, creator, scriptPubKey, ret, sigversion)); | |
+ } | |
+ | |
case TX_WITNESS_V0_KEYHASH: | |
ret.push_back(vSolutions[0]); | |
return true; | |
@@ -348,6 +355,11 @@ static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignature | |
} | |
case TX_MULTISIG: | |
return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, sigversion)); | |
+ case TX_CLTV_MULTISIG: | |
+ { | |
+ std::vector<valtype> vSolutions2(vSolutions.begin()+1, vSolutions.end()); | |
+ return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions2, sigs1.script, sigs2.script, sigversion)); | |
+ } | |
case TX_WITNESS_V0_SCRIPTHASH: | |
if (sigs1.witness.empty() || sigs1.witness.back().empty()) | |
return sigs2; | |
diff --git a/src/script/standard.cpp b/src/script/standard.cpp | |
index f57f1f61b4f..35131e27a56 100644 | |
--- a/src/script/standard.cpp | |
+++ b/src/script/standard.cpp | |
@@ -31,6 +31,7 @@ const char* GetTxnOutputType(txnouttype t) | |
case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash"; | |
case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash"; | |
case TX_WITNESS_UNKNOWN: return "witness_unknown"; | |
+ case TX_CLTV_MULTISIG: return "cltv-multisig"; | |
} | |
return nullptr; | |
} | |
@@ -49,6 +50,9 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v | |
// Sender provides N pubkeys, receivers provides M signatures | |
mTemplates.insert(std::make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG)); | |
+ | |
+ // Sender provides N pubkeys and a lock time, receivers provides M signatures | |
+ mTemplates.insert(std::make_pair(TX_CLTV_MULTISIG, CScript() << OP_PUSHEDDATA << OP_CHECKLOCKTIMEVERIFY << OP_DROP << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG)); | |
} | |
vSolutionsRet.clear(); | |
@@ -121,6 +125,12 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v | |
unsigned char n = vSolutionsRet.back()[0]; | |
if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n) | |
return false; | |
+ } else if (typeRet == TX_CLTV_MULTISIG) { | |
+ // Additional checks for TX_CLTV_MULTISIG: | |
+ unsigned char m = vSolutionsRet[1][0]; | |
+ unsigned char n = vSolutionsRet.back()[0]; | |
+ if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-3 != n) | |
+ return false; | |
} | |
return true; | |
} | |
@@ -167,6 +177,11 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v | |
else | |
break; | |
} | |
+ else if (opcode2 == OP_PUSHEDDATA) | |
+ { | |
+ // Some arbitrary data was pushed | |
+ vSolutionsRet.push_back(vch1); | |
+ } | |
else if (opcode1 != opcode2 || vch1 != vch2) | |
{ | |
// Others must match exactly | |
@@ -255,6 +270,22 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std:: | |
if (addressRet.empty()) | |
return false; | |
} | |
+ else if (typeRet == TX_CLTV_MULTISIG) | |
+ { | |
+ nRequiredRet = vSolutions[1][0]; | |
+ for (unsigned int i = 2; i < vSolutions.size()-1; i++) | |
+ { | |
+ CPubKey pubKey(vSolutions[i]); | |
+ if (!pubKey.IsValid()) | |
+ continue; | |
+ | |
+ CTxDestination address = pubKey.GetID(); | |
+ addressRet.push_back(address); | |
+ } | |
+ | |
+ if (addressRet.empty()) | |
+ return false; | |
+ } | |
else | |
{ | |
nRequiredRet = 1; | |
diff --git a/src/script/standard.h b/src/script/standard.h | |
index fa07ea88c1a..c9e423a5d51 100644 | |
--- a/src/script/standard.h | |
+++ b/src/script/standard.h | |
@@ -64,6 +64,7 @@ enum txnouttype | |
TX_NULL_DATA, //!< unspendable OP_RETURN script that carries data | |
TX_WITNESS_V0_SCRIPTHASH, | |
TX_WITNESS_V0_KEYHASH, | |
+ TX_CLTV_MULTISIG, | |
TX_WITNESS_UNKNOWN, //!< Only for Witness versions not already defined above | |
}; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment