2019-05-08 00:32:22 +02:00
// Copyright (c) 2018 The LBRY developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2019-07-09 17:02:54 +02:00
# include <coins.h>
# include <claimscriptop.h>
# include <nameclaim.h>
2019-05-08 00:32:22 +02:00
CClaimScriptAddOp : : CClaimScriptAddOp ( const COutPoint & point , CAmount nValue , int nHeight )
: point ( point ) , nValue ( nValue ) , nHeight ( nHeight )
{
}
bool CClaimScriptAddOp : : claimName ( CClaimTrieCache & trieCache , const std : : string & name )
{
return addClaim ( trieCache , name , ClaimIdHash ( point . hash , point . n ) ) ;
}
bool CClaimScriptAddOp : : updateClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
return addClaim ( trieCache , name , claimId ) ;
}
bool CClaimScriptAddOp : : addClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
return trieCache . addClaim ( name , point , claimId , nValue , nHeight ) ;
}
bool CClaimScriptAddOp : : supportClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
return trieCache . addSupport ( name , point , nValue , claimId , nHeight ) ;
}
CClaimScriptUndoAddOp : : CClaimScriptUndoAddOp ( const COutPoint & point , int nHeight ) : point ( point ) , nHeight ( nHeight )
{
}
bool CClaimScriptUndoAddOp : : claimName ( CClaimTrieCache & trieCache , const std : : string & name )
{
auto claimId = ClaimIdHash ( point . hash , point . n ) ;
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " --- [%lu]: OP_CLAIM_NAME \" %s \" with claimId %s and tx prevout %s at index %d \n " , nHeight , name , claimId . GetHex ( ) , point . hash . ToString ( ) , point . n ) ;
2019-05-08 00:32:22 +02:00
return undoAddClaim ( trieCache , name , claimId ) ;
}
bool CClaimScriptUndoAddOp : : updateClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " --- [%lu]: OP_UPDATE_CLAIM \" %s \" with claimId %s and tx prevout %s at index %d \n " , nHeight , name , claimId . GetHex ( ) , point . hash . ToString ( ) , point . n ) ;
2019-05-08 00:32:22 +02:00
return undoAddClaim ( trieCache , name , claimId ) ;
}
bool CClaimScriptUndoAddOp : : undoAddClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " %s: (txid: %s, nOut: %d) Removing %s, claimId: %s, from the claim trie due to block disconnect \n " , __func__ , point . hash . ToString ( ) , point . n , name , claimId . ToString ( ) ) ;
2019-05-08 00:32:22 +02:00
bool res = trieCache . undoAddClaim ( name , point , nHeight ) ;
if ( ! res )
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " %s: Removing claim fails \n " , __func__ ) ;
2019-05-08 00:32:22 +02:00
return res ;
}
bool CClaimScriptUndoAddOp : : supportClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
2019-07-29 17:47:33 +02:00
if ( LogAcceptCategory ( BCLog : : CLAIMS ) ) {
LogPrintf ( " --- [%lu]: OP_SUPPORT_CLAIM \" %s \" with claimId %s and tx prevout %s at index %d \n " , nHeight , name ,
claimId . GetHex ( ) , point . hash . ToString ( ) , point . n ) ;
LogPrintf (
" %s: (txid: %s, nOut: %d) Removing support for %s, claimId: %s, from the claim trie due to block disconnect \n " ,
__func__ , point . hash . ToString ( ) , point . n , name , claimId . ToString ( ) ) ;
}
2019-05-08 00:32:22 +02:00
bool res = trieCache . undoAddSupport ( name , point , nHeight ) ;
if ( ! res )
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " %s: Removing support fails \n " , __func__ ) ;
2019-05-08 00:32:22 +02:00
return res ;
}
CClaimScriptSpendOp : : CClaimScriptSpendOp ( const COutPoint & point , int nHeight , int & nValidHeight )
: point ( point ) , nHeight ( nHeight ) , nValidHeight ( nValidHeight )
{
}
bool CClaimScriptSpendOp : : claimName ( CClaimTrieCache & trieCache , const std : : string & name )
{
auto claimId = ClaimIdHash ( point . hash , point . n ) ;
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " +++ [%lu]: OP_CLAIM_NAME \" %s \" with claimId %s and tx prevout %s at index %d \n " , nHeight , name , claimId . GetHex ( ) , point . hash . ToString ( ) , point . n ) ;
2019-05-08 00:32:22 +02:00
return spendClaim ( trieCache , name , claimId ) ;
}
bool CClaimScriptSpendOp : : updateClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " +++ [%lu]: OP_UPDATE_CLAIM \" %s \" with claimId %s and tx prevout %s at index %d \n " , nHeight , name , claimId . GetHex ( ) , point . hash . ToString ( ) , point . n ) ;
2019-05-08 00:32:22 +02:00
return spendClaim ( trieCache , name , claimId ) ;
}
bool CClaimScriptSpendOp : : spendClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " %s: (txid: %s, nOut: %d) Removing %s, claimId: %s, from the claim trie \n " , __func__ , point . hash . ToString ( ) , point . n , name , claimId . ToString ( ) ) ;
2019-05-08 00:32:22 +02:00
bool res = trieCache . spendClaim ( name , point , nHeight , nValidHeight ) ;
if ( ! res )
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " %s: Removing fails \n " , __func__ ) ;
2019-05-08 00:32:22 +02:00
return res ;
}
bool CClaimScriptSpendOp : : supportClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
2019-07-29 17:47:33 +02:00
if ( LogAcceptCategory ( BCLog : : CLAIMS ) ) {
LogPrintf ( " +++ [%lu]: OP_SUPPORT_CLAIM \" %s \" with claimId %s and tx prevout %s at index %d \n " , nHeight , name ,
claimId . GetHex ( ) , point . hash . ToString ( ) , point . n ) ;
LogPrintf ( " %s: (txid: %s, nOut: %d) Restoring support for %s, claimId: %s, to the claim trie \n " , __func__ ,
point . hash . ToString ( ) , point . n , name , claimId . ToString ( ) ) ;
}
2019-05-08 00:32:22 +02:00
bool res = trieCache . spendSupport ( name , point , nHeight , nValidHeight ) ;
if ( ! res )
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " %s: Removing support fails \n " , __func__ ) ;
2019-05-08 00:32:22 +02:00
return res ;
}
CClaimScriptUndoSpendOp : : CClaimScriptUndoSpendOp ( const COutPoint & point , CAmount nValue , int nHeight , int nValidHeight )
: point ( point ) , nValue ( nValue ) , nHeight ( nHeight ) , nValidHeight ( nValidHeight )
{
}
bool CClaimScriptUndoSpendOp : : claimName ( CClaimTrieCache & trieCache , const std : : string & name )
{
return undoSpendClaim ( trieCache , name , ClaimIdHash ( point . hash , point . n ) ) ;
}
bool CClaimScriptUndoSpendOp : : updateClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
return undoSpendClaim ( trieCache , name , claimId ) ;
}
bool CClaimScriptUndoSpendOp : : undoSpendClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " %s: (txid: %s, nOut: %d) Restoring %s, claimId: %s, to the claim trie due to block disconnect \n " , __func__ , point . hash . ToString ( ) , point . n , name , claimId . ToString ( ) ) ;
2019-05-08 00:32:22 +02:00
return trieCache . undoSpendClaim ( name , point , claimId , nValue , nHeight , nValidHeight ) ;
}
bool CClaimScriptUndoSpendOp : : supportClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId )
{
2019-07-29 17:47:33 +02:00
LogPrint ( BCLog : : CLAIMS , " %s: (txid: %s, nOut: %d) Restoring support for %s, claimId: %s, to the claim trie due to block disconnect \n " , __func__ , point . hash . ToString ( ) , point . n , name , claimId . ToString ( ) ) ;
2019-05-08 00:32:22 +02:00
return trieCache . undoSpendSupport ( name , point , claimId , nValue , nHeight , nValidHeight ) ;
}
static std : : string vchToString ( const std : : vector < unsigned char > & name )
{
return std : : string ( name . begin ( ) , name . end ( ) ) ;
}
bool ProcessClaim ( CClaimScriptOp & claimOp , CClaimTrieCache & trieCache , const CScript & scriptPubKey )
{
int op ;
std : : vector < std : : vector < unsigned char > > vvchParams ;
2019-09-04 22:27:07 +02:00
if ( ! DecodeClaimScript ( scriptPubKey , op , vvchParams , trieCache . allowSupportMetadata ( ) ) )
2019-05-08 00:32:22 +02:00
return false ;
switch ( op ) {
case OP_CLAIM_NAME :
return claimOp . claimName ( trieCache , vchToString ( vvchParams [ 0 ] ) ) ;
case OP_SUPPORT_CLAIM :
return claimOp . supportClaim ( trieCache , vchToString ( vvchParams [ 0 ] ) , uint160 ( vvchParams [ 1 ] ) ) ;
case OP_UPDATE_CLAIM :
return claimOp . updateClaim ( trieCache , vchToString ( vvchParams [ 0 ] ) , uint160 ( vvchParams [ 1 ] ) ) ;
}
throw std : : runtime_error ( " Unimplemented OP handler. " ) ;
}
2019-07-09 17:02:54 +02:00
void UpdateCache ( const CTransaction & tx , CClaimTrieCache & trieCache , const CCoinsViewCache & view , int nHeight , const CUpdateCacheCallbacks & callbacks )
2019-05-08 00:32:22 +02:00
{
class CSpendClaimHistory : public CClaimScriptSpendOp
{
public :
2019-07-09 17:02:54 +02:00
using CClaimScriptSpendOp : : CClaimScriptSpendOp ;
2019-05-08 00:32:22 +02:00
bool spendClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId ) override
{
if ( CClaimScriptSpendOp : : spendClaim ( trieCache , name , claimId ) ) {
2019-07-09 17:02:54 +02:00
callback ( name , claimId ) ;
2019-05-08 00:32:22 +02:00
return true ;
}
return false ;
}
2019-07-09 17:02:54 +02:00
std : : function < void ( const std : : string & name , const uint160 & claimId ) > callback ;
2019-05-08 00:32:22 +02:00
} ;
2019-07-09 17:02:54 +02:00
spentClaimsType spentClaims ;
for ( std : : size_t j = 0 ; j < tx . vin . size ( ) ; j + + ) {
const CTxIn & txin = tx . vin [ j ] ;
const Coin & coin = view . AccessCoin ( txin . prevout ) ;
CScript scriptPubKey ;
int scriptHeight = nHeight ;
if ( coin . out . IsNull ( ) & & callbacks . findScriptKey ) {
scriptPubKey = callbacks . findScriptKey ( txin . prevout ) ;
} else {
scriptHeight = coin . nHeight ;
scriptPubKey = coin . out . scriptPubKey ;
}
if ( scriptPubKey . empty ( ) )
continue ;
int nValidAtHeight ;
CSpendClaimHistory spendClaim ( COutPoint ( txin . prevout . hash , txin . prevout . n ) , scriptHeight , nValidAtHeight ) ;
spendClaim . callback = [ & spentClaims ] ( const std : : string & name , const uint160 & claimId ) {
spentClaims . emplace_back ( name , claimId ) ;
} ;
if ( ProcessClaim ( spendClaim , trieCache , scriptPubKey ) & & callbacks . claimUndoHeights )
callbacks . claimUndoHeights ( j , nValidAtHeight ) ;
}
2019-05-08 00:32:22 +02:00
class CAddSpendClaim : public CClaimScriptAddOp
{
public :
2019-07-09 17:02:54 +02:00
using CClaimScriptAddOp : : CClaimScriptAddOp ;
2019-05-08 00:32:22 +02:00
bool updateClaim ( CClaimTrieCache & trieCache , const std : : string & name , const uint160 & claimId ) override
{
2019-07-09 17:02:54 +02:00
if ( callback ( name , claimId ) )
return CClaimScriptAddOp : : updateClaim ( trieCache , name , claimId ) ;
return false ;
}
std : : function < bool ( const std : : string & name , const uint160 & claimId ) > callback ;
} ;
for ( std : : size_t j = 0 ; j < tx . vout . size ( ) ; j + + ) {
const CTxOut & txout = tx . vout [ j ] ;
if ( txout . scriptPubKey . empty ( ) )
continue ;
CAddSpendClaim addClaim ( COutPoint ( tx . GetHash ( ) , j ) , txout . nValue , nHeight ) ;
addClaim . callback = [ & trieCache , & spentClaims ] ( const std : : string & name , const uint160 & claimId ) - > bool {
for ( auto itSpent = spentClaims . begin ( ) ; itSpent ! = spentClaims . end ( ) ; + + itSpent ) {
2019-05-08 00:32:22 +02:00
if ( itSpent - > second = = claimId & & trieCache . normalizeClaimName ( name ) = = trieCache . normalizeClaimName ( itSpent - > first ) ) {
spentClaims . erase ( itSpent ) ;
2019-07-09 17:02:54 +02:00
return true ;
2019-05-08 00:32:22 +02:00
}
}
return false ;
2019-07-09 17:02:54 +02:00
} ;
ProcessClaim ( addClaim , trieCache , txout . scriptPubKey ) ;
}
}