Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 2)
define(_CLIENT_VERSION_MINOR, 1)
define(_CLIENT_VERSION_REVISION, 0)
define(_CLIENT_VERSION_REVISION, 1)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2018)
Expand Down
207 changes: 110 additions & 97 deletions src/assets/assets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -659,52 +659,75 @@ bool CTransaction::IsNewAsset() const
}

//! To be called on CTransactions where IsNewAsset returns true
bool CTransaction::VerifyNewAsset() const
bool CTransaction::VerifyNewAsset(std::string& strError) const
{
// Issuing an Asset must contain at least 3 CTxOut( Raven Burn Tx, Any Number of other Outputs ..., Owner Asset Tx, New Asset Tx)
if (vout.size() < 3)
return false;

// Loop through all of the vouts and make sure only the expected asset creations are taking place
int nTransfers = 0;
int nOwners = 0;
int nIssues = 0;
int nReissues = 0;
GetTxOutAssetTypes(vout, nIssues, nReissues, nTransfers, nOwners);

if (nOwners != 1 || nIssues != 1 || nReissues > 0)
if (vout.size() < 3) {
strError = "bad-txns-issue-vout-size-to-small";
return false;
}

// Check for the assets data CTxOut. This will always be the last output in the transaction
if (!CheckIssueDataTx(vout[vout.size() - 1]))
if (!CheckIssueDataTx(vout[vout.size() - 1])) {
strError = "bad-txns-issue-data-not-found";
return false;
}

// Check to make sure the owner asset is created
if (!CheckOwnerDataTx(vout[vout.size() - 2]))
if (!CheckOwnerDataTx(vout[vout.size() - 2])) {
strError = "bad-txns-issue-owner-data-not-found";
return false;
}

// Get the asset type
CNewAsset asset;
std::string address;
if (!AssetFromScript(vout[vout.size() - 1].scriptPubKey, asset, address))
if (!AssetFromScript(vout[vout.size() - 1].scriptPubKey, asset, address)) {
strError = "bad-txns-issue-serialzation-failed";
return error("%s : Failed to get new asset from transaction: %s", __func__, this->GetHash().GetHex());
}

AssetType assetType;
IsAssetNameValid(asset.strName, assetType);

std::string strOwnerName;
if (!OwnerAssetFromScript(vout[vout.size() - 2].scriptPubKey, strOwnerName, address))
if (!OwnerAssetFromScript(vout[vout.size() - 2].scriptPubKey, strOwnerName, address)) {
strError = "bad-txns-issue-owner-serialzation-failed";
return false;
}

if (strOwnerName != asset.strName + OWNER_TAG)
if (strOwnerName != asset.strName + OWNER_TAG) {
strError = "bad-txns-issue-owner-name-doesn't-match";
return false;
}

// Check for the Burn CTxOut in one of the vouts ( This is needed because the change CTxOut is places in a random position in the CWalletTx
for (auto out : vout)
if (CheckIssueBurnTx(out, assetType))
return true;
bool fFoundIssueBurnTx = false;
for (auto out : vout) {
if (CheckIssueBurnTx(out, assetType)) {
fFoundIssueBurnTx = true;
break;
}
}

return false;
if (!fFoundIssueBurnTx) {
strError = "bad-txns-issue-owner-burn-not-found";
return false;
}

// Loop through all of the vouts and make sure only the expected asset creations are taking place
int nTransfers = 0;
int nOwners = 0;
int nIssues = 0;
int nReissues = 0;
GetTxOutAssetTypes(vout, nIssues, nReissues, nTransfers, nOwners);

if (nOwners != 1 || nIssues != 1 || nReissues > 0) {
strError = "bad-txns-failed-issue-asset-formatting-check";
return false;
}

return true;
}

//! Make sure to call VerifyNewUniqueAsset if this call returns true
Expand All @@ -721,11 +744,13 @@ bool CTransaction::IsNewUniqueAsset() const
}

//! Call this function after IsNewUniqueAsset
bool CTransaction::VerifyNewUniqueAsset(CCoinsViewCache& view) const
bool CTransaction::VerifyNewUniqueAsset(std::string& strError) const
{
// Must contain at least 3 outpoints (RVN burn, owner change and one or more new unique assets that share a root (should be in trailing position))
if (vout.size() < 3)
if (vout.size() < 3) {
strError = "bad-txns-unique-vout-size-to-small";
return false;
}

// check for (and count) new unique asset outpoints. make sure they share a root.
std::string assetRoot = "";
Expand All @@ -734,66 +759,57 @@ bool CTransaction::VerifyNewUniqueAsset(CCoinsViewCache& view) const
if (IsScriptNewUniqueAsset(out.scriptPubKey)) {
CNewAsset asset;
std::string address;
if (!AssetFromScript(out.scriptPubKey, asset, address))
if (!AssetFromScript(out.scriptPubKey, asset, address)) {
strError = "bad-txns-issue-unique-asset-from-script";
return false;
}
std::string root = GetParentName(asset.strName);
if (assetRoot.compare("") == 0)
assetRoot = root;
if (assetRoot.compare(root) != 0)
if (assetRoot.compare(root) != 0) {
strError = "bad-txns-issue-unique-asset-compare-failed";
return false;
}
assetOutpointCount += 1;
}
}
if (assetOutpointCount == 0)

if (assetOutpointCount == 0) {
strError = "bad-txns-issue-unique-asset-bad-outpoint-count";
return false;
}

// check for burn outpoint (must account for each new asset)
bool fBurnOutpointFound = false;
for (auto out : vout)
for (auto out : vout) {
if (CheckIssueBurnTx(out, AssetType::UNIQUE, assetOutpointCount)) {
fBurnOutpointFound = true;
break;
}
if (!fBurnOutpointFound)
}

if (!fBurnOutpointFound) {
strError = "bad-txns-issue-unique-asset-burn-outpoints-not-found";
return false;
}

// check for owner change outpoint that matches root
bool fOwnerOutFound = false;
for (auto out : vout) {
if (CheckTransferOwnerTx(out)) {
fOwnerOutFound = true;
break;
}
}

if (!fOwnerOutFound)
return false;

// The owner change output must match a corresponding owner input
bool fFoundCorrectInput = false;
for (unsigned int i = 0; i < vin.size(); ++i) {
const COutPoint &prevout = vin[i].prevout;
const Coin& coin = view.AccessCoin(prevout);
assert(!coin.IsSpent());

int nType = -1;
bool fOwner = false;
if (coin.out.scriptPubKey.IsAssetScript(nType, fOwner)) {
std::string strAssetName;
CAmount nAssetAmount;
if (!GetAssetInfoFromCoin(coin, strAssetName, nAssetAmount))
continue;
if (IsAssetNameAnOwner(strAssetName)) {
if (strAssetName == assetRoot + OWNER_TAG) {
fFoundCorrectInput = true;
break;
}
CAssetTransfer transfer;
std::string transferAddress;
if (TransferAssetFromScript(out.scriptPubKey, transfer, transferAddress)) {
if (assetRoot + OWNER_TAG == transfer.strName) {
fOwnerOutFound = true;
break;
}
}
}

if (!fFoundCorrectInput)
if (!fOwnerOutFound) {
strError = "bad-txns-issue-unique-asset-bad-owner-asset";
return false;
}

// Loop through all of the vouts and make sure only the expected asset creations are taking place
int nTransfers = 0;
Expand All @@ -803,10 +819,10 @@ bool CTransaction::VerifyNewUniqueAsset(CCoinsViewCache& view) const
GetTxOutAssetTypes(vout, nIssues, nReissues, nTransfers, nOwners);

if (nOwners > 0 || nReissues > 0 || nIssues != assetOutpointCount) {
strError = "bad-txns-failed-unique-asset-formatting-check";
return false;
}


return true;
}

Expand All @@ -820,63 +836,58 @@ bool CTransaction::IsReissueAsset() const
}

//! To be called on CTransactions where IsReissueAsset returns true
bool CTransaction::VerifyReissueAsset(CCoinsViewCache& view) const
bool CTransaction::VerifyReissueAsset(std::string& strError) const
{
// Reissuing an Asset must contain at least 3 CTxOut ( Raven Burn Tx, Any Number of other Outputs ..., Reissue Asset Tx, Owner Asset Change Tx)
if (vout.size() < 3)
if (vout.size() < 3) {
strError = "bad-txns-vout-size-to-small";
return false;
}

// Check for the reissue asset data CTxOut. This will always be the last output in the transaction
if (!CheckReissueDataTx(vout[vout.size() - 1]))
if (!CheckReissueDataTx(vout[vout.size() - 1])) {
strError = "bad-txns-reissue-data-not-found";
return false;

// Check that there is an asset transfer, this will be the owner asset change
bool fOwnerOutFound = false;
for (auto out : vout) {
if (CheckTransferOwnerTx(out)) {
fOwnerOutFound = true;
break;
}
}

if (!fOwnerOutFound)
return false;

CReissueAsset reissue;
std::string address;
if (!ReissueAssetFromScript(vout[vout.size() - 1].scriptPubKey, reissue, address))
if (!ReissueAssetFromScript(vout[vout.size() - 1].scriptPubKey, reissue, address)) {
strError = "bad-txns-reissue-serialization-failed";
return false;
}

bool fFoundCorrectInput = false;
for (unsigned int i = 0; i < vin.size(); ++i) {
const COutPoint &prevout = vin[i].prevout;
const Coin& coin = view.AccessCoin(prevout);
assert(!coin.IsSpent());

int nType = -1;
bool fOwner = false;
if (coin.out.scriptPubKey.IsAssetScript(nType, fOwner)) {
std::string strAssetName;
CAmount nAssetAmount;
if (!GetAssetInfoFromCoin(coin, strAssetName, nAssetAmount))
continue;
if (IsAssetNameAnOwner(strAssetName)) {
if (strAssetName == reissue.strName + OWNER_TAG) {
fFoundCorrectInput = true;
break;
}
// Check that there is an asset transfer, this will be the owner asset change
bool fOwnerOutFound = false;
for (auto out : vout) {
CAssetTransfer transfer;
std::string transferAddress;
if (TransferAssetFromScript(out.scriptPubKey, transfer, transferAddress)) {
if (reissue.strName + OWNER_TAG == transfer.strName) {
fOwnerOutFound = true;
break;
}
}
}

if (!fFoundCorrectInput)
if (!fOwnerOutFound) {
strError = "bad-txns-reissue-owner-outpoint-not-found";
return false;
}

// Check for the Burn CTxOut in one of the vouts ( This is needed because the change CTxOut is placed in a random position in the CWalletTx
for (auto out : vout)
if (CheckReissueBurnTx(out))
return true;
bool fFoundReissueBurnTx = false;
for (auto out : vout) {
if (CheckReissueBurnTx(out)) {
fFoundReissueBurnTx = true;
break;
}
}

if (!fFoundReissueBurnTx) {
strError = "bad-txns-reissue-burn-outpoint-not-found";
return false;
}

// Loop through all of the vouts and make sure only the expected asset creations are taking place
int nTransfers = 0;
Expand All @@ -885,10 +896,12 @@ bool CTransaction::VerifyReissueAsset(CCoinsViewCache& view) const
int nReissues = 0;
GetTxOutAssetTypes(vout, nIssues, nReissues, nTransfers, nOwners);

if (nOwners > 0 || nReissues != 1 || nIssues > 0)
if (nOwners > 0 || nReissues != 1 || nIssues > 0) {
strError = "bad-txns-failed-reissue-asset-formatting-check";
return false;
}

return false;
return true;
}

CAssetTransfer::CAssetTransfer(const std::string& strAssetName, const CAmount& nAmount)
Expand Down
Loading