Browse Source

Merge pull request #453 from VerusCoin/dev

Dev
master
Asher Dawes 2 years ago
committed by GitHub
parent
commit
d3cb2c6b63
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .gitlab-ci.yml
  2. 2
      README.md
  3. 2
      doc/man/verus-cli/linux/README.txt
  4. 2
      doc/man/verus-cli/mac/README.txt
  5. 2
      doc/man/verus-cli/windows/README.txt
  6. 17
      src/core_write.cpp
  7. 2
      src/deprecation.h
  8. 22
      src/key_io.cpp
  9. 73
      src/pbaas/crosschainrpc.h
  10. 2
      src/pbaas/identity.cpp
  11. 62
      src/pbaas/notarization.cpp
  12. 62
      src/pbaas/pbaas.cpp
  13. 2
      src/version.h

2
.gitlab-ci.yml

@ -7,7 +7,7 @@ stages:
########################################################################################################################
variables:
VERSION: 0.9.4-2
VERSION: 0.9.4-3
VERUS_CLI_ARM64_LINUX: Verus-CLI-Linux-v${VERSION}-arm64.tar.gz
VERUS_CLI_LINUX_X86_64: Verus-CLI-Linux-v${VERSION}-x86_64.tar.gz

2
README.md

@ -1,5 +1,5 @@
## VerusCoin version 0.9.4-2
## VerusCoin version 0.9.4-3
Arguably the world's most advanced technology, zero knowledge privacy-centric blockchain, Verus Coin brings Sapling performance and zero knowledge features to an intelligent system with interchain smart contracts and a completely original, combined proof of stake/proof of work consensus algorithm that solves the nothing at stake problem. With this and its approach towards CPU mining and ASICs, Verus Coin strives to be one of the most naturally decentralizing and attack resistant blockchains in existence.

2
doc/man/verus-cli/linux/README.txt

@ -1,5 +1,5 @@
VerusCoin Command Line Tools v0.9.4-2
VerusCoin Command Line Tools v0.9.4-3
Contents:
verusd - VerusCoin daemon

2
doc/man/verus-cli/mac/README.txt

@ -1,5 +1,5 @@
VerusCoin Command Line Tools v0.9.4-2
VerusCoin Command Line Tools v0.9.4-3
Contents:
verusd - VerusCoin daemon.

2
doc/man/verus-cli/windows/README.txt

@ -1,5 +1,5 @@
VerusCoin Command Line Tools v0.9.4-2
VerusCoin Command Line Tools v0.9.4-3
Contents:
verusd.exe - VerusCoin daemon

17
src/core_write.cpp

@ -883,6 +883,14 @@ UniValue CReserveDeposit::ToUniValue() const
return ret;
}
UniValue CETHNFTAddress::ToUniValue() const
{
UniValue ret(UniValue::VOBJ);
ret.pushKV("contract", "0x" + HexBytes(contractID.begin(), contractID.size()));
ret.pushKV("tokenid", "0x" + HexBytes(tokenID.begin(), tokenID.size()));
return ret;
}
UniValue CTransferDestination::ToUniValue() const
{
UniValue destVal = UniValue(UniValue::VOBJ);
@ -918,6 +926,15 @@ UniValue CTransferDestination::ToUniValue() const
destVal.push_back(Pair("address", EncodeEthDestination(uint160(destination))));
break;
case CTransferDestination::DEST_ETHNFT:
{
CETHNFTAddress oneAddr;
bool success = false;
::FromVector(destination, oneAddr, &success);
destVal.push_back(Pair("address", success ? oneAddr.ToUniValue() : UniValue(UniValue::VOBJ)));
break;
}
case CTransferDestination::DEST_FULLID:
destVal.push_back(Pair("identity", CIdentity(destination).ToUniValue()));
destVal.push_back(Pair("serializeddata", HexBytes(&(destination[0]), destination.size())));

2
src/deprecation.h

@ -9,7 +9,7 @@
// * Shut down 20 weeks' worth of blocks after the estimated release block height.
// * A warning is shown during the 2 weeks' worth of blocks prior to shut down.
static const int APPROX_RELEASE_HEIGHT = 2191000;
static const int APPROX_RELEASE_HEIGHT = 2197000;
static const int WEEKS_UNTIL_DEPRECATION = 20;
static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 60 * 24);

22
src/key_io.cpp

@ -740,6 +740,20 @@ CIdentity::CIdentity(const UniValue &uni) : CPrincipal(uni)
}
}
CETHNFTAddress::CETHNFTAddress(const UniValue &uni)
{
std::string contractAddrStr = uni_get_str(find_value(uni, "contract"));
std::string TokenIDStr = uni_get_str(find_value(uni, "tokenid"));
if (!(contractID = CTransferDestination::DecodeEthDestination(contractAddrStr)).IsNull() &&
TokenIDStr.length() == 66 &&
TokenIDStr.substr(0,2) == "0x" &&
IsHex(TokenIDStr.substr(2,64)))
{
tokenID = uint256(ParseHex(TokenIDStr.substr(2,64)));
}
}
CTransferDestination::CTransferDestination(const UniValue &obj) : fees(0)
{
type = uni_get_int(find_value(obj, "type"));
@ -777,6 +791,13 @@ CTransferDestination::CTransferDestination(const UniValue &obj) : fees(0)
break;
}
case CTransferDestination::DEST_ETHNFT:
{
CETHNFTAddress ethNFTAddress(find_value(obj, "address"));
destination = ::AsVector(ethNFTAddress);
break;
}
case CTransferDestination::DEST_FULLID:
{
std::string serializedHex(uni_get_str(find_value(obj, "serializeddata")));
@ -1212,6 +1233,7 @@ CScript CIdentity::IdentityUpdateOutputScript(uint32_t height, const std::vector
if (IsRevoked())
{
// TODO: HARDENING for next testnet reset and mainnet release version, remove primary when revoked
ret = MakeMofNCCScript(1, primary, recovery, indexDests);
}
else

73
src/pbaas/crosschainrpc.h

@ -161,6 +161,27 @@ public:
}
};
class CETHNFTAddress
{
public:
uint160 contractID;
uint256 tokenID;
CETHNFTAddress() {}
CETHNFTAddress(const UniValue &uni);
CETHNFTAddress(const uint160 &contract, const uint256 &token) : contractID(contract), tokenID(token) {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(contractID);
READWRITE(tokenID);
}
UniValue ToUniValue() const;
};
class CTransferDestination
{
public:
@ -321,22 +342,8 @@ public:
uint256 retTokenID;
UniValue nftJSON(UniValue::VOBJ);
nftJSON.read(destStr);
std::string contractAddrStr = uni_get_str(find_value(nftJSON, "contract"));
std::string TokenIDStr = uni_get_str(find_value(nftJSON, "tokenid"));
if (!(retContract = DecodeEthDestination(contractAddrStr)).IsNull() &&
TokenIDStr.length() == 66 &&
destStr.substr(0,2) == "0x" &&
IsHex(TokenIDStr.substr(2,64)))
{
retTokenID = uint256S(TokenIDStr.substr(2,64));
return std::make_pair(retContract, uint256S(TokenIDStr));
}
else
{
return std::make_pair(uint160(), uint256());
}
CETHNFTAddress retAddr(nftJSON);
return std::make_pair(retAddr.contractID, retAddr.tokenID);
}
static std::string EncodeEthNFTDestination(const uint160 &ethContractID, const uint256 &tokenID)
@ -364,40 +371,6 @@ public:
UniValue ToUniValue() const;
};
class CNFTAddress
{
public:
uint32_t version;
CTransferDestination rootContractOrID;
std::vector<uint160> shortHashes;
std::vector<uint256> longHashes;
enum EVersions {
VERSION_INVALID = 0,
VERSION_VERUSID = 1,
VERSION_FIRST = 1,
VERSION_DEFAULT = 1,
VERSION_LAST = 1
};
CNFTAddress(const UniValue &uni);
CNFTAddress(uint32_t ver=VERSION_DEFAULT) : version(ver) {}
CNFTAddress(const CTransferDestination &rootDest, const std::vector<uint160> &shorts, const std::vector<uint256> &longs, uint32_t ver=VERSION_DEFAULT) :
version(ver), rootContractOrID(rootDest), shortHashes(shorts), longHashes(longs) {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(VARINT(version));
READWRITE(rootContractOrID);
READWRITE(shortHashes);
READWRITE(longHashes);
}
UniValue ToUniValue() const;
};
extern int64_t AmountFromValueNoErr(const UniValue& value);
// convenience class for collections of currencies that supports comparisons, including ==, >, >=, <, <=, as well as addition, and subtraction

2
src/pbaas/identity.cpp

@ -2154,7 +2154,7 @@ bool PrecheckIdentityPrimary(const CTransaction &tx, int32_t outNum, CValidation
// consider the signature unfulfilled
if ((PBAAS_TESTMODE && (!(IsVerusActive() || ConnectedChains.ThisChain().name == "Gravity") || height >= TESTNET_FORK_HEIGHT)) && identity.HasTokenizedControl())
{
if (!(oneP.m == 1 && oneP.n > 1))
if (!(oneP.m == 1 && oneP.n >= oneP.m))
{
std::string errorOut = "Invalid spend condition for tokenized control in: \"" + identity.name + "\"";
return state.Error(errorOut.c_str());

62
src/pbaas/notarization.cpp

@ -2784,6 +2784,31 @@ bool CPBaaSNotarization::CreateEarnedNotarization(const CRPCChainData &externalS
return state.Error(result.isNull() ? "no-notary" : "no-matching-proof-roots-found");
}
CProofRoot lastStableProofRoot(find_value(result, "laststableproofroot"));
// work around race condition or Infura API issue under investigation in ETH bridge, where it does not confirm
// one of our proof roots, while at the same time returning identical data in laststableproofroot.
if (!lastConfirmedProofRoot.IsValid() && lastStableProofRoot.IsValid())
{
for (int i = cnd.vtx.size() - 1; i >= 0; i--)
{
auto it = cnd.vtx[i].second.proofRoots.find(SystemID);
if (it != cnd.vtx[i].second.proofRoots.end())
{
if (it->second.rootHeight < lastStableProofRoot.rootHeight)
{
break;
}
else if (it->second.rootHeight == lastStableProofRoot.rootHeight &&
it->second == lastStableProofRoot && notaryIdx != i)
{
LogPrintf("%s: notarization was rejected with identical proof root to last stable: %s\n", __func__, cnd.vtx[i].second.ToUniValue().write(1,2).c_str());
notaryIdx = i;
}
}
}
}
// now, we have the index for the transaction and notarization we agree with, a list of those we consider invalid,
// and the most recent notarization to use when creating the new one
const CTransaction &priorNotarizationTx = txes[notaryIdx].first;
@ -3451,10 +3476,6 @@ bool CPBaaSNotarization::ConfirmOrRejectNotarizations(CWallet *pWallet,
std::vector<std::pair<CIdentityMapKey, CIdentityMapValue>> imsigner, watchonly;
LOCK(pWallet->cs_wallet);
pWallet->GetIdentities(pNotaryCurrency->notaries, mine, imsigner, watchonly);
if (!mine.size())
{
return state.Error("no-notary");
}
}
{
@ -3560,14 +3581,14 @@ bool CPBaaSNotarization::ConfirmOrRejectNotarizations(CWallet *pWallet,
}
}
else if (cnd.forks.size() &&
(cnd.forks[0].size() > 2 || ConnectedChains.ThisChain().notarizationProtocol != CCurrencyDefinition::NOTARIZATION_AUTO))
(cnd.forks[0].size() > 2 || pNotaryCurrency->notarizationProtocol != CCurrencyDefinition::NOTARIZATION_AUTO))
{
bestFork = cnd.forks[0];
}
bool isFirstConfirmedCND = cnd.vtx[cnd.lastConfirmed].second.IsBlockOneNotarization() || cnd.vtx[cnd.lastConfirmed].second.IsDefinitionNotarization();
if ((bestFork.size() < ((ConnectedChains.ThisChain().notarizationProtocol == CCurrencyDefinition::NOTARIZATION_AUTO) ? 3 : 2)) ||
if ((bestFork.size() < ((pNotaryCurrency->notarizationProtocol == CCurrencyDefinition::NOTARIZATION_AUTO) ? 3 : 2)) ||
(!isFirstConfirmedCND && !cnd.vtx[cnd.lastConfirmed].second.proofRoots.count(SystemID)))
{
return state.Error("insufficient validator confirmations");
@ -3635,6 +3656,9 @@ bool CPBaaSNotarization::ConfirmOrRejectNotarizations(CWallet *pWallet,
return state.Error(result.isNull() ? "no-notary" : "no-matching-notarization-found");
}
// get the index from the best fork to make it an index into cnd.vtx
notaryIdx = bestFork[notaryIdx];
// take the lock again, now that we're back from calling out
LOCK(cs_main);
@ -3726,24 +3750,24 @@ bool CPBaaSNotarization::ConfirmOrRejectNotarizations(CWallet *pWallet,
indexKey.GetHex().c_str()); */
std::vector<int> toRemove;
std::map<COutPoint, int> outputMap;
for (int i = 0; i < mempoolUnspent.size(); i++)
for (int j = 0; j < mempoolUnspent.size(); j++)
{
if (mempoolUnspent[i].first.spending)
if (mempoolUnspent[j].first.spending)
{
auto it = outputMap.find(COutPoint(mempoolUnspent[i].second.prevhash, mempoolUnspent[i].second.prevout));
auto it = outputMap.find(COutPoint(mempoolUnspent[j].second.prevhash, mempoolUnspent[j].second.prevout));
if (it != outputMap.end())
{
it->second < i ? toRemove.push_back(it->second) : toRemove.push_back(i);
it->second < i ? toRemove.push_back(i) : toRemove.push_back(it->second);
it->second < j ? toRemove.push_back(it->second) : toRemove.push_back(j);
it->second < j ? toRemove.push_back(j) : toRemove.push_back(it->second);
}
else
{
toRemove.push_back(i);
toRemove.push_back(j);
}
}
else
{
outputMap.insert(std::make_pair(COutPoint(mempoolUnspent[i].first.txhash, mempoolUnspent[i].first.index), i));
outputMap.insert(std::make_pair(COutPoint(mempoolUnspent[j].first.txhash, mempoolUnspent[j].first.index), j));
}
}
for (auto it = toRemove.rbegin(); it != toRemove.rend(); it++)
@ -3790,6 +3814,15 @@ bool CPBaaSNotarization::ConfirmOrRejectNotarizations(CWallet *pWallet,
LogPrintf("txid: %s:%d, nValue: %ld\n", oneSpend.txIn.prevout.hash.GetHex().c_str(), oneSpend.txIn.prevout.n, oneSpend.nValue);
}
}
for (int j = 0; j < evidenceVec.size(); j++)
{
auto &oneEvidenceVec = evidenceVec[j];
LogPrintf("evidence vector: index #%d\n", j);
for (auto &oneEvidence : oneEvidenceVec)
{
LogPrintf("%s\n", oneEvidence.ToUniValue().write(1,2).c_str());
}
}
}
CNotaryEvidence ne(ASSETCHAINS_CHAINID, cnd.vtx[idx].first, CNotaryEvidence::STATE_CONFIRMING);
@ -5281,6 +5314,7 @@ bool ValidateFinalizeNotarization(struct CCcontract_info *cp, Eval* eval, const
return true;
}
}
return eval->Error("Invalid spend of confirmed finalization to transaction with no confirmed output");
}
// get currency to determine system and notarization method
@ -5372,7 +5406,7 @@ bool ValidateFinalizeNotarization(struct CCcontract_info *cp, Eval* eval, const
// TODO: HARDENING - complete
// validate both rejection and confirmation
// in order to finalize confirmation and not just rejection, we need to spend the last
// confirmed transaction. that means that if this finalization asserts it is confirmed, we must find the
// confirmed transaction. that means that if this finalization asserts it is confirmed, we must prove it
if (newFinalization.IsConfirmed())
{
}

62
src/pbaas/pbaas.cpp

@ -1891,36 +1891,42 @@ bool PrecheckCurrencyDefinition(const CTransaction &spendingTx, int32_t outNum,
systemDef = ConnectedChains.GetCachedCurrency(newCurrency.systemID);
}
bool isNFTMappedCurrency = newCurrency.IsNFTToken() &&
systemDef.IsValid() &&
!(newCurrency.options &
newCurrency.OPTION_FRACTIONAL +
newCurrency.OPTION_GATEWAY +
newCurrency.OPTION_PBAAS +
newCurrency.OPTION_GATEWAY_CONVERTER) &&
newCurrency.IsToken();
if (newCurrency.nativeCurrencyID.TypeNoFlags() == newCurrency.nativeCurrencyID.DEST_ETHNFT &&
!(isNFTMappedCurrency &&
systemDef.proofProtocol == systemDef.PROOF_ETHNOTARIZATION &&
systemDef.IsGateway() &&
newCurrency.maxPreconvert.size() == 1 &&
newCurrency.maxPreconvert[0] == 0 &&
newCurrency.GetTotalPreallocation() == 0))
{
return state.Error("NFT mapped currency must have only 0 satoshi of supply and follow all definition rules");
}
else if (newCurrency.IsNFTToken() &&
!(isNFTMappedCurrency &&
newCurrency.systemID == ASSETCHAINS_CHAINID &&
bool isNFTMappedCurrency = false;
if (newCurrency.IsNFTToken())
{
isNFTMappedCurrency = newCurrency.IsNFTToken() &&
systemDef.IsValid() &&
!(newCurrency.options &
newCurrency.OPTION_FRACTIONAL +
newCurrency.OPTION_GATEWAY +
newCurrency.OPTION_PBAAS +
newCurrency.OPTION_GATEWAY_CONVERTER) &&
newCurrency.IsToken();
if (!isNFTMappedCurrency ||
(!(newCurrency.nativeCurrencyID.TypeNoFlags() == newCurrency.nativeCurrencyID.DEST_ETHNFT &&
systemDef.proofProtocol == systemDef.PROOF_ETHNOTARIZATION &&
systemDef.IsGateway() &&
newCurrency.maxPreconvert.size() == 1 &&
newCurrency.maxPreconvert[0] == 0 &&
newCurrency.GetTotalPreallocation() == 0) &&
!(newCurrency.systemID == ASSETCHAINS_CHAINID &&
((newCurrency.GetTotalPreallocation() == 0 &&
newCurrency.maxPreconvert.size() == 1 &&
newCurrency.maxPreconvert[0] == 1) ||
(newCurrency.GetTotalPreallocation() == 1 &&
(newCurrency.GetTotalPreallocation() == 1 &&
newCurrency.maxPreconvert.size() == 1 &&
newCurrency.maxPreconvert[0] == 0))))
{
return state.Error("Tokenized ID currency must have only 1 satoshi of supply as preallocation or convertible and follow all definition rules");
newCurrency.maxPreconvert[0] == 0)))))
{
if (newCurrency.nativeCurrencyID.TypeNoFlags() == newCurrency.nativeCurrencyID.DEST_ETHNFT)
{
return state.Error("Ethereum NFT mapped currency must have 0 satoshis of supply, maxpreconversions of [0], and follow all definition rules");
}
else
{
return state.Error("Tokenized ID control currency must have 1 satoshi of supply, and follow all definition rules");
}
}
}
// TODO: HARDENING - add hardening to ensure that no more than one satoshi at a time ever comes in from a bridge for an NFT mapped currency
@ -3339,7 +3345,9 @@ bool CConnectedChains::CheckVerusPBaaSAvailable()
if (!chainInfo.isNull())
{
params.push_back(EncodeDestination(CIdentityID(FirstNotaryChain().chainDefinition.GetID())));
chainDef = find_value(RPCCallRoot("getcurrency", params), "result");
chainDef = FirstNotaryChain().chainDefinition.launchSystemID == ASSETCHAINS_CHAINID ?
FirstNotaryChain().chainDefinition.ToUniValue() :
find_value(RPCCallRoot("getcurrency", params), "result");
if (!chainDef.isNull() && CheckVerusPBaaSAvailable(chainInfo, chainDef))
{

2
src/version.h

@ -35,6 +35,6 @@ static const int MEMPOOL_GD_VERSION = 60002;
static const int NO_BLOOM_VERSION = 170004;
#define KOMODO_VERSION "0.2.1"
#define VERUS_VERSION "0.9.4-2"
#define VERUS_VERSION "0.9.4-3"
#endif // BITCOIN_VERSION_H

Loading…
Cancel
Save