Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Josh Wilcox
crown-core
Commits
fa1ca2af
Commit
fa1ca2af
authored
13 years ago
by
Gavin Andresen
Browse files
Options
Download
Email Patches
Plain Diff
Replace OP_EVAL (BIP 12) with Pay-to-script-hash (BIP 16).
parent
5c1e04a3
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
src/base58.h
+2
-2
src/base58.h
src/bitcoinrpc.cpp
+40
-19
src/bitcoinrpc.cpp
src/db.cpp
+1
-1
src/db.cpp
src/keystore.cpp
+2
-2
src/keystore.cpp
src/keystore.h
+2
-2
src/keystore.h
src/main.cpp
+88
-58
src/main.cpp
src/main.h
+5
-3
src/main.h
src/script.cpp
+136
-102
src/script.cpp
src/script.h
+16
-26
src/script.h
src/test/multisig_tests.cpp
+11
-12
src/test/multisig_tests.cpp
src/test/rpc_tests.cpp
+74
-0
src/test/rpc_tests.cpp
src/test/script_P2SH_tests.cpp
+310
-0
src/test/script_P2SH_tests.cpp
src/test/script_tests.cpp
+19
-23
src/test/script_tests.cpp
src/test/sigopcount_tests.cpp
+60
-0
src/test/sigopcount_tests.cpp
src/test/test_bitcoin.cpp
+9
-3
src/test/test_bitcoin.cpp
src/test/util_tests.cpp
+15
-0
src/test/util_tests.cpp
src/util.cpp
+28
-18
src/util.cpp
src/util.h
+1
-0
src/util.h
src/wallet.cpp
+3
-3
src/wallet.cpp
src/wallet.h
+2
-2
src/wallet.h
with
824 additions
and
276 deletions
+824
-276
src/base58.h
View file @
fa1ca2af
...
...
@@ -255,7 +255,7 @@ public:
// base58-encoded bitcoin addresses
// Public-key-hash-addresses have version 0 (or 192 testnet)
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key
// Script-hash-addresses
(OP_EVAL)
have version 5 (or 196 testnet)
// Script-hash-addresses have version 5 (or 196 testnet)
// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script
class
CBitcoinAddress
:
public
CBase58Data
{
...
...
@@ -296,7 +296,7 @@ public:
fExpectTestNet
=
false
;
break
;
case
SCRIPT_ADDRESS
:
nExpectedSize
=
20
;
//
OP_EVAL, h
ash of CScript
nExpectedSize
=
20
;
//
H
ash of CScript
fExpectTestNet
=
false
;
break
;
...
...
This diff is collapsed.
Click to expand it.
src/bitcoinrpc.cpp
View file @
fa1ca2af
...
...
@@ -1008,41 +1008,62 @@ Value addmultisigaddress(const Array& params, bool fHelp)
strAccount
=
AccountFromValue
(
params
[
2
]);
// Gather public keys
if (keys.size() < nRequired)
if
(
nRequired
<
1
||
keys
.
size
()
<
nRequired
)
throw
runtime_error
(
strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
strprintf
(
"wrong number of keys"
"(got %d, need at least %d)"
,
keys
.
size
(),
nRequired
));
std
::
vector
<
CKey
>
pubkeys
;
pubkeys
.
resize
(
keys
.
size
());
for
(
int
i
=
0
;
i
<
keys
.
size
();
i
++
)
{
const
std
::
string
&
ks
=
keys
[
i
].
get_str
();
if (ks.size() == 130) // hex public key
pubkeys[i].SetPubKey(ParseHex(ks));
else if (ks.size() > 34) // base58-encoded
{
std::vector<unsigned char> vchPubKey;
if (DecodeBase58(ks, vchPubKey))
pubkeys[i].SetPubKey(vchPubKey);
else
throw runtime_error("Error base58 decoding key: "+ks);
}
else // bitcoin address for key in this wallet
// Case 1: bitcoin address and we have full public key:
CBitcoinAddress
address
(
ks
);
if
(
address
.
IsValid
())
{
CBitcoinAddress address(ks);
if
(
address
.
IsScript
())
throw
runtime_error
(
strprintf
(
"%s is a pay-to-script address"
,
ks
.
c_str
()));
if
(
!
pwalletMain
->
GetKey
(
address
,
pubkeys
[
i
]))
throw
runtime_error
(
strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
strprintf
(
"no full public key for address %s"
,
ks
.
c_str
()));
continue
;
}
// Case 2: hex public key
if
(
IsHex
(
ks
))
{
vector
<
unsigned
char
>
vchPubKey
=
ParseHex
(
ks
);
if
(
vchPubKey
.
empty
()
||
!
pubkeys
[
i
].
SetPubKey
(
vchPubKey
))
throw
runtime_error
(
" Invalid public key: "
+
ks
);
// There is approximately a zero percent chance a random
// public key encoded as base58 will consist entirely
// of hex characters.
continue
;
}
// Case 3: base58-encoded public key
{
vector
<
unsigned
char
>
vchPubKey
;
if
(
!
DecodeBase58
(
ks
,
vchPubKey
))
throw
runtime_error
(
"base58 decoding failed: "
+
ks
);
if
(
vchPubKey
.
size
()
<
33
)
// 33 is size of a compressed public key
throw
runtime_error
(
"decoded public key too short: "
+
ks
);
if
(
pubkeys
[
i
].
SetPubKey
(
vchPubKey
))
continue
;
}
throw
runtime_error
(
" Invalid public key: "
+
ks
);
}
// Construct using
OP_EVAL
// Construct using
pay-to-script-hash:
CScript
inner
;
inner
.
SetMultisig
(
nRequired
,
pubkeys
);
uint160
scriptHash
=
Hash160
(
inner
);
CScript
scriptPubKey
;
scriptPubKey.Set
Eval
(inner);
pwalletMain->AddCScript(
scriptHash,
inner);
scriptPubKey
.
Set
PayToScriptHash
(
inner
);
pwalletMain
->
AddCScript
(
inner
);
CBitcoinAddress
address
;
address
.
SetScriptHash160
(
scriptHash
);
...
...
@@ -2681,7 +2702,7 @@ int CommandLineRPC(int argc, char *argv[])
string
s
=
params
[
1
].
get_str
();
Value
v
;
if
(
!
read_string
(
s
,
v
)
||
v
.
type
()
!=
array_type
)
throw runtime_error("
addmultisigaddress:
type mismatch "+s);
throw
runtime_error
(
"type mismatch "
+
s
);
params
[
1
]
=
v
.
get_array
();
}
...
...
This diff is collapsed.
Click to expand it.
src/db.cpp
View file @
fa1ca2af
...
...
@@ -942,7 +942,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
ssKey
>>
hash
;
CScript
script
;
ssValue
>>
script
;
if
(
!
pwallet
->
LoadCScript
(
hash
,
script
))
if
(
!
pwallet
->
LoadCScript
(
script
))
return
DB_CORRUPT
;
}
}
...
...
This diff is collapsed.
Click to expand it.
src/keystore.cpp
View file @
fa1ca2af
...
...
@@ -36,10 +36,10 @@ bool CBasicKeyStore::AddKey(const CKey& key)
return
true
;
}
bool
CBasicKeyStore
::
AddCScript
(
const
uint160
&
hash
,
const
CScript
&
redeemScript
)
bool
CBasicKeyStore
::
AddCScript
(
const
CScript
&
redeemScript
)
{
CRITICAL_BLOCK
(
cs_KeyStore
)
mapScripts
[
h
ash
]
=
redeemScript
;
mapScripts
[
H
ash
160
(
redeemScript
)
]
=
redeemScript
;
return
true
;
}
...
...
This diff is collapsed.
Click to expand it.
src/keystore.h
View file @
fa1ca2af
...
...
@@ -25,7 +25,7 @@ public:
virtual
bool
GetPubKey
(
const
CBitcoinAddress
&
address
,
std
::
vector
<
unsigned
char
>&
vchPubKeyOut
)
const
;
// Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013
virtual
bool
AddCScript
(
const
uint160
&
hash
,
const
CScript
&
redeemScript
)
=
0
;
virtual
bool
AddCScript
(
const
CScript
&
redeemScript
)
=
0
;
virtual
bool
HaveCScript
(
const
uint160
&
hash
)
const
=
0
;
virtual
bool
GetCScript
(
const
uint160
&
hash
,
CScript
&
redeemScriptOut
)
const
=
0
;
...
...
@@ -87,7 +87,7 @@ public:
}
return
false
;
}
virtual
bool
AddCScript
(
const
uint160
&
hash
,
const
CScript
&
redeemScript
);
virtual
bool
AddCScript
(
const
CScript
&
redeemScript
);
virtual
bool
HaveCScript
(
const
uint160
&
hash
)
const
;
virtual
bool
GetCScript
(
const
uint160
&
hash
,
CScript
&
redeemScriptOut
)
const
;
};
...
...
This diff is collapsed.
Click to expand it.
src/main.cpp
View file @
fa1ca2af
...
...
@@ -251,31 +251,31 @@ bool CTransaction::IsStandard() const
BOOST_FOREACH(const CTxIn& txin, vin)
{
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
//
in an OP_EVAL
, which is 3 ~80-byte signatures, 3
//
pay-to-script-hash
, which is 3 ~80-byte signatures, 3
// ~65-byte public keys, plus a few script ops.
if (txin.scriptSig.size() > 500)
return
error("nonstandard txin, size %d is too large\n", txin.scriptSig.size())
;
return
false
;
if (!txin.scriptSig.IsPushOnly())
return
error("nonstandard txin (opcodes other than PUSH): %s", txin.scriptSig.ToString().c_str())
;
return
false
;
}
BOOST_FOREACH(const CTxOut& txout, vout)
if (!::IsStandard(txout.scriptPubKey))
return
error("nonstandard txout: %s", txout.scriptPubKey.ToString().c_str())
;
return
false
;
return true;
}
//
// Check transaction inputs, and make sure any
//
OP_EVAL
transactions are evaluating IsStandard scripts
//
pay-to-script-hash
transactions are evaluating IsStandard scripts
//
// Why bother? To avoid denial-of-service attacks; an attacker
// can submit a standard
DUP
HASH... OP_E
V
AL transaction,
// which will get accepted into blocks. The
script being
//
EVAL'ed
can be anything; an attacker could use a very
// can submit a standard HASH... OP_E
QU
AL transaction,
// which will get accepted into blocks. The
redemption
//
script
can be anything; an attacker could use a very
// expensive-to-check-upon-redemption script like:
// DUP CHECKSIG DROP ... repeated 100 times... OP_1
//
bool CTransaction::AreInputsStandard(std::map<uint256, std::pair<CTxIndex, CTransaction> > mapInputs) const
bool CTransaction::AreInputsStandard(
const
std::map<uint256, std::pair<CTxIndex, CTransaction> >
&
mapInputs) const
{
if (fTestNet)
return true; // Allow non-standard on testnet
...
...
@@ -283,31 +283,51 @@ bool CTransaction::AreInputsStandard(std::map<uint256, std::pair<CTxIndex, CTran
for (int i = 0; i < vin.size(); i++)
{
COutPoint prevout = vin[i].prevout;
assert(mapInputs.count(prevout.hash) > 0);
CTransaction& txPrev = mapInputs[prevout.hash].second;
std::map<uint256, std::pair<CTxIndex, CTransaction> >::const_iterator mi = mapInputs.find(prevout.hash);
if (mi == mapInputs.end())
return false;
const CTransaction& txPrev = (mi->second).second;
assert(prevout.n < txPrev.vout.size());
vector<vector<unsigned char> > vSolutions;
txnouttype whichType;
// get the scriptPubKey corresponding to this input:
CScript& prevScript = txPrev.vout[prevout.n].scriptPubKey;
const
CScript& prevScript = txPrev.vout[prevout.n].scriptPubKey;
if (!Solver(prevScript, whichType, vSolutions))
return
error("nonstandard txin (spending nonstandard txout %s)", prevScript.ToString().c_str())
;
return
false
;
if (whichType == TX_SCRIPTHASH)
{
vector<vector<unsigned char> > stack;
int nUnused;
if (!EvalScript(stack, vin[i].scriptSig, *this, i, 0, true, nUnused))
if (!EvalScript(stack, vin[i].scriptSig, *this, i, 0))
return false;
if (stack.empty())
return false;
CScript subscript(stack.back().begin(), stack.back().end());
if (!::IsStandard(subscript))
return
error("nonstandard txin (nonstandard OP_EVAL subscript %s)", subscript.ToString().c_str())
;
return
false
;
}
}
return true;
}
int
CTransaction::GetLegacySigOpCount() const
{
int nSigOps = 0;
BOOST_FOREACH(const CTxIn& txin, vin)
{
nSigOps += txin.scriptSig.GetSigOpCount(false);
}
BOOST_FOREACH(const CTxOut& txout, vout)
{
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
}
return nSigOps;
}
int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
...
...
@@ -483,7 +503,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
return error("AcceptToMemoryPool() : FetchInputs failed %s", hash.ToString().substr(0,10).c_str());
}
// Check for non-standard
OP_EVALs
in inputs
// Check for non-standard
pay-to-script-hash
in inputs
if (!AreInputsStandard(mapInputs))
return error("AcceptToMemoryPool() : nonstandard transaction input");
...
...
@@ -496,6 +516,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
*pfMissingInputs = true;
return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str());
}
// Checking ECDSA signatures is a CPU bottleneck, so to avoid denial-of-service
// attacks disallow transactions with more than one SigOp per 65 bytes.
// 65 bytes because that is the minimum size of an ECDSA signature
...
...
@@ -967,8 +988,8 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map<uint256, CTxIndex>& mapTes
}
bool CTransaction::ConnectInputs(map<uint256, pair<CTxIndex, CTransaction> > inputs,
map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,
CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int& nSigOpsRet, int64 nMinFee)
map<uint256, CTxIndex>& mapTestPool,
const
CDiskTxPos
&
posThisTx,
const
CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int& nSigOpsRet, int64 nMinFee)
{
// Take over previous transactions' spent pointers
// fBlock is true when this is called from AcceptBlock when a new best-block is added to the blockchain
...
...
@@ -989,33 +1010,31 @@ bool CTransaction::ConnectInputs(map<uint256, pair<CTxIndex, CTransaction> > inp
// If prev is coinbase, check that it's matured
if (txPrev.IsCoinBase())
for (CBlockIndex* pindex = pindexBlock; pindex && pindexBlock->nHeight - pindex->nHeight < COINBASE_MATURITY; pindex = pindex->pprev)
for (
const
CBlockIndex* pindex = pindexBlock; pindex && pindexBlock->nHeight - pindex->nHeight < COINBASE_MATURITY; pindex = pindex->pprev)
if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)
return error("ConnectInputs() : tried to spend coinbase at depth %d", pindexBlock->nHeight - pindex->nHeight);
bool fStrictPayToScriptHash = true;
if (fBlock)
{
// To avoid being on the short end of a block-chain split,
// don't do secondary validation of pay-to-script-hash transactions
// until blocks with timestamps after paytoscripthashtime:
int64 nEvalSwitchTime = GetArg("paytoscripthashtime", 1329264000); // Feb 15, 2012
fStrictPayToScriptHash = (pindexBlock->nTime >= nEvalSwitchTime);
}
// if !fBlock, then always be strict-- don't accept
// invalid-under-new-rules pay-to-script-hash transactions into
// our memory pool (don't relay them, don't include them
// in blocks we mine).
// Skip ECDSA signature verification when connecting blocks (fBlock=true)
// before the last blockchain checkpoint. This is safe because block merkle hashes are
// still computed and checked, and any change will be caught at the next checkpoint.
if (!(fBlock && (nBestHeight < Checkpoints::GetTotalBlocksEstimate())))
{
bool fStrictOpEval = true;
// This code should be removed when OP_EVAL has
// a majority of hashing power on the network.
if (fBlock)
{
// To avoid being on the short end of a block-chain split,
// interpret OP_EVAL as a NO_OP until blocks with timestamps
// after opevaltime:
int64 nEvalSwitchTime = GetArg("opevaltime", 1328054400); // Feb 1, 2012
fStrictOpEval = (pindexBlock->nTime >= nEvalSwitchTime);
}
// if !fBlock, then always be strict-- don't accept
// invalid-under-new-rules OP_EVAL transactions into
// our memory pool (don't relay them, don't include them
// in blocks we mine).
// Verify signature
if (!VerifySignature(txPrev, *this, i,
nSigOpsRet, fStrictOpEval
))
if (!VerifySignature(txPrev, *this, i,
fStrictPayToScriptHash, 0
))
return DoS(100,error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,10).c_str()));
}
...
...
@@ -1030,6 +1049,9 @@ bool CTransaction::ConnectInputs(map<uint256, pair<CTxIndex, CTransaction> > inp
if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
return DoS(100, error("ConnectInputs() : txin values out of range"));
// Calculate sigOps accurately:
nSigOpsRet += txPrev.vout[prevout.n].scriptPubKey.GetSigOpCount(vin[i].scriptSig);
// Mark outpoints as spent
txindex.vSpent[prevout.n] = posThisTx;
...
...
@@ -1090,8 +1112,7 @@ bool CTransaction::ClientConnectInputs()
return false;
// Verify signature
int nUnused = 0;
if (!VerifySignature(txPrev, *this, i, nUnused, false))
if (!VerifySignature(txPrev, *this, i, true, 0))
return error("ConnectInputs() : VerifySignature failed");
///// this is redundant with the mapNextTx stuff, not sure which I want to get rid of
...
...
@@ -1158,10 +1179,17 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
map<uint256, pair<CTxIndex, CTransaction> > mapInputs;
if (!tx.FetchInputs(txdb, mapQueuedChanges, true, false, mapInputs))
return false;
if (!tx.ConnectInputs(mapInputs, mapQueuedChanges, posThisTx, pindex, nFees, true, false, nSigOps))
int nTxOps = 0;
if (!tx.ConnectInputs(mapInputs, mapQueuedChanges, posThisTx, pindex, nFees, true, false, nTxOps))
return false;
nSigOps += nTxOps;
if (nSigOps > MAX_BLOCK_SIGOPS)
return DoS(100, error("ConnectBlock() : too many sigops"));
// There is a different MAX_BLOCK_SIGOPS check in AcceptBlock();
// a block must satisfy both to make it into the best-chain
// (AcceptBlock() is always called before ConnectBlock())
}
// Write queued txindex changes
...
...
@@ -1441,19 +1469,13 @@ bool CBlock::CheckBlock() const
if (!tx.CheckTransaction())
return DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed"));
// This code should be removed when a compatibility-breaking block chain split has passed.
// Compatibility check for old clients that counted sigops differently:
// Pre-pay-to-script-hash (before version 0.6), this is how sigops
// were counted; there is another check in ConnectBlock when
// transaction inputs are fetched to count pay-to-script-hash sigops:
int nSigOps = 0;
BOOST_FOREACH(const CTransaction& tx, vtx)
{
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
nSigOps += txin.scriptSig.GetSigOpCount();
}
BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
nSigOps += txout.scriptPubKey.GetSigOpCount();
}
nSigOps += tx.GetLegacySigOpCount();
}
if (nSigOps > MAX_BLOCK_SIGOPS)
return DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"));
...
...
@@ -2983,7 +3005,8 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
map<uint256, CTxIndex> mapTestPool;
uint64 nBlockSize = 1000;
uint64 nBlockTx = 0;
int nBlockSigOps = 100;
int nBlockSigOps1 = 100; // pre-0.6 count of sigOps
int nBlockSigOps2 = 100; // post-0.6 count of sigOps
while (!mapPriority.empty())
{
// Take highest priority transaction off priority queue
...
...
@@ -2996,6 +3019,11 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN)
continue;
// Legacy limits on sigOps:
int nTxSigOps1 = tx.GetLegacySigOpCount();
if (nBlockSigOps1 + nTxSigOps1 >= MAX_BLOCK_SIGOPS)
continue;
// Transaction fee required depends on block size
bool fAllowFree = (nBlockSize + nTxSize < 4000 || CTransaction::AllowFree(dPriority));
int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree, GMF_BLOCK);
...
...
@@ -3006,18 +3034,20 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
map<uint256, pair<CTxIndex, CTransaction> > mapInputs;
if (!tx.FetchInputs(txdb, mapTestPoolTmp, false, true, mapInputs))
continue;
int nTxSigOps = 0;
if (!tx.ConnectInputs(mapInputs, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nTxSigOps, nMinFee))
int nTxSigOps2 = 0;
if (!tx.ConnectInputs(mapInputs, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nTxSigOps2, nMinFee))
continue;
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
if (nBlockSigOps
2
+ nTxSigOps
2
>= MAX_BLOCK_SIGOPS)
continue;
swap(mapTestPool, mapTestPoolTmp);
// Added
pblock->vtx.push_back(tx);
nBlockSize += nTxSize;
nBlockSigOps += nTxSigOps;
++nBlockTx;
nBlockSigOps1 += nTxSigOps1;
nBlockSigOps2 += nTxSigOps2;
// Add transactions that depend on this one to the priority queue
uint256 hash = tx.GetHash();
...
...
@@ -3065,10 +3095,10 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
++nExtraNonce;
pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nTime << CBigNum(nExtraNonce);
// Put "
OP_EVAL
" in the coinbase so everybody can tell when
// Put "
/P2SH/
" in the coinbase so everybody can tell when
// a majority of miners support it
const char* p
OpEvalName = GetOpName(OP_EVAL)
;
pblock->vtx[0].vin[0].scriptSig += CScript() << std::vector<unsigned char>(p
OpEvalName, pOpEvalName+strlen(pOpEvalName
));
const char* p
szP2SH = "/P2SH/"
;
pblock->vtx[0].vin[0].scriptSig += CScript() << std::vector<unsigned char>(p
szP2SH, pszP2SH+strlen(pszP2SH
));
assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100);
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
...
...
This diff is collapsed.
Click to expand it.
src/main.h
View file @
fa1ca2af
...
...
@@ -503,7 +503,9 @@ public:
}
bool
IsStandard
()
const
;
bool
AreInputsStandard
(
std
::
map
<
uint256
,
std
::
pair
<
CTxIndex
,
CTransaction
>
>
mapInputs
)
const
;
bool
AreInputsStandard
(
const
std
::
map
<
uint256
,
std
::
pair
<
CTxIndex
,
CTransaction
>
>&
mapInputs
)
const
;
int
GetLegacySigOpCount
()
const
;
int64
GetValueOut
()
const
{
...
...
@@ -636,8 +638,8 @@ public:
bool
FetchInputs
(
CTxDB
&
txdb
,
const
std
::
map
<
uint256
,
CTxIndex
>&
mapTestPool
,
bool
fBlock
,
bool
fMiner
,
std
::
map
<
uint256
,
std
::
pair
<
CTxIndex
,
CTransaction
>
>&
inputsRet
);
bool
ConnectInputs
(
std
::
map
<
uint256
,
std
::
pair
<
CTxIndex
,
CTransaction
>
>
inputs
,
std
::
map
<
uint256
,
CTxIndex
>&
mapTestPool
,
CDiskTxPos
posThisTx
,
CBlockIndex
*
pindexBlock
,
int64
&
nFees
,
bool
fBlock
,
bool
fMiner
,
int
&
nSigOpsRet
,
int64
nMinFee
=
0
);
std
::
map
<
uint256
,
CTxIndex
>&
mapTestPool
,
const
CDiskTxPos
&
posThisTx
,
const
CBlockIndex
*
pindexBlock
,
int64
&
nFees
,
bool
fBlock
,
bool
fMiner
,
int
&
nSigOpsRet
,
int64
nMinFee
=
0
);
bool
ClientConnectInputs
();
bool
CheckTransaction
()
const
;
bool
AcceptToMemoryPool
(
CTxDB
&
txdb
,
bool
fCheckInputs
=
true
,
bool
*
pfMissingInputs
=
NULL
);
...
...
This diff is collapsed.
Click to expand it.
src/script.cpp
View file @
fa1ca2af
...
...
@@ -203,10 +203,8 @@ const char* GetOpName(opcodetype opcode)
case
OP_CHECKMULTISIG
:
return
"OP_CHECKMULTISIG"
;
case
OP_CHECKMULTISIGVERIFY
:
return
"OP_CHECKMULTISIGVERIFY"
;
// meta
case
OP_EVAL
:
return
"OP_EVAL"
;
// expanson
case
OP_NOP1
:
return
"OP_NOP1"
;
case
OP_NOP2
:
return
"OP_NOP2"
;
case
OP_NOP3
:
return
"OP_NOP3"
;
case
OP_NOP4
:
return
"OP_NOP4"
;
...
...
@@ -220,7 +218,6 @@ const char* GetOpName(opcodetype opcode)
// template matching params
case
OP_SCRIPTHASH
:
return
"OP_SCRIPTHASH"
;
case
OP_PUBKEYHASH
:
return
"OP_PUBKEYHASH"
;
case
OP_PUBKEY
:
return
"OP_PUBKEY"
;
...
...
@@ -230,26 +227,20 @@ const char* GetOpName(opcodetype opcode)
}
}
//
// Returns true if script is valid.
//
bool
EvalScriptInner
(
vector
<
vector
<
unsigned
char
>
>&
stack
,
const
CScript
&
script
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
nHashType
,
CScript
::
const_iterator
pbegincodehash
,
CScript
::
const_iterator
pendcodehash
,
int
&
nOpCount
,
int
&
nSigOpCount
,
bool
fStrictOpEval
,
int
nRecurseDepth
)
bool
EvalScript
(
vector
<
vector
<
unsigned
char
>
>&
stack
,
const
CScript
&
script
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
nHashType
)
{
CAutoBN_CTX
pctx
;
CScript
::
const_iterator
pc
=
script
.
begin
();
CScript
::
const_iterator
pend
=
script
.
end
();
CScript
::
const_iterator
pbegincodehash
=
script
.
begin
();
opcodetype
opcode
;
valtype
vchPushValue
;
vector
<
bool
>
vfExec
;
vector
<
valtype
>
altstack
;
if
(
script
.
size
()
>
10000
)
return
false
;
int
nOpCount
=
0
;
// Limit OP_EVAL recursion
if
(
nRecurseDepth
>
2
)
return
false
;
try
{
...
...
@@ -321,7 +312,7 @@ bool EvalScriptInner(vector<vector<unsigned char> >& stack, const CScript& scrip
// Control
//
case
OP_NOP
:
case
OP_NOP2
:
case
OP_NOP3
:
case
OP_NOP4
:
case
OP_NOP5
:
case
OP_NOP1
:
case
OP_NOP2
:
case
OP_NOP3
:
case
OP_NOP4
:
case
OP_NOP5
:
case
OP_NOP6
:
case
OP_NOP7
:
case
OP_NOP8
:
case
OP_NOP9
:
case
OP_NOP10
:
break
;
...
...
@@ -917,13 +908,12 @@ bool EvalScriptInner(vector<vector<unsigned char> >& stack, const CScript& scrip
//PrintHex(vchPubKey.begin(), vchPubKey.end(), "pubkey: %s\n");
// Subset of script starting at the most recent codeseparator
CScript
scriptCode
(
pbegincodehash
,
pend
codehash
);
CScript
scriptCode
(
pbegincodehash
,
pend
);
// Drop the signature, since there's no way for a signature to sign itself
scriptCode
.
FindAndDelete
(
CScript
(
vchSig
));
bool
fSuccess
=
CheckSig
(
vchSig
,
vchPubKey
,
scriptCode
,
txTo
,
nIn
,
nHashType
);
nSigOpCount
++
;
popstack
(
stack
);
popstack
(
stack
);
...
...
@@ -967,7 +957,7 @@ bool EvalScriptInner(vector<vector<unsigned char> >& stack, const CScript& scrip
return
false
;
// Subset of script starting at the most recent codeseparator
CScript
scriptCode
(
pbegincodehash
,
pend
codehash
);
CScript
scriptCode
(
pbegincodehash
,
pend
);
// Drop the signatures, since there's no way for a signature to sign itself
for
(
int
k
=
0
;
k
<
nSigsCount
;
k
++
)
...
...
@@ -990,7 +980,6 @@ bool EvalScriptInner(vector<vector<unsigned char> >& stack, const CScript& scrip
}
ikey
++
;
nKeysCount
--
;
nSigOpCount
++
;
// If there are more signatures left than keys left,
// then too many signatures have failed
...
...
@@ -1012,32 +1001,6 @@ bool EvalScriptInner(vector<vector<unsigned char> >& stack, const CScript& scrip
}
break
;
case
OP_EVAL
:
{
if
(
!
fStrictOpEval
)
break
;
// Act as a NO_OP
// Evaluate the top item on the stack as a Script
// [serialized script ] -- [result(s) of executing script]
if
(
stack
.
size
()
<
1
)
return
false
;
valtype
&
vchScript
=
stacktop
(
-
1
);
CScript
subscript
(
vchScript
.
begin
(),
vchScript
.
end
());
popstack
(
stack
);
// Codeseparators not allowed; they don't make sense 'inside' an OP_EVAL, because
// their purpose is to change which parts of the scriptPubKey script is copied
// and signed by OP_CHECKSIG, but OP_EVAl'ed code is in the scriptSig, not the scriptPubKey.
if
(
subscript
.
Find
(
OP_CODESEPARATOR
))
return
false
;
if
(
!
EvalScriptInner
(
stack
,
subscript
,
txTo
,
nIn
,
nHashType
,
pbegincodehash
,
pendcodehash
,
nOpCount
,
nSigOpCount
,
fStrictOpEval
,
nRecurseDepth
+
1
))
return
false
;
}
break
;
default:
return
false
;
}
...
...
@@ -1059,18 +1022,6 @@ bool EvalScriptInner(vector<vector<unsigned char> >& stack, const CScript& scrip
return
true
;
}
bool
EvalScript
(
vector
<
vector
<
unsigned
char
>
>&
stack
,
const
CScript
&
script
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
nHashType
,
bool
fStrictOpEval
,
int
&
nSigOpCountRet
)
{
CScript
::
const_iterator
pbegincodehash
=
script
.
begin
();
CScript
::
const_iterator
pendcodehash
=
script
.
end
();
int
nOpCount
=
0
;
return
EvalScriptInner
(
stack
,
script
,
txTo
,
nIn
,
nHashType
,
pbegincodehash
,
pendcodehash
,
nOpCount
,
nSigOpCountRet
,
fStrictOpEval
,
0
);
}
...
...
@@ -1186,10 +1137,16 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
// Sender provides N pubkeys, receivers provides M signatures
mTemplates
.
insert
(
make_pair
(
TX_MULTISIG
,
CScript
()
<<
OP_SMALLINTEGER
<<
OP_PUBKEYS
<<
OP_SMALLINTEGER
<<
OP_CHECKMULTISIG
));
}
// Sender provides script hash, receiver provides script and
// as many signatures as required to satisfy script
mTemplates
.
insert
(
make_pair
(
TX_SCRIPTHASH
,
CScript
()
<<
OP_DUP
<<
OP_HASH160
<<
OP_SCRIPTHASH
<<
OP_EQUALVERIFY
<<
OP_EVAL
));
// Shortcut for pay-to-script-hash, which are more constrained than the other types:
// it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
if
(
scriptPubKey
.
IsPayToScriptHash
())
{
typeRet
=
TX_SCRIPTHASH
;
vector
<
unsigned
char
>
hashBytes
(
scriptPubKey
.
begin
()
+
2
,
scriptPubKey
.
begin
()
+
22
);
vSolutionsRet
.
push_back
(
hashBytes
);
return
true
;
}
// Scan templates
...
...
@@ -1253,12 +1210,6 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
break
;
vSolutionsRet
.
push_back
(
vch1
);
}
else
if
(
opcode2
==
OP_SCRIPTHASH
)
{
if
(
vch1
.
size
()
!=
sizeof
(
uint160
))
break
;
vSolutionsRet
.
push_back
(
vch1
);
}
else
if
(
opcode2
==
OP_SMALLINTEGER
)
{
// Single-byte small integer pushed onto vSolutions
if
(
opcode1
==
OP_0
||
...
...
@@ -1319,21 +1270,21 @@ bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint2
//
// Sign scriptPubKey with private keys stored in keystore, given transaction hash and hash type.
// Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed).
// Returns true if scriptPubKey could be completely satisified.
// Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
// unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
// Returns false if scriptPubKey could not be completely satisified.
//
bool
Solver
(
const
CKeyStore
&
keystore
,
const
CScript
&
scriptPubKey
,
uint256
hash
,
int
nHashType
,
CScript
&
scriptSigRet
)
bool
Solver
(
const
CKeyStore
&
keystore
,
const
CScript
&
scriptPubKey
,
uint256
hash
,
int
nHashType
,
CScript
&
scriptSigRet
,
txnouttype
&
whichTypeRet
)
{
scriptSigRet
.
clear
();
txnouttype
whichType
;
vector
<
valtype
>
vSolutions
;
if
(
!
Solver
(
scriptPubKey
,
whichType
,
vSolutions
))
if
(
!
Solver
(
scriptPubKey
,
whichType
Ret
,
vSolutions
))
return
false
;
CBitcoinAddress
address
;
CScript
subscript
;
switch
(
whichType
)
switch
(
whichTypeRet
)
{
case
TX_NONSTANDARD
:
return
false
;
...
...
@@ -1350,21 +1301,15 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
keystore
.
GetPubKey
(
address
,
vch
);
scriptSigRet
<<
vch
;
}
b
re
ak
;
re
turn
true
;
case
TX_SCRIPTHASH
:
if
(
!
keystore
.
GetCScript
(
uint160
(
vSolutions
[
0
]),
subscript
))
return
false
;
if
(
!
Solver
(
keystore
,
subscript
,
hash
,
nHashType
,
scriptSigRet
))
return
false
;
if
(
hash
!=
0
)
// static_cast to get vector.operator<< instead of CScript.operator<<
scriptSigRet
<<
static_cast
<
valtype
>
(
subscript
);
// signatures AND serialized script
break
;
return
keystore
.
GetCScript
(
uint160
(
vSolutions
[
0
]),
scriptSigRet
);
case
TX_MULTISIG
:
scriptSigRet
<<
OP_0
;
// workaround CHECKMULTISIG bug
return
(
SignN
(
vSolutions
,
keystore
,
hash
,
nHashType
,
scriptSigRet
));
}
return
tru
e
;
return
fals
e
;
}
...
...
@@ -1503,25 +1448,40 @@ bool ExtractAddresses(const CScript& scriptPubKey, txnouttype& typeRet, vector<C
return
true
;
}
bool
VerifyScript
(
const
CScript
&
scriptSig
,
const
CScript
&
scriptPubKey
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
&
nSigOpCountRet
,
int
nHashType
,
bool
fStrictOpEval
)
bool
VerifyScript
(
const
CScript
&
scriptSig
,
const
CScript
&
scriptPubKey
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
bool
fValidatePayToScriptHash
,
int
nHashType
)
{
vector
<
vector
<
unsigned
char
>
>
stack
;
if
(
!
EvalScript
(
stack
,
scriptSig
,
txTo
,
nIn
,
nHashType
,
fStrictOpEval
,
nSigOpCountRet
))
vector
<
vector
<
unsigned
char
>
>
stack
,
stackCopy
;
if
(
!
EvalScript
(
stack
,
scriptSig
,
txTo
,
nIn
,
nHashType
))
return
false
;
if
(
!
EvalScript
(
stack
,
scriptPubKey
,
txTo
,
nIn
,
nHashType
,
fStrictOpEval
,
nSigOpCountRet
))
if
(
fValidatePayToScriptHash
)
stackCopy
=
stack
;
if
(
!
EvalScript
(
stack
,
scriptPubKey
,
txTo
,
nIn
,
nHashType
))
return
false
;
if
(
stack
.
empty
())
return
false
;
bool
fResult
=
CastToBool
(
stack
.
back
());
// This code should be removed when a compatibility-breaking block chain split has passed.
// Special check for OP_EVAL backwards-compatibility: if scriptPubKey or scriptSig contains
// OP_EVAL, then result must be identical if OP_EVAL is treated as a no-op:
if
(
fResult
&&
fStrictOpEval
&&
(
scriptPubKey
.
Find
(
OP_EVAL
)
||
scriptSig
.
Find
(
OP_EVAL
)))
return
VerifyScript
(
scriptSig
,
scriptPubKey
,
txTo
,
nIn
,
nSigOpCountRet
,
nHashType
,
false
);
if
(
CastToBool
(
stack
.
back
())
==
false
)
return
false
;
// Additional validation for spend-to-script-hash transactions:
if
(
fValidatePayToScriptHash
&&
scriptPubKey
.
IsPayToScriptHash
())
{
if
(
!
scriptSig
.
IsPushOnly
())
// scriptSig must be literals-only
return
false
;
// or validation fails
const
valtype
&
pubKeySerialized
=
stackCopy
.
back
();
CScript
pubKey2
(
pubKeySerialized
.
begin
(),
pubKeySerialized
.
end
());
popstack
(
stackCopy
);
return
fResult
;
if
(
!
EvalScript
(
stackCopy
,
pubKey2
,
txTo
,
nIn
,
nHashType
))
return
false
;
if
(
stackCopy
.
empty
())
return
false
;
return
CastToBool
(
stackCopy
.
back
());
}
return
true
;
}
...
...
@@ -1536,19 +1496,36 @@ bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTrans
// The checksig op will also drop the signatures from its hash.
uint256
hash
=
SignatureHash
(
txout
.
scriptPubKey
,
txTo
,
nIn
,
nHashType
);
if
(
!
Solver
(
keystore
,
txout
.
scriptPubKey
,
hash
,
nHashType
,
txin
.
scriptSig
))
txnouttype
whichType
;
if
(
!
Solver
(
keystore
,
txout
.
scriptPubKey
,
hash
,
nHashType
,
txin
.
scriptSig
,
whichType
))
return
false
;
if
(
whichType
==
TX_SCRIPTHASH
)
{
// Solver returns the subscript that need to be evaluated;
// the final scriptSig is the signatures from that
// and then the serialized subscript:
CScript
subscript
=
txin
.
scriptSig
;
// Recompute txn hash using subscript in place of scriptPubKey:
uint256
hash2
=
SignatureHash
(
subscript
,
txTo
,
nIn
,
nHashType
);
txnouttype
subType
;
if
(
!
Solver
(
keystore
,
subscript
,
hash2
,
nHashType
,
txin
.
scriptSig
,
subType
))
return
false
;
if
(
subType
==
TX_SCRIPTHASH
)
return
false
;
txin
.
scriptSig
<<
static_cast
<
valtype
>
(
subscript
);
// Append serialized subscript
}
// Test solution
int
nUnused
=
0
;
if
(
!
VerifyScript
(
txin
.
scriptSig
,
txout
.
scriptPubKey
,
txTo
,
nIn
,
nUnused
,
0
,
true
))
if
(
!
VerifyScript
(
txin
.
scriptSig
,
txout
.
scriptPubKey
,
txTo
,
nIn
,
true
,
0
))
return
false
;
return
true
;
}
bool
VerifySignature
(
const
CTransaction
&
txFrom
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
&
nSigOpCountRet
,
int
nHashType
,
bool
fStrictOpEval
)
bool
VerifySignature
(
const
CTransaction
&
txFrom
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
bool
fValidatePayToScriptHash
,
int
nHashType
)
{
assert
(
nIn
<
txTo
.
vin
.
size
());
const
CTxIn
&
txin
=
txTo
.
vin
[
nIn
];
...
...
@@ -1559,17 +1536,74 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig
if
(
txin
.
prevout
.
hash
!=
txFrom
.
GetHash
())
return
false
;
if
(
!
VerifyScript
(
txin
.
scriptSig
,
txout
.
scriptPubKey
,
txTo
,
nIn
,
nSigOpCountRet
,
nHashType
,
fStrictOpEval
))
if
(
!
VerifyScript
(
txin
.
scriptSig
,
txout
.
scriptPubKey
,
txTo
,
nIn
,
fValidatePayToScriptHash
,
nHashType
))
return
false
;
return
true
;
}
int
CScript
::
GetSigOpCount
(
bool
fAccurate
)
const
{
int
n
=
0
;
const_iterator
pc
=
begin
();
opcodetype
lastOpcode
=
OP_INVALIDOPCODE
;
while
(
pc
<
end
())
{
opcodetype
opcode
;
if
(
!
GetOp
(
pc
,
opcode
))
break
;
if
(
opcode
==
OP_CHECKSIG
||
opcode
==
OP_CHECKSIGVERIFY
)
n
++
;
else
if
(
opcode
==
OP_CHECKMULTISIG
||
opcode
==
OP_CHECKMULTISIGVERIFY
)
{
if
(
fAccurate
&&
lastOpcode
>=
OP_1
&&
lastOpcode
<=
OP_16
)
n
+=
DecodeOP_N
(
lastOpcode
);
else
n
+=
20
;
}
lastOpcode
=
opcode
;
}
return
n
;
}
int
CScript
::
GetSigOpCount
(
const
CScript
&
scriptSig
)
const
{
if
(
!
IsPayToScriptHash
())
return
GetSigOpCount
(
true
);
// This is a pay-to-script-hash scriptPubKey;
// get the last item that the scriptSig
// pushes onto the stack:
const_iterator
pc
=
scriptSig
.
begin
();
vector
<
unsigned
char
>
data
;
while
(
pc
<
scriptSig
.
end
())
{
opcodetype
opcode
;
if
(
!
scriptSig
.
GetOp
(
pc
,
opcode
,
data
))
return
0
;
if
(
opcode
>
OP_16
)
return
0
;
}
/// ... and return it's opcount:
CScript
subscript
(
data
.
begin
(),
data
.
end
());
return
subscript
.
GetSigOpCount
(
true
);
}
bool
CScript
::
IsPayToScriptHash
()
const
{
// Extra-fast test for pay-to-script-hash CScripts:
return
(
this
->
size
()
==
23
&&
this
->
at
(
0
)
==
OP_HASH160
&&
this
->
at
(
1
)
==
0x14
&&
this
->
at
(
22
)
==
OP_EQUAL
);
}
void
CScript
::
SetBitcoinAddress
(
const
CBitcoinAddress
&
address
)
{
this
->
clear
();
if
(
address
.
IsScript
())
*
this
<<
OP_DUP
<<
OP_HASH160
<<
address
.
GetHash160
()
<<
OP_EQUAL
VERIFY
<<
OP_EVAL
;
*
this
<<
OP_HASH160
<<
address
.
GetHash160
()
<<
OP_EQUAL
;
else
*
this
<<
OP_DUP
<<
OP_HASH160
<<
address
.
GetHash160
()
<<
OP_EQUALVERIFY
<<
OP_CHECKSIG
;
}
...
...
@@ -1584,10 +1618,10 @@ void CScript::SetMultisig(int nRequired, const std::vector<CKey>& keys)
*
this
<<
EncodeOP_N
(
keys
.
size
())
<<
OP_CHECKMULTISIG
;
}
void
CScript
::
Set
Eval
(
const
CScript
&
subscript
)
void
CScript
::
Set
PayToScriptHash
(
const
CScript
&
subscript
)
{
assert
(
!
subscript
.
empty
());
uint160
subscriptHash
=
Hash160
(
subscript
);
this
->
clear
();
*
this
<<
OP_DUP
<<
OP_HASH160
<<
subscriptHash
<<
OP_EQUAL
VERIFY
<<
OP_EVAL
;
*
this
<<
OP_HASH160
<<
subscriptHash
<<
OP_EQUAL
;
}
This diff is collapsed.
Click to expand it.
src/script.h
View file @
fa1ca2af
...
...
@@ -158,10 +158,8 @@ enum opcodetype
OP_CHECKMULTISIG
,
OP_CHECKMULTISIGVERIFY
,
// meta
OP_EVAL
,
// Was OP_NOP1
// expansion
OP_NOP1
,
OP_NOP2
,
OP_NOP3
,
OP_NOP4
,
...
...
@@ -177,7 +175,6 @@ enum opcodetype
// template matching params
OP_SMALLINTEGER
=
0xfa
,
OP_PUBKEYS
=
0xfb
,
OP_SCRIPTHASH
=
0xfc
,
OP_PUBKEYHASH
=
0xfd
,
OP_PUBKEY
=
0xfe
,
...
...
@@ -485,24 +482,18 @@ public:
return
nFound
;
}
// This method should be removed when a compatibility-breaking block chain split has passed.
// Compatibility method for old clients that count sigops differently:
int
GetSigOpCount
()
const
{
int
n
=
0
;
const_iterator
pc
=
begin
();
while
(
pc
<
end
())
{
opcodetype
opcode
;
if
(
!
GetOp
(
pc
,
opcode
))
break
;
if
(
opcode
==
OP_CHECKSIG
||
opcode
==
OP_CHECKSIGVERIFY
)
n
++
;
else
if
(
opcode
==
OP_CHECKMULTISIG
||
opcode
==
OP_CHECKMULTISIGVERIFY
)
n
+=
20
;
}
return
n
;
}
// Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
// as 20 sigops. With pay-to-script-hash, that changed:
// CHECKMULTISIGs serialized in scriptSigs are
// counted more accurately, assuming they are of the form
// ... OP_N CHECKMULTISIG ...
int
GetSigOpCount
(
bool
fAccurate
)
const
;
// Accurately count sigOps, including sigOps in
// pay-to-script-hash transactions:
int
GetSigOpCount
(
const
CScript
&
scriptSig
)
const
;
bool
IsPayToScriptHash
()
const
;
// Called by CTransaction::IsStandard
bool
IsPushOnly
()
const
...
...
@@ -526,7 +517,7 @@ public:
SetBitcoinAddress
(
CBitcoinAddress
(
vchPubKey
));
}
void
SetMultisig
(
int
nRequired
,
const
std
::
vector
<
CKey
>&
keys
);
void
Set
Eval
(
const
CScript
&
subscript
);
void
Set
PayToScriptHash
(
const
CScript
&
subscript
);
void
PrintHex
()
const
...
...
@@ -567,14 +558,13 @@ public:
bool
EvalScript
(
std
::
vector
<
std
::
vector
<
unsigned
char
>
>&
stack
,
const
CScript
&
script
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
nHashType
,
bool
fStrictOpEval
,
int
&
nSigOpCountRet
);
bool
EvalScript
(
std
::
vector
<
std
::
vector
<
unsigned
char
>
>&
stack
,
const
CScript
&
script
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
nHashType
);
bool
Solver
(
const
CScript
&
scriptPubKey
,
txnouttype
&
typeRet
,
std
::
vector
<
std
::
vector
<
unsigned
char
>
>&
vSolutionsRet
);
bool
IsStandard
(
const
CScript
&
scriptPubKey
);
bool
IsMine
(
const
CKeyStore
&
keystore
,
const
CScript
&
scriptPubKey
);
bool
ExtractAddress
(
const
CScript
&
scriptPubKey
,
CBitcoinAddress
&
addressRet
);
bool
ExtractAddresses
(
const
CScript
&
scriptPubKey
,
txnouttype
&
typeRet
,
std
::
vector
<
CBitcoinAddress
>&
addressRet
,
int
&
nRequiredRet
);
bool
SignSignature
(
const
CKeyStore
&
keystore
,
const
CTransaction
&
txFrom
,
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
nHashType
=
SIGHASH_ALL
);
bool
VerifySignature
(
const
CTransaction
&
txFrom
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
&
nSigOpCountRet
,
int
nHashType
=
0
,
bool
fStrictOpEval
=
tru
e
);
bool
VerifySignature
(
const
CTransaction
&
txFrom
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
bool
fValidatePayToScriptHash
,
int
nHashTyp
e
);
#endif
This diff is collapsed.
Click to expand it.
src/test/multisig_tests.cpp
View file @
fa1ca2af
...
...
@@ -20,8 +20,8 @@ using namespace boost::assign;
typedef
vector
<
unsigned
char
>
valtype
;
extern
uint256
SignatureHash
(
CScript
scriptCode
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
nHashType
);
extern
bool
VerifyScript
(
const
CScript
&
scriptSig
,
const
CScript
&
scriptPubKey
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
&
nSigOpCount
,
int
nHashType
,
bool
fStrictOpEval
);
extern
bool
VerifyScript
(
const
CScript
&
scriptSig
,
const
CScript
&
scriptPubKey
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
bool
fValidatePayToScriptHash
,
int
nHashType
);
BOOST_AUTO_TEST_SUITE
(
multisig_tests
)
...
...
@@ -75,25 +75,24 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
vector
<
CKey
>
keys
;
CScript
s
;
int
nUnused
=
0
;
// Test a AND b:
keys
.
clear
();
keys
+=
key
[
0
],
key
[
1
];
// magic operator+= from boost.assign
s
=
sign_multisig
(
a_and_b
,
keys
,
txTo
[
0
],
0
);
BOOST_CHECK
(
VerifyScript
(
s
,
a_and_b
,
txTo
[
0
],
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
VerifyScript
(
s
,
a_and_b
,
txTo
[
0
],
0
,
true
,
0
));
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
keys
.
clear
();
keys
+=
key
[
i
];
s
=
sign_multisig
(
a_and_b
,
keys
,
txTo
[
0
],
0
);
BOOST_CHECK_MESSAGE
(
!
VerifyScript
(
s
,
a_and_b
,
txTo
[
0
],
0
,
nUnused
,
0
,
true
),
strprintf
(
"a&b 1: %d"
,
i
));
BOOST_CHECK_MESSAGE
(
!
VerifyScript
(
s
,
a_and_b
,
txTo
[
0
],
0
,
true
,
0
),
strprintf
(
"a&b 1: %d"
,
i
));
keys
.
clear
();
keys
+=
key
[
1
],
key
[
i
];
s
=
sign_multisig
(
a_and_b
,
keys
,
txTo
[
0
],
0
);
BOOST_CHECK_MESSAGE
(
!
VerifyScript
(
s
,
a_and_b
,
txTo
[
0
],
0
,
nUnused
,
0
,
true
),
strprintf
(
"a&b 2: %d"
,
i
));
BOOST_CHECK_MESSAGE
(
!
VerifyScript
(
s
,
a_and_b
,
txTo
[
0
],
0
,
true
,
0
),
strprintf
(
"a&b 2: %d"
,
i
));
}
// Test a OR b:
...
...
@@ -103,16 +102,16 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys
+=
key
[
i
];
s
=
sign_multisig
(
a_or_b
,
keys
,
txTo
[
1
],
0
);
if
(
i
==
0
||
i
==
1
)
BOOST_CHECK_MESSAGE
(
VerifyScript
(
s
,
a_or_b
,
txTo
[
1
],
0
,
nUnused
,
0
,
true
),
strprintf
(
"a|b: %d"
,
i
));
BOOST_CHECK_MESSAGE
(
VerifyScript
(
s
,
a_or_b
,
txTo
[
1
],
0
,
true
,
0
),
strprintf
(
"a|b: %d"
,
i
));
else
BOOST_CHECK_MESSAGE
(
!
VerifyScript
(
s
,
a_or_b
,
txTo
[
1
],
0
,
nUnused
,
0
,
true
),
strprintf
(
"a|b: %d"
,
i
));
BOOST_CHECK_MESSAGE
(
!
VerifyScript
(
s
,
a_or_b
,
txTo
[
1
],
0
,
true
,
0
),
strprintf
(
"a|b: %d"
,
i
));
}
s
.
clear
();
s
<<
OP_0
<<
OP_0
;
BOOST_CHECK
(
!
VerifyScript
(
s
,
a_or_b
,
txTo
[
1
],
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifyScript
(
s
,
a_or_b
,
txTo
[
1
],
0
,
true
,
0
));
s
.
clear
();
s
<<
OP_0
<<
OP_1
;
BOOST_CHECK
(
!
VerifyScript
(
s
,
a_or_b
,
txTo
[
1
],
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifyScript
(
s
,
a_or_b
,
txTo
[
1
],
0
,
true
,
0
));
for
(
int
i
=
0
;
i
<
4
;
i
++
)
...
...
@@ -122,9 +121,9 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys
+=
key
[
i
],
key
[
j
];
s
=
sign_multisig
(
escrow
,
keys
,
txTo
[
2
],
0
);
if
(
i
<
j
&&
i
<
3
&&
j
<
3
)
BOOST_CHECK_MESSAGE
(
VerifyScript
(
s
,
escrow
,
txTo
[
2
],
0
,
nUnused
,
0
,
true
),
strprintf
(
"escrow 1: %d %d"
,
i
,
j
));
BOOST_CHECK_MESSAGE
(
VerifyScript
(
s
,
escrow
,
txTo
[
2
],
0
,
true
,
0
),
strprintf
(
"escrow 1: %d %d"
,
i
,
j
));
else
BOOST_CHECK_MESSAGE
(
!
VerifyScript
(
s
,
escrow
,
txTo
[
2
],
0
,
nUnused
,
0
,
true
),
strprintf
(
"escrow 2: %d %d"
,
i
,
j
));
BOOST_CHECK_MESSAGE
(
!
VerifyScript
(
s
,
escrow
,
txTo
[
2
],
0
,
true
,
0
),
strprintf
(
"escrow 2: %d %d"
,
i
,
j
));
}
}
...
...
This diff is collapsed.
Click to expand it.
src/test/rpc_tests.cpp
0 → 100644
View file @
fa1ca2af
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
#include "base58.h"
#include "util.h"
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"
using
namespace
std
;
using
namespace
json_spirit
;
typedef
Value
(
*
rpcfn_type
)(
const
Array
&
params
,
bool
fHelp
);
extern
map
<
string
,
rpcfn_type
>
mapCallTable
;
BOOST_AUTO_TEST_SUITE
(
rpc_tests
)
static
Array
createArgs
(
int
nRequired
,
const
char
*
address1
=
NULL
,
const
char
*
address2
=
NULL
)
{
Array
result
;
result
.
push_back
(
nRequired
);
Array
addresses
;
if
(
address1
)
addresses
.
push_back
(
address1
);
if
(
address2
)
addresses
.
push_back
(
address1
);
result
.
push_back
(
addresses
);
return
result
;
}
// This can be removed this when addmultisigaddress is enabled on main net:
struct
TestNetFixture
{
TestNetFixture
()
{
fTestNet
=
true
;
}
~
TestNetFixture
()
{
fTestNet
=
false
;
}
};
BOOST_FIXTURE_TEST_CASE
(
rpc_addmultisig
,
TestNetFixture
)
{
rpcfn_type
addmultisig
=
mapCallTable
[
"addmultisigaddress"
];
// old, 65-byte-long:
const
char
*
address1Hex
=
"0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8"
;
// new, compressed:
const
char
*
address2Hex
=
"0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4"
;
Value
v
;
CBitcoinAddress
address
;
BOOST_CHECK_NO_THROW
(
v
=
addmultisig
(
createArgs
(
1
,
address1Hex
),
false
));
address
.
SetString
(
v
.
get_str
());
BOOST_CHECK
(
address
.
IsValid
()
&&
address
.
IsScript
());
BOOST_CHECK_NO_THROW
(
v
=
addmultisig
(
createArgs
(
1
,
address1Hex
,
address2Hex
),
false
));
address
.
SetString
(
v
.
get_str
());
BOOST_CHECK
(
address
.
IsValid
()
&&
address
.
IsScript
());
BOOST_CHECK_NO_THROW
(
v
=
addmultisig
(
createArgs
(
2
,
address1Hex
,
address2Hex
),
false
));
address
.
SetString
(
v
.
get_str
());
BOOST_CHECK
(
address
.
IsValid
()
&&
address
.
IsScript
());
BOOST_CHECK_THROW
(
addmultisig
(
createArgs
(
0
),
false
),
runtime_error
);
BOOST_CHECK_THROW
(
addmultisig
(
createArgs
(
1
),
false
),
runtime_error
);
BOOST_CHECK_THROW
(
addmultisig
(
createArgs
(
2
,
address1Hex
),
false
),
runtime_error
);
BOOST_CHECK_THROW
(
addmultisig
(
createArgs
(
1
,
""
),
false
),
runtime_error
);
BOOST_CHECK_THROW
(
addmultisig
(
createArgs
(
1
,
"NotAValidPubkey"
),
false
),
runtime_error
);
string
short1
(
address1Hex
,
address1Hex
+
sizeof
(
address1Hex
)
-
2
);
// last byte missing
BOOST_CHECK_THROW
(
addmultisig
(
createArgs
(
2
,
short1
.
c_str
()),
false
),
runtime_error
);
string
short2
(
address1Hex
+
2
,
address1Hex
+
sizeof
(
address1Hex
));
// first byte missing
BOOST_CHECK_THROW
(
addmultisig
(
createArgs
(
2
,
short2
.
c_str
()),
false
),
runtime_error
);
}
BOOST_AUTO_TEST_SUITE_END
()
This diff is collapsed.
Click to expand it.
src/test/script_
op_eval
_tests.cpp
→
src/test/script_
P2SH
_tests.cpp
View file @
fa1ca2af
...
...
@@ -13,16 +13,44 @@ using namespace std;
// Test routines internal to script.cpp:
extern
uint256
SignatureHash
(
CScript
scriptCode
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
nHashType
);
extern
bool
VerifyScript
(
const
CScript
&
scriptSig
,
const
CScript
&
scriptPubKey
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
&
nSigOps
,
int
nHashType
,
bool
fStrictOpEval
);
extern
bool
VerifyScript
(
const
CScript
&
scriptSig
,
const
CScript
&
scriptPubKey
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
bool
fValidatePayToScriptHash
,
int
nHashType
);
BOOST_AUTO_TEST_SUITE
(
script_op_eval_tests
)
// Helpers:
static
std
::
vector
<
unsigned
char
>
Serialize
(
const
CScript
&
s
)
{
std
::
vector
<
unsigned
char
>
sSerialized
(
s
);
return
sSerialized
;
}
static
bool
Verify
(
const
CScript
&
scriptSig
,
const
CScript
&
scriptPubKey
,
bool
fStrict
)
{
// Create dummy to/from transactions:
CTransaction
txFrom
;
txFrom
.
vout
.
resize
(
1
);
txFrom
.
vout
[
0
].
scriptPubKey
=
scriptPubKey
;
CTransaction
txTo
;
txTo
.
vin
.
resize
(
1
);
txTo
.
vout
.
resize
(
1
);
txTo
.
vin
[
0
].
prevout
.
n
=
0
;
txTo
.
vin
[
0
].
prevout
.
hash
=
txFrom
.
GetHash
();
txTo
.
vin
[
0
].
scriptSig
=
scriptSig
;
txTo
.
vout
[
0
].
nValue
=
1
;
return
VerifyScript
(
scriptSig
,
scriptPubKey
,
txTo
,
0
,
fStrict
,
0
);
}
BOOST_AUTO_TEST_SUITE
(
script_P2SH_tests
)
BOOST_AUTO_TEST_CASE
(
s
cript_op_eval1
)
BOOST_AUTO_TEST_CASE
(
s
ign
)
{
//
OP_EVAL
looks like this:
//
Pay-to-script-hash
looks like this:
// scriptSig: <sig> <sig...> <serialized_script>
// scriptPubKey:
DUP
HASH160 <hash> EQUAL
VERIFY EVAL
// scriptPubKey: HASH160 <hash> EQUAL
// Test SignSignature() (and therefore the version of Solver() that signs transactions)
CBasicKeyStore
keystore
;
...
...
@@ -34,19 +62,17 @@ BOOST_AUTO_TEST_CASE(script_op_eval1)
}
// 8 Scripts: checking all combinations of
// different keys, straight/
EVAL
, pubkey/pubkeyhash
// different keys, straight/
P2SH
, pubkey/pubkeyhash
CScript
standardScripts
[
4
];
standardScripts
[
0
]
<<
key
[
0
].
GetPubKey
()
<<
OP_CHECKSIG
;
standardScripts
[
1
].
SetBitcoinAddress
(
key
[
1
].
GetPubKey
());
standardScripts
[
2
]
<<
key
[
1
].
GetPubKey
()
<<
OP_CHECKSIG
;
standardScripts
[
3
].
SetBitcoinAddress
(
key
[
2
].
GetPubKey
());
CScript
evalScripts
[
4
];
uint160
sigScriptHashes
[
4
];
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
sigScriptHashes
[
i
]
=
Hash160
(
standardScripts
[
i
]);
keystore
.
AddCScript
(
sigScriptHashes
[
i
],
standardScripts
[
i
]);
evalScripts
[
i
]
<<
OP_DUP
<<
OP_HASH160
<<
sigScriptHashes
[
i
]
<<
OP_EQUALVERIFY
<<
OP_EVAL
;
keystore
.
AddCScript
(
standardScripts
[
i
]);
evalScripts
[
i
].
SetPayToScriptHash
(
standardScripts
[
i
]);
}
CTransaction
txFrom
;
// Funding transaction:
...
...
@@ -79,8 +105,7 @@ BOOST_AUTO_TEST_CASE(script_op_eval1)
{
CScript
sigSave
=
txTo
[
i
].
vin
[
0
].
scriptSig
;
txTo
[
i
].
vin
[
0
].
scriptSig
=
txTo
[
j
].
vin
[
0
].
scriptSig
;
int
nUnused
=
0
;
bool
sigOK
=
VerifySignature
(
txFrom
,
txTo
[
i
],
0
,
nUnused
);
bool
sigOK
=
VerifySignature
(
txFrom
,
txTo
[
i
],
0
,
true
,
0
);
if
(
i
==
j
)
BOOST_CHECK_MESSAGE
(
sigOK
,
strprintf
(
"VerifySignature %d %d"
,
i
,
j
));
else
...
...
@@ -89,72 +114,33 @@ BOOST_AUTO_TEST_CASE(script_op_eval1)
}
}
BOOST_AUTO_TEST_CASE
(
script_op_eval2
)
BOOST_AUTO_TEST_CASE
(
norecurse
)
{
// Test OP_EVAL edge cases
// Make sure only the outer pay-to-script-hash does the
// extra-validation thing:
CScript
invalidAsScript
;
invalidAsScript
<<
OP_INVALIDOPCODE
<<
OP_INVALIDOPCODE
;
// Make sure infinite recursion fails to validate:
CScript
infiniteRecurse
;
infiniteRecurse
<<
OP_DUP
<<
OP_EVAL
;
CScript
p2sh
;
p2sh
.
SetPayToScriptHash
(
invalidAsScript
);
uint160
infiniteRecurseHash
=
Hash160
(
infiniteRecurse
);
CScript
scriptSig
;
scriptSig
<<
Serialize
(
invalidAsScript
);
CScript
fund1
;
fund1
<<
OP_DUP
<<
OP_HASH160
<<
infiniteRecurseHash
<<
OP_EQUALVERIFY
<<
OP_EVAL
;
// Should not verify, because it will try to execute OP_INVALIDOPCODE
BOOST_CHECK
(
!
Verify
(
scriptSig
,
p2sh
,
true
))
;
CTransaction
txFrom1
;
// Funding transaction:
txFrom1
.
vout
.
resize
(
1
);
txFrom1
.
vout
[
0
].
scriptPubKey
=
fund1
;
// Try to recurse, and verification should succeed because
// the inner HASH160 <> EQUAL should only check the hash:
CScript
p2sh2
;
p2sh2
.
SetPayToScriptHash
(
p2sh
);
CScript
scriptSig2
;
scriptSig2
<<
Serialize
(
invalidAsScript
)
<<
Serialize
(
p2sh
);
BOOST_CHECK
(
txFrom1
.
IsStandard
());
// Looks like a standard transaction until you try to spend it
std
::
vector
<
unsigned
char
>
infiniteRecurseSerialized
(
infiniteRecurse
);
CTransaction
txTo1
;
txTo1
.
vin
.
resize
(
1
);
txTo1
.
vout
.
resize
(
1
);
txTo1
.
vin
[
0
].
prevout
.
n
=
0
;
txTo1
.
vin
[
0
].
prevout
.
hash
=
txFrom1
.
GetHash
();
txTo1
.
vin
[
0
].
scriptSig
=
CScript
()
<<
infiniteRecurseSerialized
<<
infiniteRecurseSerialized
;
txTo1
.
vout
[
0
].
nValue
=
1
;
int
nUnused1
=
0
;
BOOST_CHECK
(
!
VerifyScript
(
txTo1
.
vin
[
0
].
scriptSig
,
txFrom1
.
vout
[
0
].
scriptPubKey
,
txTo1
,
0
,
nUnused1
,
0
,
true
));
BOOST_CHECK
(
!
VerifySignature
(
txFrom1
,
txTo1
,
0
,
nUnused1
,
true
));
// Make sure 3-level-deep recursion fails to validate:
CScript
recurse3
;
recurse3
<<
OP_EVAL
;
uint160
recurse3Hash
=
Hash160
(
recurse3
);
CScript
fund2
;
fund2
<<
OP_DUP
<<
OP_HASH160
<<
recurse3Hash
<<
OP_EQUALVERIFY
<<
OP_EVAL
;
CTransaction
txFrom2
;
// Funding transaction:
txFrom2
.
vout
.
resize
(
1
);
txFrom2
.
vout
[
0
].
scriptPubKey
=
fund2
;
BOOST_CHECK
(
txFrom2
.
IsStandard
());
// Looks like a standard transaction until you try to spend it
std
::
vector
<
unsigned
char
>
recurse3Serialized
(
recurse3
);
CScript
op1Script
=
CScript
()
<<
OP_1
;
std
::
vector
<
unsigned
char
>
op1Serialized
(
op1Script
);
CTransaction
txTo2
;
txTo2
.
vin
.
resize
(
1
);
txTo2
.
vout
.
resize
(
1
);
txTo2
.
vin
[
0
].
prevout
.
n
=
0
;
txTo2
.
vin
[
0
].
prevout
.
hash
=
txFrom2
.
GetHash
();
txTo2
.
vin
[
0
].
scriptSig
=
CScript
()
<<
op1Serialized
<<
recurse3Serialized
<<
recurse3Serialized
;
txTo2
.
vout
[
0
].
nValue
=
1
;
int
nUnused2
=
0
;
BOOST_CHECK
(
!
VerifyScript
(
txTo2
.
vin
[
0
].
scriptSig
,
txFrom2
.
vout
[
0
].
scriptPubKey
,
txTo2
,
0
,
nUnused2
,
0
,
true
));
BOOST_CHECK
(
!
VerifySignature
(
txFrom2
,
txTo2
,
0
,
nUnused2
,
true
));
BOOST_CHECK
(
Verify
(
scriptSig2
,
p2sh2
,
true
));
}
BOOST_AUTO_TEST_CASE
(
s
cript_op_eval3
)
BOOST_AUTO_TEST_CASE
(
s
et
)
{
// Test the CScript::Set* methods
CBasicKeyStore
keystore
;
...
...
@@ -176,8 +162,8 @@ BOOST_AUTO_TEST_CASE(script_op_eval3)
CScript
outer
[
4
];
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
outer
[
i
].
Set
Eval
(
inner
[
i
]);
keystore
.
AddCScript
(
Hash160
(
inner
[
i
]),
inner
[
i
]);
outer
[
i
].
Set
PayToScriptHash
(
inner
[
i
]);
keystore
.
AddCScript
(
inner
[
i
]);
}
CTransaction
txFrom
;
// Funding transaction:
...
...
@@ -206,63 +192,119 @@ BOOST_AUTO_TEST_CASE(script_op_eval3)
}
}
BOOST_AUTO_TEST_CASE
(
s
cript_op_eval_backcompat1
)
BOOST_AUTO_TEST_CASE
(
i
s
)
{
// Check backwards-incompatibility-testing code
CScript
returnsEleven
;
returnsEleven
<<
OP_11
;
// This should validate on new clients, but will
// be invalid on old clients (that interpret OP_EVAL as a no-op)
// ... except there's a special rule that makes new clients reject
// it.
CScript
fund
;
fund
<<
OP_EVAL
<<
OP_11
<<
OP_EQUAL
;
CTransaction
txFrom
;
// Funding transaction:
txFrom
.
vout
.
resize
(
1
);
txFrom
.
vout
[
0
].
scriptPubKey
=
fund
;
CTransaction
txTo
;
txTo
.
vin
.
resize
(
1
);
txTo
.
vout
.
resize
(
1
);
txTo
.
vin
[
0
].
prevout
.
n
=
0
;
txTo
.
vin
[
0
].
prevout
.
hash
=
txFrom
.
GetHash
();
txTo
.
vin
[
0
].
scriptSig
=
CScript
()
<<
static_cast
<
std
::
vector
<
unsigned
char
>
>
(
returnsEleven
);
txTo
.
vout
[
0
].
nValue
=
1
;
int
nUnused
=
0
;
BOOST_CHECK
(
!
VerifyScript
(
txTo
.
vin
[
0
].
scriptSig
,
txFrom
.
vout
[
0
].
scriptPubKey
,
txTo
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifySignature
(
txFrom
,
txTo
,
0
,
nUnused
,
true
));
// Test CScript::IsPayToScriptHash()
uint160
dummy
;
CScript
p2sh
;
p2sh
<<
OP_HASH160
<<
dummy
<<
OP_EQUAL
;
BOOST_CHECK
(
p2sh
.
IsPayToScriptHash
());
// Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes:
static
const
unsigned
char
direct
[]
=
{
OP_HASH160
,
20
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
OP_EQUAL
};
BOOST_CHECK
(
CScript
(
direct
,
direct
+
sizeof
(
direct
)).
IsPayToScriptHash
());
static
const
unsigned
char
pushdata1
[]
=
{
OP_HASH160
,
OP_PUSHDATA1
,
20
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
OP_EQUAL
};
BOOST_CHECK
(
!
CScript
(
pushdata1
,
pushdata1
+
sizeof
(
pushdata1
)).
IsPayToScriptHash
());
static
const
unsigned
char
pushdata2
[]
=
{
OP_HASH160
,
OP_PUSHDATA2
,
20
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
OP_EQUAL
};
BOOST_CHECK
(
!
CScript
(
pushdata2
,
pushdata2
+
sizeof
(
pushdata2
)).
IsPayToScriptHash
());
static
const
unsigned
char
pushdata4
[]
=
{
OP_HASH160
,
OP_PUSHDATA4
,
20
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
OP_EQUAL
};
BOOST_CHECK
(
!
CScript
(
pushdata4
,
pushdata4
+
sizeof
(
pushdata4
)).
IsPayToScriptHash
());
CScript
not_p2sh
;
BOOST_CHECK
(
!
not_p2sh
.
IsPayToScriptHash
());
not_p2sh
.
clear
();
not_p2sh
<<
OP_HASH160
<<
dummy
<<
dummy
<<
OP_EQUAL
;
BOOST_CHECK
(
!
not_p2sh
.
IsPayToScriptHash
());
not_p2sh
.
clear
();
not_p2sh
<<
OP_NOP
<<
dummy
<<
OP_EQUAL
;
BOOST_CHECK
(
!
not_p2sh
.
IsPayToScriptHash
());
not_p2sh
.
clear
();
not_p2sh
<<
OP_HASH160
<<
dummy
<<
OP_CHECKSIG
;
BOOST_CHECK
(
!
not_p2sh
.
IsPayToScriptHash
());
}
BOOST_AUTO_TEST_CASE
(
script_op_eval_
switchover
)
BOOST_AUTO_TEST_CASE
(
switchover
)
{
// Test
OP_EVAL
switchover code
// Test switchover code
CScript
notValid
;
notValid
<<
OP_11
<<
OP_12
<<
OP_EQUALVERIFY
;
CScript
scriptSig
;
scriptSig
<<
Serialize
(
notValid
);
// This will be valid under old rules, invalid under new:
CScript
fund
;
fund
<<
OP_EVAL
;
fund
.
SetPayToScriptHash
(
notValid
)
;
CTransaction
txFrom
;
// Funding transaction:
txFrom
.
vout
.
resize
(
1
);
txFrom
.
vout
[
0
].
scriptPubKey
=
fund
;
// Validation should succeed under old rules (hash is correct):
BOOST_CHECK
(
Verify
(
scriptSig
,
fund
,
false
));
// Fail under new:
BOOST_CHECK
(
!
Verify
(
scriptSig
,
fund
,
true
));
}
BOOST_AUTO_TEST_CASE
(
AreInputsStandard
)
{
std
::
map
<
uint256
,
std
::
pair
<
CTxIndex
,
CTransaction
>
>
mapInputs
;
CBasicKeyStore
keystore
;
CKey
key
[
3
];
vector
<
CKey
>
keys
;
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
key
[
i
].
MakeNewKey
();
keystore
.
AddKey
(
key
[
i
]);
keys
.
push_back
(
key
[
i
]);
}
CTransaction
txFrom
;
txFrom
.
vout
.
resize
(
5
);
// First three are standard:
CScript
pay1
;
pay1
.
SetBitcoinAddress
(
key
[
0
].
GetPubKey
());
keystore
.
AddCScript
(
pay1
);
CScript
payScriptHash1
;
payScriptHash1
.
SetPayToScriptHash
(
pay1
);
CScript
pay1of3
;
pay1of3
.
SetMultisig
(
1
,
keys
);
txFrom
.
vout
[
0
].
scriptPubKey
=
payScriptHash1
;
txFrom
.
vout
[
1
].
scriptPubKey
=
pay1
;
txFrom
.
vout
[
2
].
scriptPubKey
=
pay1of3
;
// Last two non-standard:
CScript
empty
;
keystore
.
AddCScript
(
empty
);
txFrom
.
vout
[
3
].
scriptPubKey
=
empty
;
// Can't use SetPayToScriptHash, it checks for the empty Script. So:
txFrom
.
vout
[
4
].
scriptPubKey
<<
OP_HASH160
<<
Hash160
(
empty
)
<<
OP_EQUAL
;
mapInputs
[
txFrom
.
GetHash
()]
=
make_pair
(
CTxIndex
(),
txFrom
);
CTransaction
txTo
;
txTo
.
vin
.
resize
(
1
);
txTo
.
vout
.
resize
(
1
);
txTo
.
vout
[
0
].
scriptPubKey
.
SetBitcoinAddress
(
key
[
1
].
GetPubKey
());
txTo
.
vin
.
resize
(
3
);
txTo
.
vin
[
0
].
prevout
.
n
=
0
;
txTo
.
vin
[
0
].
prevout
.
hash
=
txFrom
.
GetHash
();
txTo
.
vin
[
0
].
scriptSig
=
CScript
()
<<
static_cast
<
std
::
vector
<
unsigned
char
>
>
(
notValid
);
txTo
.
vout
[
0
].
nValue
=
1
;
int
nUnused
=
0
;
BOOST_CHECK
(
VerifyScript
(
txTo
.
vin
[
0
].
scriptSig
,
txFrom
.
vout
[
0
].
scriptPubKey
,
txTo
,
0
,
nUnused
,
0
,
false
));
// Under strict op_eval switchover, it should be considered invalid:
BOOST_CHECK
(
!
VerifyScript
(
txTo
.
vin
[
0
].
scriptSig
,
txFrom
.
vout
[
0
].
scriptPubKey
,
txTo
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
SignSignature
(
keystore
,
txFrom
,
txTo
,
0
));
txTo
.
vin
[
1
].
prevout
.
n
=
1
;
txTo
.
vin
[
1
].
prevout
.
hash
=
txFrom
.
GetHash
();
BOOST_CHECK
(
SignSignature
(
keystore
,
txFrom
,
txTo
,
1
));
txTo
.
vin
[
2
].
prevout
.
n
=
2
;
txTo
.
vin
[
2
].
prevout
.
hash
=
txFrom
.
GetHash
();
BOOST_CHECK
(
SignSignature
(
keystore
,
txFrom
,
txTo
,
2
));
BOOST_CHECK
(
txTo
.
AreInputsStandard
(
mapInputs
));
CTransaction
txToNonStd
;
txToNonStd
.
vout
.
resize
(
1
);
txToNonStd
.
vout
[
0
].
scriptPubKey
.
SetBitcoinAddress
(
key
[
1
].
GetPubKey
());
txToNonStd
.
vin
.
resize
(
1
);
txToNonStd
.
vin
[
0
].
prevout
.
n
=
4
;
txToNonStd
.
vin
[
0
].
prevout
.
hash
=
txFrom
.
GetHash
();
txToNonStd
.
vin
[
0
].
scriptSig
<<
Serialize
(
empty
);
BOOST_CHECK
(
!
txToNonStd
.
AreInputsStandard
(
mapInputs
));
txToNonStd
.
vin
[
0
].
scriptSig
.
clear
();
BOOST_CHECK
(
!
txToNonStd
.
AreInputsStandard
(
mapInputs
));
}
BOOST_AUTO_TEST_SUITE_END
()
This diff is collapsed.
Click to expand it.
src/test/script_tests.cpp
View file @
fa1ca2af
...
...
@@ -7,8 +7,8 @@
using
namespace
std
;
extern
uint256
SignatureHash
(
CScript
scriptCode
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
nHashType
);
extern
bool
VerifyScript
(
const
CScript
&
scriptSig
,
const
CScript
&
scriptPubKey
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
int
&
nSigOps
,
int
nHashType
,
bool
fStrictOpEval
);
extern
bool
VerifyScript
(
const
CScript
&
scriptSig
,
const
CScript
&
scriptPubKey
,
const
CTransaction
&
txTo
,
unsigned
int
nIn
,
bool
fValidatePayToScriptHash
,
int
nHashType
);
BOOST_AUTO_TEST_SUITE
(
script_tests
)
...
...
@@ -21,21 +21,19 @@ BOOST_AUTO_TEST_CASE(script_PushData)
static
const
unsigned
char
pushdata2
[]
=
{
OP_PUSHDATA2
,
1
,
0
,
0x5a
};
static
const
unsigned
char
pushdata4
[]
=
{
OP_PUSHDATA4
,
1
,
0
,
0
,
0
,
0x5a
};
int
nUnused
=
0
;
vector
<
vector
<
unsigned
char
>
>
directStack
;
BOOST_CHECK
(
EvalScript
(
directStack
,
CScript
(
&
direct
[
0
],
&
direct
[
sizeof
(
direct
)]),
CTransaction
(),
0
,
0
,
true
,
nUnused
));
BOOST_CHECK
(
EvalScript
(
directStack
,
CScript
(
&
direct
[
0
],
&
direct
[
sizeof
(
direct
)]),
CTransaction
(),
0
,
0
));
vector
<
vector
<
unsigned
char
>
>
pushdata1Stack
;
BOOST_CHECK
(
EvalScript
(
pushdata1Stack
,
CScript
(
&
pushdata1
[
0
],
&
pushdata1
[
sizeof
(
pushdata1
)]),
CTransaction
(),
0
,
0
,
true
,
nUnused
));
BOOST_CHECK
(
EvalScript
(
pushdata1Stack
,
CScript
(
&
pushdata1
[
0
],
&
pushdata1
[
sizeof
(
pushdata1
)]),
CTransaction
(),
0
,
0
));
BOOST_CHECK
(
pushdata1Stack
==
directStack
);
vector
<
vector
<
unsigned
char
>
>
pushdata2Stack
;
BOOST_CHECK
(
EvalScript
(
pushdata2Stack
,
CScript
(
&
pushdata2
[
0
],
&
pushdata2
[
sizeof
(
pushdata2
)]),
CTransaction
(),
0
,
0
,
true
,
nUnused
));
BOOST_CHECK
(
EvalScript
(
pushdata2Stack
,
CScript
(
&
pushdata2
[
0
],
&
pushdata2
[
sizeof
(
pushdata2
)]),
CTransaction
(),
0
,
0
));
BOOST_CHECK
(
pushdata2Stack
==
directStack
);
vector
<
vector
<
unsigned
char
>
>
pushdata4Stack
;
BOOST_CHECK
(
EvalScript
(
pushdata4Stack
,
CScript
(
&
pushdata4
[
0
],
&
pushdata4
[
sizeof
(
pushdata4
)]),
CTransaction
(),
0
,
0
,
true
,
nUnused
));
BOOST_CHECK
(
EvalScript
(
pushdata4Stack
,
CScript
(
&
pushdata4
[
0
],
&
pushdata4
[
sizeof
(
pushdata4
)]),
CTransaction
(),
0
,
0
));
BOOST_CHECK
(
pushdata4Stack
==
directStack
);
}
...
...
@@ -73,7 +71,6 @@ sign_multisig(CScript scriptPubKey, CKey key, CTransaction transaction)
BOOST_AUTO_TEST_CASE
(
script_CHECKMULTISIG12
)
{
int
nUnused
=
0
;
CKey
key1
,
key2
,
key3
;
key1
.
MakeNewKey
();
key2
.
MakeNewKey
();
...
...
@@ -94,20 +91,19 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
txTo12
.
vout
[
0
].
nValue
=
1
;
CScript
goodsig1
=
sign_multisig
(
scriptPubKey12
,
key1
,
txTo12
);
BOOST_CHECK
(
VerifyScript
(
goodsig1
,
scriptPubKey12
,
txTo12
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
VerifyScript
(
goodsig1
,
scriptPubKey12
,
txTo12
,
0
,
true
,
0
));
txTo12
.
vout
[
0
].
nValue
=
2
;
BOOST_CHECK
(
!
VerifyScript
(
goodsig1
,
scriptPubKey12
,
txTo12
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifyScript
(
goodsig1
,
scriptPubKey12
,
txTo12
,
0
,
true
,
0
));
CScript
goodsig2
=
sign_multisig
(
scriptPubKey12
,
key2
,
txTo12
);
BOOST_CHECK
(
VerifyScript
(
goodsig2
,
scriptPubKey12
,
txTo12
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
VerifyScript
(
goodsig2
,
scriptPubKey12
,
txTo12
,
0
,
true
,
0
));
CScript
badsig1
=
sign_multisig
(
scriptPubKey12
,
key3
,
txTo12
);
BOOST_CHECK
(
!
VerifyScript
(
badsig1
,
scriptPubKey12
,
txTo12
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifyScript
(
badsig1
,
scriptPubKey12
,
txTo12
,
0
,
true
,
0
));
}
BOOST_AUTO_TEST_CASE
(
script_CHECKMULTISIG23
)
{
int
nUnused
=
0
;
CKey
key1
,
key2
,
key3
,
key4
;
key1
.
MakeNewKey
();
key2
.
MakeNewKey
();
...
...
@@ -131,46 +127,46 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
std
::
vector
<
CKey
>
keys
;
keys
.
push_back
(
key1
);
keys
.
push_back
(
key2
);
CScript
goodsig1
=
sign_multisig
(
scriptPubKey23
,
keys
,
txTo23
);
BOOST_CHECK
(
VerifyScript
(
goodsig1
,
scriptPubKey23
,
txTo23
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
VerifyScript
(
goodsig1
,
scriptPubKey23
,
txTo23
,
0
,
true
,
0
));
keys
.
clear
();
keys
.
push_back
(
key1
);
keys
.
push_back
(
key3
);
CScript
goodsig2
=
sign_multisig
(
scriptPubKey23
,
keys
,
txTo23
);
BOOST_CHECK
(
VerifyScript
(
goodsig2
,
scriptPubKey23
,
txTo23
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
VerifyScript
(
goodsig2
,
scriptPubKey23
,
txTo23
,
0
,
true
,
0
));
keys
.
clear
();
keys
.
push_back
(
key2
);
keys
.
push_back
(
key3
);
CScript
goodsig3
=
sign_multisig
(
scriptPubKey23
,
keys
,
txTo23
);
BOOST_CHECK
(
VerifyScript
(
goodsig3
,
scriptPubKey23
,
txTo23
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
VerifyScript
(
goodsig3
,
scriptPubKey23
,
txTo23
,
0
,
true
,
0
));
keys
.
clear
();
keys
.
push_back
(
key2
);
keys
.
push_back
(
key2
);
// Can't re-use sig
CScript
badsig1
=
sign_multisig
(
scriptPubKey23
,
keys
,
txTo23
);
BOOST_CHECK
(
!
VerifyScript
(
badsig1
,
scriptPubKey23
,
txTo23
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifyScript
(
badsig1
,
scriptPubKey23
,
txTo23
,
0
,
true
,
0
));
keys
.
clear
();
keys
.
push_back
(
key2
);
keys
.
push_back
(
key1
);
// sigs must be in correct order
CScript
badsig2
=
sign_multisig
(
scriptPubKey23
,
keys
,
txTo23
);
BOOST_CHECK
(
!
VerifyScript
(
badsig2
,
scriptPubKey23
,
txTo23
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifyScript
(
badsig2
,
scriptPubKey23
,
txTo23
,
0
,
true
,
0
));
keys
.
clear
();
keys
.
push_back
(
key3
);
keys
.
push_back
(
key2
);
// sigs must be in correct order
CScript
badsig3
=
sign_multisig
(
scriptPubKey23
,
keys
,
txTo23
);
BOOST_CHECK
(
!
VerifyScript
(
badsig3
,
scriptPubKey23
,
txTo23
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifyScript
(
badsig3
,
scriptPubKey23
,
txTo23
,
0
,
true
,
0
));
keys
.
clear
();
keys
.
push_back
(
key4
);
keys
.
push_back
(
key2
);
// sigs must match pubkeys
CScript
badsig4
=
sign_multisig
(
scriptPubKey23
,
keys
,
txTo23
);
BOOST_CHECK
(
!
VerifyScript
(
badsig4
,
scriptPubKey23
,
txTo23
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifyScript
(
badsig4
,
scriptPubKey23
,
txTo23
,
0
,
true
,
0
));
keys
.
clear
();
keys
.
push_back
(
key1
);
keys
.
push_back
(
key4
);
// sigs must match pubkeys
CScript
badsig5
=
sign_multisig
(
scriptPubKey23
,
keys
,
txTo23
);
BOOST_CHECK
(
!
VerifyScript
(
badsig5
,
scriptPubKey23
,
txTo23
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifyScript
(
badsig5
,
scriptPubKey23
,
txTo23
,
0
,
true
,
0
));
keys
.
clear
();
// Must have signatures
CScript
badsig6
=
sign_multisig
(
scriptPubKey23
,
keys
,
txTo23
);
BOOST_CHECK
(
!
VerifyScript
(
badsig6
,
scriptPubKey23
,
txTo23
,
0
,
nUnused
,
0
,
true
));
BOOST_CHECK
(
!
VerifyScript
(
badsig6
,
scriptPubKey23
,
txTo23
,
0
,
true
,
0
));
}
...
...
This diff is collapsed.
Click to expand it.
src/test/sigopcount_tests.cpp
0 → 100644
View file @
fa1ca2af
#include <vector>
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
#include "script.h"
#include "key.h"
using
namespace
std
;
// Helpers:
static
std
::
vector
<
unsigned
char
>
Serialize
(
const
CScript
&
s
)
{
std
::
vector
<
unsigned
char
>
sSerialized
(
s
);
return
sSerialized
;
}
BOOST_AUTO_TEST_SUITE
(
sigopcount_tests
)
BOOST_AUTO_TEST_CASE
(
GetSigOpCount
)
{
// Test CScript::GetSigOpCount()
CScript
s1
;
BOOST_CHECK_EQUAL
(
s1
.
GetSigOpCount
(
false
),
0
);
BOOST_CHECK_EQUAL
(
s1
.
GetSigOpCount
(
true
),
0
);
uint160
dummy
;
s1
<<
OP_1
<<
dummy
<<
dummy
<<
OP_2
<<
OP_CHECKMULTISIG
;
BOOST_CHECK_EQUAL
(
s1
.
GetSigOpCount
(
true
),
2
);
s1
<<
OP_IF
<<
OP_CHECKSIG
<<
OP_ENDIF
;
BOOST_CHECK_EQUAL
(
s1
.
GetSigOpCount
(
true
),
3
);
BOOST_CHECK_EQUAL
(
s1
.
GetSigOpCount
(
false
),
21
);
CScript
p2sh
;
p2sh
.
SetPayToScriptHash
(
s1
);
CScript
scriptSig
;
scriptSig
<<
OP_0
<<
Serialize
(
s1
);
BOOST_CHECK_EQUAL
(
p2sh
.
GetSigOpCount
(
scriptSig
),
3
);
std
::
vector
<
CKey
>
keys
;
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
CKey
k
;
k
.
MakeNewKey
();
keys
.
push_back
(
k
);
}
CScript
s2
;
s2
.
SetMultisig
(
1
,
keys
);
BOOST_CHECK_EQUAL
(
s2
.
GetSigOpCount
(
true
),
3
);
BOOST_CHECK_EQUAL
(
s2
.
GetSigOpCount
(
false
),
20
);
p2sh
.
SetPayToScriptHash
(
s2
);
BOOST_CHECK_EQUAL
(
p2sh
.
GetSigOpCount
(
true
),
0
);
BOOST_CHECK_EQUAL
(
p2sh
.
GetSigOpCount
(
false
),
0
);
CScript
scriptSig2
;
scriptSig2
<<
OP_1
<<
dummy
<<
dummy
<<
Serialize
(
s2
);
BOOST_CHECK_EQUAL
(
p2sh
.
GetSigOpCount
(
scriptSig2
),
3
);
}
BOOST_AUTO_TEST_SUITE_END
()
This diff is collapsed.
Click to expand it.
src/test/test_bitcoin.cpp
View file @
fa1ca2af
...
...
@@ -4,18 +4,24 @@
#include "main.h"
#include "wallet.h"
CWallet
*
pwalletMain
;
extern
bool
fPrintToConsole
;
struct
TestingSetup
{
TestingSetup
()
{
fPrintToConsole
=
true
;
// don't want to write to debug.log file
pwalletMain
=
new
CWallet
();
RegisterWallet
(
pwalletMain
);
}
~
TestingSetup
()
{
delete
pwalletMain
;
pwalletMain
=
NULL
;
}
~
TestingSetup
()
{
}
};
BOOST_GLOBAL_FIXTURE
(
TestingSetup
);
CWallet
*
pwalletMain
;
void
Shutdown
(
void
*
parg
)
{
exit
(
0
);
...
...
This diff is collapsed.
Click to expand it.
src/test/util_tests.cpp
View file @
fa1ca2af
...
...
@@ -232,4 +232,19 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
BOOST_CHECK
(
!
ParseMoney
(
"92233720368.54775808"
,
ret
));
}
BOOST_AUTO_TEST_CASE
(
util_IsHex
)
{
BOOST_CHECK
(
IsHex
(
"00"
));
BOOST_CHECK
(
IsHex
(
"00112233445566778899aabbccddeeffAABBCCDDEEFF"
));
BOOST_CHECK
(
IsHex
(
"ff"
));
BOOST_CHECK
(
IsHex
(
"FF"
));
BOOST_CHECK
(
!
IsHex
(
""
));
BOOST_CHECK
(
!
IsHex
(
"0"
));
BOOST_CHECK
(
!
IsHex
(
"a"
));
BOOST_CHECK
(
!
IsHex
(
"eleven"
));
BOOST_CHECK
(
!
IsHex
(
"00xx00"
));
BOOST_CHECK
(
!
IsHex
(
"0x0000"
));
}
BOOST_AUTO_TEST_SUITE_END
()
This diff is collapsed.
Click to expand it.
src/util.cpp
View file @
fa1ca2af
...
...
@@ -400,26 +400,36 @@ bool ParseMoney(const char* pszIn, int64& nRet)
}
vector
<
unsigned
char
>
ParseHex
(
const
char
*
psz
)
static
char
phexdigit
[
256
]
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
0xa
,
0xb
,
0xc
,
0xd
,
0xe
,
0xf
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
0xa
,
0xb
,
0xc
,
0xd
,
0xe
,
0xf
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
};
bool
IsHex
(
const
string
&
str
)
{
static
char
phexdigit
[
256
]
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
0xa
,
0xb
,
0xc
,
0xd
,
0xe
,
0xf
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
0xa
,
0xb
,
0xc
,
0xd
,
0xe
,
0xf
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
};
BOOST_FOREACH
(
unsigned
char
c
,
str
)
{
if
(
phexdigit
[
c
]
<
0
)
return
false
;
}
return
(
str
.
size
()
>
0
)
&&
(
str
.
size
()
%
2
==
0
);
}
vector
<
unsigned
char
>
ParseHex
(
const
char
*
psz
)
{
// convert hex dump to vector
vector
<
unsigned
char
>
vch
;
loop
...
...
This diff is collapsed.
Click to expand it.
src/util.h
View file @
fa1ca2af
...
...
@@ -138,6 +138,7 @@ bool ParseMoney(const std::string& str, int64& nRet);
bool
ParseMoney
(
const
char
*
pszIn
,
int64
&
nRet
);
std
::
vector
<
unsigned
char
>
ParseHex
(
const
char
*
psz
);
std
::
vector
<
unsigned
char
>
ParseHex
(
const
std
::
string
&
str
);
bool
IsHex
(
const
std
::
string
&
str
);
std
::
vector
<
unsigned
char
>
DecodeBase64
(
const
char
*
p
,
bool
*
pfInvalid
=
NULL
);
std
::
string
DecodeBase64
(
const
std
::
string
&
str
);
std
::
string
EncodeBase64
(
const
unsigned
char
*
pch
,
size_t
len
);
...
...
This diff is collapsed.
Click to expand it.
src/wallet.cpp
View file @
fa1ca2af
...
...
@@ -42,13 +42,13 @@ bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector
return
false
;
}
bool
CWallet
::
AddCScript
(
const
uint160
&
hash
,
const
CScript
&
redeemScript
)
bool
CWallet
::
AddCScript
(
const
CScript
&
redeemScript
)
{
if
(
!
CCryptoKeyStore
::
AddCScript
(
hash
,
redeemScript
))
if
(
!
CCryptoKeyStore
::
AddCScript
(
redeemScript
))
return
false
;
if
(
!
fFileBacked
)
return
true
;
return
CWalletDB
(
strWalletFile
).
WriteCScript
(
h
ash
,
redeemScript
);
return
CWalletDB
(
strWalletFile
).
WriteCScript
(
H
ash
160
(
redeemScript
)
,
redeemScript
);
}
bool
CWallet
::
Unlock
(
const
SecureString
&
strWalletPassphrase
)
...
...
This diff is collapsed.
Click to expand it.
src/wallet.h
View file @
fa1ca2af
...
...
@@ -70,8 +70,8 @@ public:
bool
AddCryptedKey
(
const
std
::
vector
<
unsigned
char
>
&
vchPubKey
,
const
std
::
vector
<
unsigned
char
>
&
vchCryptedSecret
);
// Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
bool
LoadCryptedKey
(
const
std
::
vector
<
unsigned
char
>
&
vchPubKey
,
const
std
::
vector
<
unsigned
char
>
&
vchCryptedSecret
)
{
return
CCryptoKeyStore
::
AddCryptedKey
(
vchPubKey
,
vchCryptedSecret
);
}
bool
AddCScript
(
const
uint160
&
hash
,
const
CScript
&
redeemScript
);
bool
LoadCScript
(
const
uint160
&
hash
,
const
CScript
&
redeemScript
)
{
return
CCryptoKeyStore
::
AddCScript
(
hash
,
redeemScript
);
}
bool
AddCScript
(
const
CScript
&
redeemScript
);
bool
LoadCScript
(
const
CScript
&
redeemScript
)
{
return
CCryptoKeyStore
::
AddCScript
(
redeemScript
);
}
bool
Unlock
(
const
SecureString
&
strWalletPassphrase
);
bool
ChangeWalletPassphrase
(
const
SecureString
&
strOldWalletPassphrase
,
const
SecureString
&
strNewWalletPassphrase
);
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment