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)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptAddOp::claimName(CClaimTrieCache& trieCache, const std::string& name,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-11-07 19:29:38 +01:00
|
|
|
auto claimId = ClaimIdHash(point.hash, point.n);
|
2019-11-08 00:42:37 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "+++ Claim added: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n",
|
2019-11-07 19:29:38 +01:00
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue);
|
|
|
|
return addClaim(trieCache, name, claimId, -1, metadata);
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptAddOp::updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-11-08 00:42:37 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "+++ Claim updated: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n",
|
2019-11-07 19:29:38 +01:00
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue);
|
2019-10-29 00:15:42 +01:00
|
|
|
return addClaim(trieCache, name, claimId, -1, metadata);
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptAddOp::addClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
2019-10-29 00:15:42 +01:00
|
|
|
int takeoverHeight, const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-10-29 00:15:42 +01:00
|
|
|
return trieCache.addClaim(name, point, claimId, nValue, nHeight, takeoverHeight, metadata);
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptAddOp::supportClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-11-08 00:42:37 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "+++ Support added: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n",
|
2019-11-07 19:29:38 +01:00
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue);
|
2019-10-09 17:09:30 +02:00
|
|
|
return trieCache.addSupport(name, point, claimId, nValue, nHeight, -1, metadata);
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CClaimScriptUndoAddOp::CClaimScriptUndoAddOp(const COutPoint& point, int nHeight) : point(point), nHeight(nHeight)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptUndoAddOp::claimName(CClaimTrieCache& trieCache, const std::string& name,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
|
|
|
auto claimId = ClaimIdHash(point.hash, point.n);
|
2019-11-07 19:29:38 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "--- Undoing claim add: %s, c: %.6s, t: %.6s:%d, h: %.6d\n",
|
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight);
|
2019-05-08 00:32:22 +02:00
|
|
|
return undoAddClaim(trieCache, name, claimId);
|
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptUndoAddOp::updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-11-07 19:29:38 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "--- Undoing claim update: %s, c: %.6s, t: %.6s:%d, h: %.6d\n",
|
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight);
|
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-10-23 22:15:37 +02:00
|
|
|
std::string nodeName;
|
|
|
|
int validHeight;
|
2019-10-29 00:15:42 +01:00
|
|
|
bool res = trieCache.removeClaim(claimId, point, nodeName, validHeight);
|
2019-05-08 00:32:22 +02:00
|
|
|
if (!res)
|
2019-11-07 19:29:38 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "Remove claim failed for %s with claimid %s\n", name, claimId.GetHex().substr(0, 6));
|
2019-05-08 00:32:22 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptUndoAddOp::supportClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-11-07 19:29:38 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "--- Undoing support add: %s, c: %.6s, t: %.6s:%d, h: %.6d\n",
|
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight);
|
2019-10-23 22:15:37 +02:00
|
|
|
std::string nodeName;
|
|
|
|
int validHeight;
|
|
|
|
bool res = trieCache.removeSupport(point, nodeName, validHeight);
|
2019-05-08 00:32:22 +02:00
|
|
|
if (!res)
|
2019-11-07 19:29:38 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "Remove support failed for %s with claimid %s\n", name, claimId.GetHex().substr(0, 6));
|
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)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptSpendOp::claimName(CClaimTrieCache& trieCache, const std::string& name,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
|
|
|
auto claimId = ClaimIdHash(point.hash, point.n);
|
2019-11-07 19:29:38 +01:00
|
|
|
auto ret = spendClaim(trieCache, name, claimId);
|
2019-11-13 00:54:16 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "--- Spent original claim: %s, c: %.6s, t: %.6s:%d, h: %.6d, vh: %d\n",
|
2019-11-07 19:29:38 +01:00
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValidHeight);
|
|
|
|
return ret;
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptSpendOp::updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-11-07 19:29:38 +01:00
|
|
|
auto ret = spendClaim(trieCache, name, claimId);
|
2019-11-13 00:54:16 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "--- Spent updated claim: %s, c: %.6s, t: %.6s:%d, h: %.6d, vh: %d\n",
|
2019-11-07 19:29:38 +01:00
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValidHeight);
|
|
|
|
return ret;
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CClaimScriptSpendOp::spendClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId)
|
|
|
|
{
|
2019-10-23 22:15:37 +02:00
|
|
|
std::string nodeName;
|
2019-10-29 00:15:42 +01:00
|
|
|
bool res = trieCache.removeClaim(claimId, point, nodeName, nValidHeight);
|
2019-05-08 00:32:22 +02:00
|
|
|
if (!res)
|
2019-11-07 19:29:38 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "Remove claim failed for %s with claimid %s\n", name, claimId.GetHex().substr(0, 6));
|
2019-05-08 00:32:22 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptSpendOp::supportClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-10-23 22:15:37 +02:00
|
|
|
std::string nodeName;
|
|
|
|
bool res = trieCache.removeSupport(point, nodeName, nValidHeight);
|
2019-11-13 00:54:16 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "--- Spent support: %s, c: %.6s, t: %.6s:%d, h: %.6d, vh: %d\n",
|
2019-11-07 19:29:38 +01:00
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValidHeight);
|
2019-05-08 00:32:22 +02:00
|
|
|
if (!res)
|
2019-11-07 19:29:38 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "Remove support failed for %s with claimid %s\n", name, claimId.GetHex().substr(0, 6));
|
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)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptUndoSpendOp::claimName(CClaimTrieCache& trieCache, const std::string& name,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-11-07 19:29:38 +01:00
|
|
|
auto claimId = ClaimIdHash(point.hash, point.n);
|
|
|
|
LogPrint(BCLog::CLAIMS, "+++ Undoing original claim spend: %s, c: %.6s, t: %.6s:%d, h: %.6d, vh: %d\n",
|
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValidHeight);
|
|
|
|
return undoSpendClaim(trieCache, name, claimId, metadata);
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptUndoSpendOp::updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-11-07 19:29:38 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "+++ Undoing updated claim spend: %s, c: %.6s, t: %.6s:%d, h: %.6d, vh: %d\n",
|
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValidHeight);
|
2019-10-23 22:15:37 +02:00
|
|
|
return undoSpendClaim(trieCache, name, claimId, metadata);
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptUndoSpendOp::undoSpendClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-10-29 00:15:42 +01:00
|
|
|
return trieCache.addClaim(name, point, claimId, nValue, nHeight, nValidHeight, metadata);
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool CClaimScriptUndoSpendOp::supportClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
|
|
|
const std::vector<unsigned char>& metadata)
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-11-07 19:29:38 +01:00
|
|
|
LogPrint(BCLog::CLAIMS, "+++ Undoing support spend: %s, c: %.6s, t: %.6s:%d, h: %.6d, vh: %d\n",
|
|
|
|
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValidHeight);
|
2019-10-09 17:09:30 +02:00
|
|
|
return trieCache.addSupport(name, point, claimId, nValue, nHeight, nValidHeight, metadata);
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
2019-10-23 22:15:37 +02:00
|
|
|
return claimOp.claimName(trieCache, vchToString(vvchParams[0]), vvchParams[1]);
|
2019-05-08 00:32:22 +02:00
|
|
|
case OP_SUPPORT_CLAIM:
|
2019-10-23 22:15:37 +02:00
|
|
|
return claimOp.supportClaim(trieCache, vchToString(vvchParams[0]), uint160(vvchParams[1]),
|
|
|
|
vvchParams.size() > 2 ? vvchParams[2] : std::vector<unsigned char>());
|
2019-05-08 00:32:22 +02:00
|
|
|
case OP_UPDATE_CLAIM:
|
2019-10-23 22:15:37 +02:00
|
|
|
return claimOp.updateClaim(trieCache, vchToString(vvchParams[0]), uint160(vvchParams[1]),
|
|
|
|
vvchParams[2]);
|
2019-10-31 06:13:07 +01:00
|
|
|
default:
|
|
|
|
throw std::runtime_error("Unimplemented OP handler.");
|
2019-05-08 00:32:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-10-31 06:13:07 +01:00
|
|
|
callback(name, claimId);
|
2019-05-08 00:32:22 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2019-10-31 06:13:07 +01: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);
|
2019-10-31 06:13:07 +01:00
|
|
|
spendClaim.callback = [&spentClaims](const std::string& name, const uint160& claimId) {
|
|
|
|
spentClaims.emplace_back(name, claimId);
|
2019-07-09 17:02:54 +02:00
|
|
|
};
|
|
|
|
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
|
|
|
|
2019-10-23 22:15:37 +02:00
|
|
|
bool updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
|
2019-10-29 00:15:42 +01:00
|
|
|
const std::vector<unsigned char>& metadata) override
|
2019-05-08 00:32:22 +02:00
|
|
|
{
|
2019-10-31 06:13:07 +01:00
|
|
|
if (callback(name, claimId))
|
2019-11-07 19:29:38 +01:00
|
|
|
return CClaimScriptAddOp::updateClaim(trieCache, name, claimId, metadata);
|
2019-07-09 17:02:54 +02:00
|
|
|
return false;
|
|
|
|
}
|
2019-10-31 06:13:07 +01:00
|
|
|
std::function<bool(const std::string& name, const uint160& claimId)> callback;
|
2019-07-09 17:02:54 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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);
|
2019-10-31 06:13:07 +01:00
|
|
|
addClaim.callback = [&trieCache, &spentClaims](const std::string& name, const uint160& claimId) -> bool {
|
2019-07-09 17:02:54 +02:00
|
|
|
for (auto itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent) {
|
2019-10-31 06:13:07 +01:00
|
|
|
if (itSpent->second == claimId && trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first)) {
|
2019-05-08 00:32:22 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|