2014-09-10 16:16:09 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2016-12-31 11:01:21 -07:00
// Copyright (c) 2009-2016 The Bitcoin Core developers
2014-10-06 13:00:55 +02:00
// Distributed under the MIT software license, see the accompanying
2014-09-10 16:16:09 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# include "sigcache.h"
2015-10-30 23:14:38 +01:00
# include "memusage.h"
2014-10-28 17:47:18 -04:00
# include "pubkey.h"
2014-09-10 16:16:09 +02:00
# include "random.h"
# include "uint256.h"
# include "util.h"
2016-10-05 16:58:47 -04:00
# include "cuckoocache.h"
2014-09-10 16:16:09 +02:00
# include <boost/thread.hpp>
namespace {
2015-10-30 23:14:38 +01:00
/**
* We ' re hashing a nonce into the entries themselves , so we don ' t need extra
* blinding in the set hash computation .
2016-10-05 16:58:47 -04:00
*
* This may exhibit platform endian dependent behavior but because these are
* nonced hashes ( random ) and this state is only ever used locally it is safe .
* All that matters is local consistency .
2015-10-30 23:14:38 +01:00
*/
2016-10-05 16:58:47 -04:00
class SignatureCacheHasher
2015-10-30 23:14:38 +01:00
{
public :
2016-10-05 16:58:47 -04:00
template < uint8_t hash_select >
uint32_t operator ( ) ( const uint256 & key ) const
{
static_assert ( hash_select < 8 , " SignatureCacheHasher only has 8 hashes available. " ) ;
uint32_t u ;
std : : memcpy ( & u , key . begin ( ) + 4 * hash_select , 4 ) ;
return u ;
2015-10-30 23:14:38 +01:00
}
} ;
2014-11-10 14:40:01 +08:00
/**
* Valid signature cache , to avoid doing expensive ECDSA signature checking
* twice for every transaction ( once when accepted into memory pool , and
* again when accepted into the block chain )
*/
2014-09-10 16:16:09 +02:00
class CSignatureCache
{
private :
2017-03-23 10:55:40 -04:00
//! Entries are SHA256(nonce || signature hash || public key || signature || additional commit || CScript). They are used in various ways for different checks
2015-10-30 23:14:38 +01:00
uint256 nonce ;
2016-10-05 16:58:47 -04:00
typedef CuckooCache : : cache < uint256 , SignatureCacheHasher > map_type ;
2015-10-30 23:14:38 +01:00
map_type setValid ;
2014-09-10 16:16:09 +02:00
boost : : shared_mutex cs_sigcache ;
public :
2015-10-30 23:14:38 +01:00
CSignatureCache ( )
{
GetRandBytes ( nonce . begin ( ) , 32 ) ;
}
void
2017-03-23 10:55:40 -04:00
ComputeEntry ( uint256 & entry , const uint256 & hash , const std : : vector < unsigned char > & vchSig , const CPubKey & pubkey , const std : : vector < unsigned char > & vchCommitment , const CScript & scriptPubKey )
2015-10-30 23:14:38 +01:00
{
2017-03-23 10:55:40 -04:00
CSHA256 ( ) . Write ( nonce . begin ( ) , 32 ) . Write ( hash . begin ( ) , 32 ) . Write ( & pubkey [ 0 ] , pubkey . size ( ) ) . Write ( & vchSig [ 0 ] , vchSig . size ( ) ) . Write ( & vchCommitment [ 0 ] , vchCommitment . size ( ) ) . Write ( & scriptPubKey [ 0 ] , scriptPubKey . size ( ) ) . Finalize ( entry . begin ( ) ) ;
2015-10-30 23:14:38 +01:00
}
2014-09-10 16:16:09 +02:00
bool
2016-10-05 16:58:47 -04:00
Get ( const uint256 & entry , const bool erase )
2014-09-10 16:16:09 +02:00
{
boost : : shared_lock < boost : : shared_mutex > lock ( cs_sigcache ) ;
2016-10-05 16:58:47 -04:00
return setValid . contains ( entry , erase ) ;
2014-09-10 16:16:09 +02:00
}
2016-10-05 16:58:47 -04:00
void Set ( uint256 & entry )
2015-10-30 23:38:40 +01:00
{
boost : : unique_lock < boost : : shared_mutex > lock ( cs_sigcache ) ;
2016-10-05 16:58:47 -04:00
setValid . insert ( entry ) ;
2015-10-30 23:38:40 +01:00
}
2016-10-05 16:58:47 -04:00
uint32_t setup_bytes ( size_t n )
2014-09-10 16:16:09 +02:00
{
2016-10-05 16:58:47 -04:00
return setValid . setup_bytes ( n ) ;
2014-09-10 16:16:09 +02:00
}
} ;
2016-10-05 16:58:47 -04:00
/* In previous versions of this code, signatureCache was a local static variable
* in CachingTransactionSignatureChecker : : VerifySignature . We initialize
* signatureCache outside of VerifySignature to avoid the atomic operation per
* call overhead associated with local static variables even though
* signatureCache could be made local to VerifySignature .
*/
static CSignatureCache signatureCache ;
2016-07-12 11:02:06 -04:00
static CSignatureCache rangeProofCache ;
2016-11-29 13:59:01 -05:00
static CSignatureCache surjectionProofCache ;
2014-09-10 16:16:09 +02:00
}
2016-10-05 16:58:47 -04:00
// To be called once in AppInit2/TestingSetup to initialize the signatureCache
void InitSignatureCache ( )
2014-09-10 16:16:09 +02:00
{
2017-02-15 14:19:16 -05:00
// nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
// setup_bytes creates the minimum possible cache (2 elements).
size_t nMaxCacheSize = std : : min ( std : : max ( ( int64_t ) 0 , GetArg ( " -maxsigcachesize " , DEFAULT_MAX_SIG_CACHE_SIZE ) ) , MAX_MAX_SIG_CACHE_SIZE ) * ( ( size_t ) 1 < < 20 ) ;
2016-10-05 16:58:47 -04:00
size_t nElems = signatureCache . setup_bytes ( nMaxCacheSize ) ;
LogPrintf ( " Using %zu MiB out of %zu requested for signature cache, able to store %zu elements \n " ,
( nElems * sizeof ( uint256 ) ) > > 20 , nMaxCacheSize > > 20 , nElems ) ;
}
2014-09-10 16:16:09 +02:00
2016-07-12 11:02:06 -04:00
// To be called once in AppInit2/TestingSetup to initialize the rangeproof cache
void InitRangeproofCache ( )
{
// nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
// setup_bytes creates the minimum possible cache (2 elements).
size_t nMaxCacheSize = std : : min ( std : : max ( ( int64_t ) 0 , GetArg ( " -maxsigcachesize " , DEFAULT_MAX_SIG_CACHE_SIZE ) ) , MAX_MAX_SIG_CACHE_SIZE ) * ( ( size_t ) 1 < < 20 ) ;
size_t nElems = rangeProofCache . setup_bytes ( nMaxCacheSize ) ;
LogPrintf ( " Using %zu MiB out of %zu requested for rangeproof cache, able to store %zu elements \n " ,
( nElems * sizeof ( uint256 ) ) > > 20 , nMaxCacheSize > > 20 , nElems ) ;
}
2016-11-29 13:59:01 -05:00
// To be called once in AppInit2/TestingSetup to initialize the surjectionrproof cache
void InitSurjectionproofCache ( )
{
// nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
// setup_bytes creates the minimum possible cache (2 elements).
size_t nMaxCacheSize = std : : min ( std : : max ( ( int64_t ) 0 , GetArg ( " -maxsigcachesize " , DEFAULT_MAX_SIG_CACHE_SIZE ) ) , MAX_MAX_SIG_CACHE_SIZE ) * ( ( size_t ) 1 < < 20 ) ;
size_t nElems = surjectionProofCache . setup_bytes ( nMaxCacheSize ) ;
LogPrintf ( " Using %zu MiB out of %zu requested for surjectionproof cache, able to store %zu elements \n " ,
( nElems * sizeof ( uint256 ) ) > > 20 , nMaxCacheSize > > 20 , nElems ) ;
}
2016-10-05 16:58:47 -04:00
bool CachingTransactionSignatureChecker : : VerifySignature ( const std : : vector < unsigned char > & vchSig , const CPubKey & pubkey , const uint256 & sighash ) const
{
2015-10-30 23:14:38 +01:00
uint256 entry ;
2017-03-23 10:55:40 -04:00
signatureCache . ComputeEntry ( entry , sighash , vchSig , pubkey , vchSig , CScript ( ) ) ;
2016-10-05 16:58:47 -04:00
if ( signatureCache . Get ( entry , ! store ) )
2014-09-10 16:16:09 +02:00
return true ;
2015-01-27 09:28:45 -04:00
if ( ! TransactionSignatureChecker : : VerifySignature ( vchSig , pubkey , sighash ) )
2014-09-10 16:16:09 +02:00
return false ;
2016-10-05 16:58:47 -04:00
if ( store )
2015-10-30 23:14:38 +01:00
signatureCache . Set ( entry ) ;
2014-09-10 16:16:09 +02:00
return true ;
}
2016-07-12 11:02:06 -04:00
2017-03-09 13:32:33 -08:00
bool CachingRangeProofChecker : : VerifyRangeProof ( const std : : vector < unsigned char > & vchRangeProof , const std : : vector < unsigned char > & vchValueCommitment , const std : : vector < unsigned char > & vchAssetCommitment , const CScript & scriptPubKey , const secp256k1_context * secp256k1_ctx_verify_amounts ) const
2016-07-12 11:02:06 -04:00
{
2017-03-09 13:32:33 -08:00
CPubKey pubkey ( vchValueCommitment ) ;
2016-07-12 11:02:06 -04:00
uint256 entry ;
2017-03-23 10:55:40 -04:00
rangeProofCache . ComputeEntry ( entry , uint256 ( ) , vchRangeProof , pubkey , vchAssetCommitment , scriptPubKey ) ;
2016-07-12 11:02:06 -04:00
if ( rangeProofCache . Get ( entry , ! store ) ) {
return true ;
}
uint64_t min_value , max_value ;
2016-11-02 10:54:51 -04:00
secp256k1_pedersen_commitment commit ;
2017-03-09 13:32:33 -08:00
if ( secp256k1_pedersen_commitment_parse ( secp256k1_ctx_verify_amounts , & commit , & vchValueCommitment [ 0 ] ) ! = 1 )
2016-11-02 10:54:51 -04:00
return false ;
2016-12-01 09:34:31 -05:00
secp256k1_generator tag ;
2017-03-09 13:32:33 -08:00
if ( secp256k1_generator_parse ( secp256k1_ctx_verify_amounts , & tag , & vchAssetCommitment [ 0 ] ) ! = 1 )
2016-12-01 09:34:31 -05:00
return false ;
2017-02-09 11:35:00 -05:00
if ( ! secp256k1_rangeproof_verify ( secp256k1_ctx_verify_amounts , & min_value , & max_value , & commit , vchRangeProof . data ( ) , vchRangeProof . size ( ) , scriptPubKey . size ( ) ? & scriptPubKey . front ( ) : NULL , scriptPubKey . size ( ) , & tag ) ) {
2016-07-12 11:02:06 -04:00
return false ;
}
2017-03-30 15:03:50 -04:00
// An rangeproof is not valid if the output is spendable but the minimum number
// is 0. This is to prevent people passing 0-value tokens around, or conjuring
// reissuance tokens from nothing then attempting to reissue an asset.
// ie reissuance doesn't require revealing value of reissuance output
// Issuances proofs are always "unspendable" as they commit to an empty script.
if ( min_value = = 0 & & ! scriptPubKey . IsUnspendable ( ) ) {
return false ;
}
2016-07-12 11:02:06 -04:00
return true ;
}
2016-11-29 13:59:01 -05:00
bool CachingSurjectionProofChecker : : VerifySurjectionProof ( secp256k1_surjectionproof & proof , std : : vector < secp256k1_generator > & vTags , secp256k1_generator & gen , const secp256k1_context * secp256k1_ctx_verify_amounts ) const
{
2017-03-23 10:55:40 -04:00
// Serialize objects
2016-11-29 13:59:01 -05:00
std : : vector < unsigned char > vchproof ;
size_t proof_len = 0 ;
vchproof . resize ( secp256k1_surjectionproof_serialized_size ( secp256k1_ctx_verify_amounts , & proof ) ) ;
secp256k1_surjectionproof_serialize ( secp256k1_ctx_verify_amounts , & vchproof [ 0 ] , & proof_len , & proof ) ;
2017-03-23 10:55:40 -04:00
std : : vector < unsigned char > tagCommit ;
tagCommit . resize ( 33 ) ;
CSHA256 sha2 ;
for ( unsigned int i = 0 ; i < vTags . size ( ) ; i + + ) {
secp256k1_generator_serialize ( secp256k1_ctx_verify_amounts , tagCommit . data ( ) , & vTags [ i ] ) ;
sha2 . Write ( tagCommit . data ( ) , tagCommit . size ( ) ) ;
}
tagCommit . resize ( 32 ) ;
sha2 . Finalize ( tagCommit . data ( ) ) ;
2016-11-29 13:59:01 -05:00
std : : vector < unsigned char > vchGen ;
2017-03-10 03:03:48 -08:00
vchGen . resize ( CConfidentialValue : : nCommittedSize ) ;
2016-11-29 13:59:01 -05:00
secp256k1_generator_serialize ( secp256k1_ctx_verify_amounts , & vchGen [ 0 ] , & gen ) ;
CPubKey pubkey ( vchGen ) ;
uint256 entry ;
2017-03-23 10:55:40 -04:00
surjectionProofCache . ComputeEntry ( entry , uint256 ( tagCommit ) , vchproof , pubkey , vchGen , CScript ( ) ) ;
2016-11-29 13:59:01 -05:00
if ( surjectionProofCache . Get ( entry , ! store ) ) {
return true ;
}
if ( secp256k1_surjectionproof_verify ( secp256k1_ctx_verify_amounts , & proof , vTags . data ( ) , vTags . size ( ) , & gen ) ! = 1 ) {
return false ;
}
return true ;
}