diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7967c75bd..a3ac6c228 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,7 @@ stages: ######################################################################################################################## variables: - VERSION: 0.9.4-1 + VERSION: 0.9.4-2 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 @@ -30,6 +30,7 @@ variables: ####START#### LINUX ####START#### ######################################################################################################################## build:linux: + tags: [ "verusd" ] image: asherd/verus-builders:verus-debian-10 variables: DOCKER_DRIVER: overlay2 @@ -58,12 +59,6 @@ build:linux: - tar -czvf ${VERUS_CLI_LINUX_X86_64} verus-cli - sha256sum ${VERUS_CLI_LINUX_X86_64} > ${VERUS_CLI_LINUX_X86_64}.sha256 - git status - after_script: - - curl -F file=@"${VERUS_CLI_LINUX_X86_64}" - -F channels="${CLI_POST_CHANNEL}" - -F initial_comment="${POST_MESSAGE}" - -H "${SLACK_BOT_AUTH}" - "https://slack.com/api/files.upload" artifacts: paths: - ${VERUS_CLI_LINUX_X86_64} @@ -72,6 +67,7 @@ build:linux: build:linux:arm64: + tags: [ "verusd" ] image: asherd/verus-builders:cross-arm variables: DOCKER_DRIVER: overlay2 @@ -100,13 +96,6 @@ build:linux:arm64: - chmod +x verus-cli/fetch-bootstrap - tar -czvf ${VERUS_CLI_ARM64_LINUX} verus-cli - sha256sum ${VERUS_CLI_ARM64_LINUX} > ${VERUS_CLI_ARM64_LINUX}.sha256 - - git status - after_script: - - curl -F file=@"${VERUS_CLI_ARM64_LINUX}" - -F channels="${CLI_POST_CHANNEL}" - -F initial_comment="${POST_MESSAGE}" - -H "${SLACK_BOT_AUTH}" - "https://slack.com/api/files.upload" artifacts: paths: - ${VERUS_CLI_ARM64_LINUX} @@ -118,6 +107,7 @@ build:linux:arm64: ####START#### WINDOWS ####START#### ######################################################################################################################## build:windows: + tags: [ "verusd" ] image: asherd/verus-builders:verus-windows variables: DOCKER_DRIVER: overlay2 @@ -139,11 +129,6 @@ build:windows: - if [ "${STRIP_BINARIES}" = "true" ]; then strip --strip-unneeded verus-cli/verusd.exe && strip --strip-unneeded verus-cli/verus.exe; fi - zip -r ${VERUS_CLI_WINDOWS} verus-cli - sha256sum ${VERUS_CLI_WINDOWS} > ${VERUS_CLI_WINDOWS}.sha256 - - curl -F file=@"${VERUS_CLI_WINDOWS}" - -F channels="${CLI_POST_CHANNEL}" - -F initial_comment="${POST_MESSAGE}" - -H "${SLACK_BOT_AUTH}" - "https://slack.com/api/files.upload" artifacts: paths: - ${VERUS_CLI_WINDOWS} @@ -155,10 +140,10 @@ build:windows: ####START#### MACOS ####START#### ######################################################################################################################## build:mac: + tags: [ "MacOS" ] variables: CONFIGURE_FLAGS: --with-gcc-arch=x86-64 stage: build - tags: ["Mojave"] cache: key: "${CI_JOB_NAME}${CI_COMMIT_REF_NAME}" paths: @@ -180,11 +165,6 @@ build:mac: - chmod +x verus-cli/verusd - tar -czvf ${VERUS_CLI_MACOS} verus-cli - shasum -a 256 ${VERUS_CLI_MACOS} > ${VERUS_CLI_MACOS}.sha256 - - curl -F file=@"${VERUS_CLI_MACOS}" - -F channels="${CLI_POST_CHANNEL}" - -F initial_comment="${POST_MESSAGE}" - -H "${SLACK_BOT_AUTH}" - "https://slack.com/api/files.upload" artifacts: paths: - ${VERUS_CLI_MACOS} @@ -197,174 +177,10 @@ build:mac: ####END#### Build Stage ####END#### ######################################################################################################################## ######################################################################################################################## -######################################################################################################################## -######################################################################################################################## -####START#### Test stage: Test functionality of komodo binaries. Produce code quality and SAST reports. ####START#### -######################################################################################################################## -######################################################################################################################## -######################################################################################################################## -####START#### Code Quality ####START#### -######################################################################################################################## -.code_quality: - image: docker:stable - variables: - DOCKER_DRIVER: overlay2 - allow_failure: true - services: - - docker:stable-dind - script: - - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') - - docker run - --env SOURCE_CODE="$PWD" - --volume "$PWD":/code - --volume /var/run/docker.sock:/var/run/docker.sock - "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code - artifacts: - paths: [gl-code-quality-report.json] -######################################################################################################################## -####END#### Code Quality ####END#### -######################################################################################################################## -######################################################################################################################## -####START#### Static Application Security Tests ####START#### -######################################################################################################################## -.sast: - image: docker:stable - variables: - DOCKER_DRIVER: overlay2 - allow_failure: true - services: - - docker:stable-dind - script: - - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') - - docker run - --env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}" - --volume "$PWD:/code" - --volume /var/run/docker.sock:/var/run/docker.sock - "registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code - artifacts: - paths: [gl-sast-report.json] -######################################################################################################################## -####END#### Static Application Security Tests ####END#### -######################################################################################################################## -######################################################################################################################## -####START#### Run Verus CLI on Ubuntu Xenial (16.04) ####START#### -######################################################################################################################## -.ubuntu:xenial: - image: ubuntu:xenial - variables: - DOCKER_DRIVER: overlay2 - stage: test - before_script: - - apt update && apt install -y wget libgomp1 python - - rm -rf /root/.komodo || true - - mv .komodo /root/ || true - script: - - tar -xzvf ${VERUS_CLI_LINUX_X86_64} - - export PATH=$PATH:$CI_PROJECT_DIR/verus-cli - - python qa/verus-cli-tests/verus-cli-tester.py - after_script: - - mv /root/.komodo ./ || true - cache: - key: ${CI_JOB_NAME} - paths: [.komodo] - artifacts: - paths: [log.txt] - expire_in: 1 week - dependencies: - - build:linux -######################################################################################################################## -####END#### Run Verus CLI on Ubuntu Xenial (16.04) ####END#### -######################################################################################################################## -######################################################################################################################## -####START#### Run Verus CLI on Ubuntu Bionic (18.04) ####START#### -######################################################################################################################## -.ubuntu:bionic: - image: ubuntu:bionic - variables: - DOCKER_DRIVER: overlay2 - stage: test - before_script: - - apt update && apt install -y wget libgomp1 python - - rm -rf /root/.komodo || true - - mv .komodo /root/ || true - script: - - tar -xzvf ${VERUS_CLI_LINUX_X86_64} - - export PATH=$PATH:$CI_PROJECT_DIR/verus-cli - - python qa/verus-cli-tests/verus-cli-tester.py - after_script: - - mv /root/.komodo ./ || true - cache: - key: ${CI_JOB_NAME} - paths: [.komodo] - artifacts: - paths: [log.txt] - expire_in: 1 week - dependencies: - - build:linux -######################################################################################################################## -####END#### Run Verus CLI on Ubuntu Bionic (18.04) ####END#### -######################################################################################################################## -######################################################################################################################## -####START#### Run Verus CLI on MacOS Sierra (10.12.6) ####START#### -######################################################################################################################## -.macos:sierra: - stage: test - tags: ["Sierra"] - script: - - tar -xzvf $VERUS_CLI_MACOS - - export PATH=$PATH:$CI_PROJECT_DIR/verus-cli - - python qa/verus-cli-tests/verus-cli-tester.py - artifacts: - paths: [log.txt] - expire_in: 1 week - dependencies: - - build:mac -######################################################################################################################## -####END#### Run Verus CLI on MacOS Sierra (10.12.6) ####END#### -######################################################################################################################## -######################################################################################################################## -####START#### Run Verus CLI on MacOS High Sierra (10.12.6) ####START#### -######################################################################################################################## -.macos:high-sierra: - stage: test - tags: ["High Sierra"] - script: - - tar -xzvf ${VERUS_CLI_MACOS} - - export PATH=$PATH:$CI_PROJECT_DIR/verus-cli - - python qa/verus-cli-tests/verus-cli-tester.py - artifacts: - paths: [log.txt] - expire_in: 1 week - dependencies: - - build:mac -######################################################################################################################## -####START#### Run Verus CLI on MacOS High Sierra (10.12.6) ####START#### -######################################################################################################################## -######################################################################################################################## -####START#### Run Verus CLI on Windows 10 ####START#### -######################################################################################################################## -.windows:10: - stage: test - tags: ["Windows 10"] - script: - - PowerShell Expand-Archive -Path %VERUS_CLI_WINDOWS% -DestinationPath %CI_PROJECT_DIR% - - set PATH=%PATH%;%CI_PROJECT_DIR%\verus-cli - - qa\verus-cli-tests\verus-cli-tester.py - artifacts: - paths: [log.txt] - expire_in: 1 week - dependencies: - - build:windows -######################################################################################################################## -####END#### Run Verus CLI on Windows 10 ####END#### -######################################################################################################################## -######################################################################################################################## -####END#### Test Stage ####END#### -######################################################################################################################## -######################################################################################################################## ####START#### Deploy ####START#### ######################################################################################################################## deploy: + tags: [ "verusd" ] stage: deploy image: google/cloud-sdk:alpine variables: diff --git a/README.md b/README.md index 419dfafed..ca768d224 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -## VerusCoin version 0.9.4-1 +## VerusCoin version 0.9.4-2 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. diff --git a/doc/man/verus-cli/linux/README.txt b/doc/man/verus-cli/linux/README.txt index 41a6c3b6b..08a190826 100644 --- a/doc/man/verus-cli/linux/README.txt +++ b/doc/man/verus-cli/linux/README.txt @@ -1,5 +1,5 @@ -VerusCoin Command Line Tools v0.9.4-1 +VerusCoin Command Line Tools v0.9.4-2 Contents: verusd - VerusCoin daemon diff --git a/doc/man/verus-cli/mac/README.txt b/doc/man/verus-cli/mac/README.txt index 807a7ff49..41663a85e 100644 --- a/doc/man/verus-cli/mac/README.txt +++ b/doc/man/verus-cli/mac/README.txt @@ -1,5 +1,5 @@ -VerusCoin Command Line Tools v0.9.4-1 +VerusCoin Command Line Tools v0.9.4-2 Contents: verusd - VerusCoin daemon. diff --git a/doc/man/verus-cli/windows/README.txt b/doc/man/verus-cli/windows/README.txt index f33e21968..ceffad66e 100644 --- a/doc/man/verus-cli/windows/README.txt +++ b/doc/man/verus-cli/windows/README.txt @@ -1,5 +1,5 @@ -VerusCoin Command Line Tools v0.9.4-1 +VerusCoin Command Line Tools v0.9.4-2 Contents: verusd.exe - VerusCoin daemon diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 84823c731..1a79ce276 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -91,7 +91,7 @@ public: CMainParams() { strNetworkID = "main"; - strCurrencyUnits = "KMD"; + strCurrencyUnits = "VRSC"; bip44CoinType = 133; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md (ZCASH, should be VRSC) consensus.fCoinbaseMustBeProtected = false; // true this is only true wuth Verus and enforced after block 12800 (enforcement ending at solution V3) consensus.nSubsidySlowStartInterval = 20000; diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 773c36575..e464956f1 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -93,15 +93,6 @@ void SelectBaseParams(CBaseChainParams::Network network) CBaseChainParams::Network NetworkIdFromCommandLine() { - bool fRegTest = GetBoolArg("-regtest", false); - bool fTestNet = GetBoolArg("-testnet", false); - - if (fTestNet && fRegTest) - return CBaseChainParams::MAX_NETWORK_TYPES; - if (fRegTest) - return CBaseChainParams::REGTEST; - if (fTestNet) - return CBaseChainParams::TESTNET; return CBaseChainParams::MAIN; } diff --git a/src/core_write.cpp b/src/core_write.cpp index 76b36a9e4..f052d02eb 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -839,8 +839,8 @@ UniValue CPBaaSNotarization::ToUniValue() const obj.push_back(Pair("currencystate", currencyState.ToUniValue())); obj.push_back(Pair("prevnotarizationtxid", prevNotarization.hash.GetHex())); obj.push_back(Pair("prevnotarizationout", (int64_t)prevNotarization.n)); - obj.push_back(Pair("hashprevnotarizationobject", hashPrevNotarization.GetHex())); obj.push_back(Pair("prevheight", (int64_t)prevHeight)); + obj.push_back(Pair("hashprevcrossnotarization", hashPrevCrossNotarization.GetHex())); // now get states and roots, of which there may be multiple UniValue curStateArr(UniValue::VARR); diff --git a/src/deprecation.h b/src/deprecation.h index 23e5b75ca..b262f876c 100644 --- a/src/deprecation.h +++ b/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 = 2183000; +static const int APPROX_RELEASE_HEIGHT = 2191000; static const int WEEKS_UNTIL_DEPRECATION = 20; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 60 * 24); diff --git a/src/init.cpp b/src/init.cpp index 9310dfeab..6a4c1eb8a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -346,16 +346,6 @@ std::string HelpMessage(HelpMessageMode mode) // When adding new options to the categories, please keep and ensure alphabetical ordering. // Do not translate _(...) -help-debug options, many technical terms, and only a very small audience, so is unnecessary stress to translators - // TODO: HARDENING - edit this help information before final mainnet release, remove irrelevant switches, include: - // -mineraddress - // -pubkey - // -defaultid - // -cheatcatcher - // -miningdistribution - // -miningdistributionpassthrough - // -chain= - // more... - string strUsage = HelpMessageGroup(_("Options:")); strUsage += HelpMessageOpt("-?", _("This help message")); strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS)); @@ -516,7 +506,16 @@ std::string HelpMessage(HelpMessageMode mode) "This is intended for regression testing tools and app development."); } // strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)")); - strUsage += HelpMessageOpt("-testnet", _("Use the test network")); + strUsage += HelpMessageOpt("-mineraddress=
", _("Mining rewards will go to this address")); + strUsage += HelpMessageOpt("-pubkey=", _("If set, mining and staking rewards will go to this address by default")); + strUsage += HelpMessageOpt("-defaultid=", _("VerusID used for default change out and staking reward recipient")); + strUsage += HelpMessageOpt("-defaultzaddr=", _("sapling address to receive fraud proof rewards and if used with \"-privatechange=1\", z-change address for the sendcurrency command")); + strUsage += HelpMessageOpt("-cheatcatcher=", _("same as \"-defaultzaddr\"")); + strUsage += HelpMessageOpt("-privatechange", _("directs all change from sendcurency or z_sendmany APIs to the defaultzaddr set, if it is a valid sapling address")); + strUsage += HelpMessageOpt("-miningdistribution={\"addressorid\":,...}", _("destination addresses and relative amounts used as ratios to divide total rewards + fees")); + strUsage += HelpMessageOpt("-miningdistributionpassthrough", _("uses the same miningdistribution values and addresses/IDs as Verus when merge mining")); + strUsage += HelpMessageOpt("-chain=pbaaschainname", _("loads either mainnet or resolves and loads a PBaaS chain if not vrsc or vrsctest")); + strUsage += HelpMessageOpt("-testnet", _("loads PBaaS network in testmode")); strUsage += HelpMessageGroup(_("Node relay options:")); strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), 1)); diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 4ba0c9f27..aca536fac 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1766,7 +1766,7 @@ void komodo_args(char *argv0) */ // either the testmode parameter or calling this chain VRSCTEST will put us into testmode - PBAAS_TESTMODE = GetBoolArg("-testmode", false); + PBAAS_TESTMODE = GetBoolArg("-testnet", false); // setting test mode also prevents the name of this chain from being set to VRSC @@ -1778,7 +1778,7 @@ void komodo_args(char *argv0) std::string lowerName = boost::to_lower_copy(name); - // TODO: HARDENING - right now, all PBaaS chains assume testmode. change before mainnet + // TODO: POST HARDENING - right now, all PBaaS chains assume testmode. change before mainnet if (lowerName != "vrsc") { PBAAS_TESTMODE = true; diff --git a/src/params.cpp b/src/params.cpp index dddc89fef..57e5360b1 100644 --- a/src/params.cpp +++ b/src/params.cpp @@ -92,15 +92,6 @@ static int xferinfo(void *p, void initalizeMapParamBootstrap() { mapParams.clear(); - ParamFile bootFile; - bootFile.name = "bootstrap"; - bootFile.URL = "https://bootstrap.verus.io/VRSC-bootstrap.tar.gz"; - bootFile.verified = false; - bootFile.path = GetDataDir() / "VRSC-bootstrap.tar.gz"; - bootFile.dlnow = 0; - bootFile.dltotal = 0; - mapParams[bootFile.URL] = bootFile; - ParamFile bootSigFile; bootSigFile.name = "bootstrap-signature"; bootSigFile.URL = "https://bootstrap.verus.io/VRSC-bootstrap.tar.gz.verusid"; @@ -109,6 +100,15 @@ void initalizeMapParamBootstrap() { bootSigFile.dlnow = 0; bootSigFile.dltotal = 0; mapParams[bootSigFile.URL] = bootSigFile; + + ParamFile bootFile; + bootFile.name = "bootstrap"; + bootFile.URL = "https://bootstrap.verus.io/VRSC-bootstrap.tar.gz"; + bootFile.verified = false; + bootFile.path = GetDataDir() / "VRSC-bootstrap.tar.gz"; + bootFile.dlnow = 0; + bootFile.dltotal = 0; + mapParams[bootFile.URL] = bootFile; } diff --git a/src/pbaas/crosschainrpc.h b/src/pbaas/crosschainrpc.h index c7e2d37ad..d165796bb 100644 --- a/src/pbaas/crosschainrpc.h +++ b/src/pbaas/crosschainrpc.h @@ -1474,7 +1474,7 @@ private: CKeccack256Writer *hw_keccack; }; nativeHashWriter state; - + public: CNativeHashWriter(CCurrencyDefinition::EProofProtocol proofProtocol=CCurrencyDefinition::EProofProtocol::PROOF_PBAASMMR, const unsigned char *personal=nullptr) diff --git a/src/pbaas/notarization.cpp b/src/pbaas/notarization.cpp index 31bea5194..3087df1ad 100644 --- a/src/pbaas/notarization.cpp +++ b/src/pbaas/notarization.cpp @@ -727,7 +727,7 @@ CPBaaSNotarization::CPBaaSNotarization(const UniValue &obj) notarizationHeight = (uint32_t)uni_get_int64(find_value(obj, "notarizationheight")); currencyState = CCoinbaseCurrencyState(find_value(obj, "currencystate")); prevNotarization = CUTXORef(uint256S(uni_get_str(find_value(obj, "prevnotarizationtxid"))), (uint32_t)uni_get_int(find_value(obj, "prevnotarizationout"))); - hashPrevNotarization = uint256S(uni_get_str(find_value(obj, "hashprevnotarizationobject"))); + hashPrevCrossNotarization = uint256S(uni_get_str(find_value(obj, "hashprevcrossnotarization"))); prevHeight = (uint32_t)uni_get_int64(find_value(obj, "prevheight")); auto curStateArr = find_value(obj, "currencystates"); @@ -962,7 +962,7 @@ bool CPBaaSNotarization::NextNotarizationInfo(const CCurrencyDefinition &sourceS uint160 externalSystemID = sourceSystem.SystemOrGatewayID() == ASSETCHAINS_CHAINID ? ((destSystemID == ASSETCHAINS_CHAINID) ? uint160() : destSystemID) : - ASSETCHAINS_CHAINID; + sourceSystem.GetID(); CCurrencyDefinition externalSystemDef; if (externalSystemID.IsNull() || externalSystemID == ASSETCHAINS_CHAINID) @@ -997,9 +997,9 @@ bool CPBaaSNotarization::NextNotarizationInfo(const CCurrencyDefinition &sourceS hashType = (CCurrencyDefinition::EProofProtocol)externalSystemDef.proofProtocol; } - CNativeHashWriter hwPrevNotarization(hashType); + CNativeHashWriter hwPrevNotarization; hwPrevNotarization << *this; - newNotarization.hashPrevNotarization = hwPrevNotarization.GetHash(); + newNotarization.hashPrevCrossNotarization = hwPrevNotarization.GetHash(); CNativeHashWriter hw(hashType); @@ -1318,13 +1318,16 @@ bool CPBaaSNotarization::NextNotarizationInfo(const CCurrencyDefinition &sourceS } newNotarization.currencyState.SetLaunchClear(false); + CCurrencyDefinition destSystem = newNotarization.IsRefunding() ? ConnectedChains.GetCachedCurrency(destCurrency.launchSystemID) : + ConnectedChains.GetCachedCurrency(destCurrency.SystemOrGatewayID()); + // calculate new state from processing all transfers // we are not refunding, and it is possible that we also have // normal conversions in addition to pre-conversions. add any conversions that may // be present into the new currency state CCoinbaseCurrencyState intermediateState = newNotarization.currencyState; - bool isValidExport = rtxd.AddReserveTransferImportOutputs(newNotarization.IsRefunding() ? externalSystemDef : sourceSystem, - newNotarization.IsRefunding() ? sourceSystem : externalSystemDef, + bool isValidExport = rtxd.AddReserveTransferImportOutputs(sourceSystem, + destSystem, destCurrency, intermediateState, exportTransfers, @@ -1349,8 +1352,8 @@ bool CPBaaSNotarization::NextNotarizationInfo(const CCurrencyDefinition &sourceS tempCurState.conversionPrice = newNotarization.currencyState.conversionPrice; tempCurState.viaConversionPrice = newNotarization.currencyState.viaConversionPrice; rtxd = CReserveTransactionDescriptor(); - isValidExport = rtxd.AddReserveTransferImportOutputs(newNotarization.IsRefunding() ? externalSystemDef : sourceSystem, - newNotarization.IsRefunding() ? sourceSystem : externalSystemDef, + isValidExport = rtxd.AddReserveTransferImportOutputs(sourceSystem, + destSystem, destCurrency, tempCurState, exportTransfers, @@ -2838,6 +2841,24 @@ bool CPBaaSNotarization::CreateEarnedNotarization(const CRPCChainData &externalS return state.Error(errorPrefix + "invalid or missing currency state data from notary"); } + params = UniValue(UniValue::VARR); + params.push_back(EncodeDestination(CIdentityID(ASSETCHAINS_CHAINID))); + try + { + result = find_value(RPCCallRoot("getnotarizationdata", params), "result"); + } catch (exception e) + { + result = NullUniValue; + } + CChainNotarizationData crosschainCND; + if (result.isNull() || + !(crosschainCND = CChainNotarizationData(result)).IsValid() || + (!externalSystem.chainDefinition.IsGateway() && !crosschainCND.IsConfirmed())) + { + LogPrint("notarization", "Unable to get notarization data from %s\n", EncodeDestination(CIdentityID(externalSystem.GetID())).c_str()); + return state.Error("invalid crosschain notarization data"); + } + // take the lock again, now that we're back from calling out LOCK2(cs_main, mempool.cs); @@ -2847,6 +2868,45 @@ bool CPBaaSNotarization::CreateEarnedNotarization(const CRPCChainData &externalS return state.Error("stale-block"); } + if (crosschainCND.vtx.size()) + { + int prevNotarizationIdx; + CPBaaSNotarization lastPBN; + for (prevNotarizationIdx = crosschainCND.vtx.size() - 1; prevNotarizationIdx >= 0; prevNotarizationIdx--) + { + lastPBN = crosschainCND.vtx[prevNotarizationIdx].second; + + // TODO: HARDENING check all currency states on this chain in last valid as well + std::map::iterator pIT = lastPBN.proofRoots.find(ASSETCHAINS_CHAINID); + if (pIT != lastPBN.proofRoots.end() && + (!priorNotarization.proofRoots.count(ASSETCHAINS_CHAINID) || + pIT->second.rootHeight <= priorNotarization.proofRoots.find(ASSETCHAINS_CHAINID)->second.rootHeight) && + CProofRoot::GetProofRoot(pIT->second.rootHeight) == pIT->second) + { + break; + } + else if (pIT == crosschainCND.vtx[prevNotarizationIdx].second.proofRoots.end() && + !prevNotarizationIdx && + (crosschainCND.vtx[prevNotarizationIdx].second.IsDefinitionNotarization() || crosschainCND.vtx[prevNotarizationIdx].second.IsLaunchCleared())) + { + // use the 0th element if no proof root and it is definition or start, since it has no proof root to be wrong + break; + } + } + if (prevNotarizationIdx >= 0 && + lastPBN.SetMirror(false) && + !lastPBN.IsMirror()) + { + CNativeHashWriter hw; + hw << lastPBN; + notarization.hashPrevCrossNotarization = hw.GetHash(); + } + else + { + notarization.hashPrevCrossNotarization.SetNull(); + } + } + notarization.currencyStates.clear(); for (int i = 0; i < currencyStatesUni.size(); i++) { @@ -2913,9 +2973,6 @@ bool CPBaaSNotarization::CreateEarnedNotarization(const CRPCChainData &externalS notarization.nodes = GetGoodNodes(CPBaaSNotarization::MAX_NODES); notarization.prevNotarization = cnd.vtx[notaryIdx].first; - CNativeHashWriter hw; - hw << cnd.vtx[notaryIdx].second; - notarization.hashPrevNotarization = hw.GetHash(); notarization.prevHeight = cnd.vtx[notaryIdx].second.notarizationHeight; CCcontract_info CC; @@ -4325,7 +4382,9 @@ std::vector CPBaaSNotarization::SubmitFinalizedNotarizations(const CRPC { CAddressIndexDbEntry tmpIndexEntry; CObjectFinalization finalizationObj; - if (crosschainCND.vtx[i].second.FindEarnedNotarization(finalizationObj, &tmpIndexEntry) && finalizationObj.IsConfirmed()) + if (crosschainCND.vtx[i].second.proofRoots.count(ASSETCHAINS_CHAINID) && + crosschainCND.vtx[i].second.FindEarnedNotarization(finalizationObj, &tmpIndexEntry) && + finalizationObj.IsConfirmed()) { earnedNotarizationIndexEntry = tmpIndexEntry; confirmingIdx = i; @@ -4343,7 +4402,8 @@ std::vector CPBaaSNotarization::SubmitFinalizedNotarizations(const CRPC uint256 blockHash; CTransaction confirmedNTx; CBlockIndex *pIndex; - if (!myGetTransaction(cnd.vtx[confirmingIdx].first.hash, confirmedNTx, blockHash) || + if (earnedNotarizationIndexEntry.first.txhash.IsNull() || + !myGetTransaction(earnedNotarizationIndexEntry.first.txhash, confirmedNTx, blockHash) || !mapBlockIndex.count(blockHash) || !chainActive.Contains(pIndex = mapBlockIndex[blockHash])) { @@ -4351,14 +4411,14 @@ std::vector CPBaaSNotarization::SubmitFinalizedNotarizations(const CRPC printf("Unable to get confirmed notarization transaction for %s\n", EncodeDestination(CIdentityID(systemID)).c_str()); return retVal; } - CPartialTransactionProof firstProof(notarizationTxes[confirmingIdx].first, + CPartialTransactionProof firstProof(confirmedNTx, std::vector(), - std::vector({(int)cnd.vtx[confirmingIdx].first.n}), + std::vector({(int)earnedNotarizationIndexEntry.first.index}), pIndex, - cnd.vtx[cnd.lastConfirmed].second.proofRoots[ASSETCHAINS_CHAINID].rootHeight); - notarizationTxInfo = std::make_pair(CInputDescriptor(notarizationTxes[confirmingIdx].first.vout[cnd.vtx[confirmingIdx].first.n].scriptPubKey, - notarizationTxes[confirmingIdx].first.vout[cnd.vtx[confirmingIdx].first.n].nValue, - CTxIn(cnd.vtx[confirmingIdx].first)), + crosschainCND.vtx[confirmingIdx].second.proofRoots[ASSETCHAINS_CHAINID].rootHeight); + notarizationTxInfo = std::make_pair(CInputDescriptor(confirmedNTx.vout[earnedNotarizationIndexEntry.first.index].scriptPubKey, + confirmedNTx.vout[earnedNotarizationIndexEntry.first.index].nValue, + CTxIn(earnedNotarizationIndexEntry.first.txhash, earnedNotarizationIndexEntry.first.index)), firstProof); } } @@ -4590,7 +4650,8 @@ std::vector CPBaaSNotarization::SubmitFinalizedNotarizations(const CRPC */ bool ValidateAcceptedNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled) { - // TODO: this validates the spending transaction + // TODO: HARDENING + // the spending transaction must be a notarization in the same thread of notarizations // check the following things: // 1. It represents a valid PoS or merge mined block on the other chain, and contains the header in the opret // 2. The MMR and proof provided for the currently asserted block can prove the provided header. The provided @@ -5117,6 +5178,7 @@ bool IsAcceptedNotarizationInput(const CScript &scriptSig) bool ValidateEarnedNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled) { // TODO: HARDENING ensure that earned notarization UTXOs are spent appropriately + // the spending transaction must be a finalization that either confirms or invalidates this notarization return true; } diff --git a/src/pbaas/pbaas.cpp b/src/pbaas/pbaas.cpp index a7404575d..613ff88c9 100644 --- a/src/pbaas/pbaas.cpp +++ b/src/pbaas/pbaas.cpp @@ -584,8 +584,8 @@ bool PrecheckCrossChainImport(const CTransaction &tx, int32_t outNum, CValidatio return state.Error(strprintf("%s: Invalid currency import", __func__)); } - // TODO: HARDENING - imported currencies do need to conform to type constraints in order - // to benefit from reduced import fees + // imported currencies do need to conform to type constraints in order + // to benefit from reduced import fees. this happens on the precheck for currency definition if ((oneTransfer.HasNextLeg() && oneTransfer.destination.gatewayID != ASSETCHAINS_CHAINID ? nextLegFeeEquiv : @@ -3428,33 +3428,37 @@ bool CConnectedChains::ConfigureEthBridge(bool callToCheck) map> settingsmulti; // create config file for our notary chain if one does not exist already - if (ReadConfigFile("veth", settings, settingsmulti)) + if (ReadConfigFile("veth", settings, settingsmulti) && + settingsmulti.count("-rpchost") && + settingsmulti.count("-rpcuser") && + settingsmulti.count("-rpcport") && + settingsmulti.count("-rpcpassword")) { // the Ethereum bridge, "VETH", serves as the root currency to VRSC and for Rinkeby to VRSCTEST vethNotaryChain.rpcUserPass = PBAAS_USERPASS = settingsmulti.find("-rpcuser")->second[0] + ":" + settingsmulti.find("-rpcpassword")->second[0]; vethNotaryChain.rpcPort = PBAAS_PORT = atoi(settingsmulti.find("-rpcport")->second[0]); PBAAS_HOST = settingsmulti.find("-rpchost")->second[0]; - if (!PBAAS_HOST.size()) - { - PBAAS_HOST = "127.0.0.1"; - } - vethNotaryChain.rpcHost = PBAAS_HOST; - CNotarySystemInfo notarySystem; - CChainNotarizationData cnd; - if (!GetNotarizationData(gatewayID, cnd)) - { - LogPrintf("%s: Failed to get notarization data for notary chain %s\n", __func__, vethNotaryChain.chainDefinition.name.c_str()); - return false; - } - - notarySystems.insert(std::make_pair(gatewayID, - CNotarySystemInfo(cnd.IsConfirmed() ? cnd.vtx[cnd.lastConfirmed].second.notarizationHeight : 0, - vethNotaryChain, - cnd.vtx.size() ? cnd.vtx[cnd.forks[cnd.bestChain].back()].second : CPBaaSNotarization(), - CNotarySystemInfo::TYPE_ETH, - CNotarySystemInfo::VERSION_CURRENT))); - return IsNotaryAvailable(callToCheck); } + if (!PBAAS_HOST.size()) + { + PBAAS_HOST = "127.0.0.1"; + } + vethNotaryChain.rpcHost = PBAAS_HOST; + CNotarySystemInfo notarySystem; + CChainNotarizationData cnd; + if (!GetNotarizationData(gatewayID, cnd)) + { + LogPrintf("%s: Failed to get notarization data for notary chain %s\n", __func__, vethNotaryChain.chainDefinition.name.c_str()); + return false; + } + + notarySystems.insert(std::make_pair(gatewayID, + CNotarySystemInfo(cnd.IsConfirmed() ? cnd.vtx[cnd.lastConfirmed].second.notarizationHeight : 0, + vethNotaryChain, + cnd.vtx.size() ? cnd.vtx[cnd.forks[cnd.bestChain].back()].second : CPBaaSNotarization(), + CNotarySystemInfo::TYPE_ETH, + CNotarySystemInfo::VERSION_CURRENT))); + return IsNotaryAvailable(callToCheck); } return false; } @@ -4451,6 +4455,7 @@ bool CConnectedChains::CreateLatestImports(const CCurrencyDefinition &sourceSyst else if (useProofs) { // make sure we have the latest, confirmed proof roots to prove this import + lastNotarization.proposer = proofNotarization.proposer; lastNotarization.proofRoots[sourceSystemID] = proofNotarization.proofRoots[sourceSystemID]; if (lastNotarization.proofRoots.count(ASSETCHAINS_CHAINID)) { @@ -4589,20 +4594,19 @@ bool CConnectedChains::CreateLatestImports(const CCurrencyDefinition &sourceSyst newLocalDepositsRequired.valueMap[destCurID] -= newPrimaryCurrency; } - /*printf("%s: newNotarization:\n%s\n", __func__, newNotarization.ToUniValue().write(1,2).c_str()); - printf("%s: ccx.totalAmounts: %s\ngatewayDepositsUsed: %s\nimportedCurrency: %s\nspentCurrencyOut: %s\n", + LogPrint("crosschainimports", "%s: newNotarization:\n%s\n", __func__, newNotarization.ToUniValue().write(1,2).c_str()); + LogPrint("crosschainimports", "%s: ccx.totalAmounts: %s\ngatewayDepositsUsed: %s\nimportedCurrency: %s\nspentCurrencyOut: %s\n", __func__, ccx.totalAmounts.ToUniValue().write(1,2).c_str(), gatewayDepositsUsed.ToUniValue().write(1,2).c_str(), importedCurrency.ToUniValue().write(1,2).c_str(), spentCurrencyOut.ToUniValue().write(1,2).c_str()); - printf("%s: incomingCurrency: %s\ncurrencyChange: %s\nnewLocalDepositsRequired: %s\n", + LogPrint("crosschainimports", "%s: incomingCurrency: %s\ncurrencyChange: %s\nnewLocalDepositsRequired: %s\n", __func__, incomingCurrency.ToUniValue().write(1,2).c_str(), newLocalReserveDeposits.ToUniValue().write(1,2).c_str(), newLocalDepositsRequired.ToUniValue().write(1,2).c_str()); - //*/ // create the import CCrossChainImport cci = CCrossChainImport(sourceSystemID, @@ -4825,9 +4829,8 @@ bool CConnectedChains::CreateLatestImports(const CCurrencyDefinition &sourceSyst gatewayChange = (totalDepositsInput - gatewayDepositsUsed).CanonicalMap(); - /*printf("%s: gatewayDepositsUsed: %s\n", __func__, gatewayDepositsUsed.ToUniValue().write(1,2).c_str()); - printf("%s: gatewayChange: %s\n", __func__, gatewayChange.ToUniValue().write(1,2).c_str()); - //*/ + LogPrint("crosschainimports", "%s: gatewayDepositsUsed: %s\n", __func__, gatewayDepositsUsed.ToUniValue().write(1,2).c_str()); + LogPrint("crosschainimports", "%s: gatewayChange: %s\n", __func__, gatewayChange.ToUniValue().write(1,2).c_str()); // we should always be able to fulfill // gateway despoit requirements, or this is an error @@ -4867,15 +4870,14 @@ bool CConnectedChains::CreateLatestImports(const CCurrencyDefinition &sourceSyst } } - /* printf("%s: newNotarization.currencyState: %s\n", __func__, newNotarization.currencyState.ToUniValue().write(1,2).c_str()); - printf("%s: cci: %s\n", __func__, cci.ToUniValue().write(1,2).c_str()); - printf("%s: spentcurrencyout: %s\n", __func__, spentCurrencyOut.ToUniValue().write(1,2).c_str()); - printf("%s: newcurrencyin: %s\n", __func__, incomingCurrency.ToUniValue().write(1,2).c_str()); - printf("%s: importedCurrency: %s\n", __func__, importedCurrency.ToUniValue().write(1,2).c_str()); - printf("%s: localdepositrequirements: %s\n", __func__, newLocalDepositsRequired.ToUniValue().write(1,2).c_str()); - printf("%s: checkImportedCurrency: %s\n", __func__, checkImportedCurrency.ToUniValue().write(1,2).c_str()); - printf("%s: checkRequiredDeposits: %s\n", __func__, checkRequiredDeposits.ToUniValue().write(1,2).c_str()); - //*/ + LogPrint("crosschainimports", "%s: newNotarization.currencyState: %s\n", __func__, newNotarization.currencyState.ToUniValue().write(1,2).c_str()); + LogPrint("crosschainimports", "%s: cci: %s\n", __func__, cci.ToUniValue().write(1,2).c_str()); + LogPrint("crosschainimports", "%s: spentcurrencyout: %s\n", __func__, spentCurrencyOut.ToUniValue().write(1,2).c_str()); + LogPrint("crosschainimports", "%s: newcurrencyin: %s\n", __func__, incomingCurrency.ToUniValue().write(1,2).c_str()); + LogPrint("crosschainimports", "%s: importedCurrency: %s\n", __func__, importedCurrency.ToUniValue().write(1,2).c_str()); + LogPrint("crosschainimports", "%s: localdepositrequirements: %s\n", __func__, newLocalDepositsRequired.ToUniValue().write(1,2).c_str()); + LogPrint("crosschainimports", "%s: checkImportedCurrency: %s\n", __func__, checkImportedCurrency.ToUniValue().write(1,2).c_str()); + LogPrint("crosschainimports", "%s: checkRequiredDeposits: %s\n", __func__, checkRequiredDeposits.ToUniValue().write(1,2).c_str()); // add local reserve deposit inputs and determine change if (newLocalDepositsRequired.valueMap.size() || @@ -4901,7 +4903,7 @@ bool CConnectedChains::CreateLatestImports(const CCurrencyDefinition &sourceSyst newLocalReserveDeposits = ((totalDepositsInput + incomingCurrency) - spentCurrencyOut).CanonicalMap(); - /* printf("%s: totalDepositsInput: %s\nincomingPlusDepositsMinusSpent: %s\n", + LogPrint("crosschainimports", "%s: totalDepositsInput: %s\nincomingPlusDepositsMinusSpent: %s\n", __func__, totalDepositsInput.ToUniValue().write(1,2).c_str(), newLocalReserveDeposits.ToUniValue().write(1,2).c_str()); //*/ @@ -4974,12 +4976,12 @@ bool CConnectedChains::CreateLatestImports(const CCurrencyDefinition &sourceSyst // ins and outs are correct. now calculate the fee correctly here and set the transaction builder accordingly // to prevent an automatic change output. we could just let it go and have a setting to stop creation of a change output, // but this is a nice doublecheck requirement - /*printf("%s: reserveInMap:\n%s\nspentCurrencyOut:\n%s\nccx.totalAmounts:\n%s\nccx.totalFees:\n%s\n", + LogPrint("crosschainimports", "%s: reserveInMap:\n%s\nspentCurrencyOut:\n%s\nccx.totalAmounts:\n%s\nccx.totalFees:\n%s\n", __func__, reserveInMap.ToUniValue().write(1,2).c_str(), spentCurrencyOut.ToUniValue().write(1,2).c_str(), ccx.totalAmounts.ToUniValue().write(1,2).c_str(), - ccx.totalFees.ToUniValue().write(1,2).c_str()); //*/ + ccx.totalFees.ToUniValue().write(1,2).c_str()); // pay the fee out to the miner CReserveTransactionDescriptor rtxd(tb.mtx, view, nHeight + 1); @@ -4990,7 +4992,7 @@ bool CConnectedChains::CreateLatestImports(const CCurrencyDefinition &sourceSyst tb.SetReserveFee(reserveFees); } - if (LogAcceptCategory("imports")) + if (LogAcceptCategory("crosschainimports")) { UniValue jsonTx(UniValue::VOBJ); uint256 hashBlk; diff --git a/src/pbaas/pbaas.h b/src/pbaas/pbaas.h index 1bb2a92f6..978d2ac35 100644 --- a/src/pbaas/pbaas.h +++ b/src/pbaas/pbaas.h @@ -256,7 +256,8 @@ public: CCoinbaseCurrencyState currencyState; // state of the currency being notarized as of this notarization CUTXORef prevNotarization; // reference of the prior notarization on this system with which we agree - uint256 hashPrevNotarization; // hash of the prior notarization on this system with which we agree, even one not accepted yet + uint256 hashPrevCrossNotarization; // (this is not the same notarization as the prev notarization or prev height) + // it is the hash of the prior notarization on the other chain with which we agree, even one not yet confirmed uint32_t prevHeight; // height of previous notarization we agree with std::map currencyStates; // currency state of other currencies to be co-notarized for gateways @@ -313,7 +314,7 @@ public: READWRITE(currencyState); READWRITE(notarizationHeight); READWRITE(prevNotarization); - READWRITE(hashPrevNotarization); + READWRITE(hashPrevCrossNotarization); READWRITE(prevHeight); std::vector> vecCurrencyStates; diff --git a/src/pbaas/reserves.cpp b/src/pbaas/reserves.cpp index b6c2f7108..a8c3bf883 100644 --- a/src/pbaas/reserves.cpp +++ b/src/pbaas/reserves.cpp @@ -426,141 +426,168 @@ bool CCrossChainImport::GetImportInfo(const CTransaction &importTx, } // TODO: HARDENING - review to ensure that if this is skipped an error is thrown when appropriate - if (!isPBaaSDefinitionOrLaunch && - (pBaseImport->importCurrencyID == ASSETCHAINS_CHAINID || - (!pBaseImport->importCurrencyID.IsNull() && pBaseImport->importCurrencyID == ConnectedChains.ThisChain().GatewayConverterID()))) + // for example, if we are coming in from ETH to the Verus / ETH converter + bool passedCheck = isPBaaSDefinitionOrLaunch; + if (!passedCheck) { - // next output should be export in evidence output followed by supplemental reserve transfers for the export - evidenceOutStart = importNotarizationOut + 1; - int afterEvidence; - CNotaryEvidence evidence(importTx, evidenceOutStart, afterEvidence, CNotaryEvidence::TYPE_IMPORT_PROOF); - - if (!evidence.IsValid()) + passedCheck = pBaseImport->importCurrencyID == ASSETCHAINS_CHAINID || + (!pBaseImport->importCurrencyID.IsNull() && pBaseImport->importCurrencyID == ConnectedChains.ThisChain().GatewayConverterID()); + if (!passedCheck && !pBaseImport->importCurrencyID.IsNull()) { - // TODO: remove the line assigning evidence just below, as it is only for debugging - evidence = CNotaryEvidence(importTx, evidenceOutStart, afterEvidence); - - return state.Error(strprintf("%s: cannot retrieve export evidence for import", __func__)); + for (auto &oneCur : ConnectedChains.notarySystems) + { + if (oneCur.second.notaryChain.chainDefinition.IsGateway() && + pBaseImport->importCurrencyID == oneCur.second.notaryChain.chainDefinition.GatewayConverterID()) + { + passedCheck = true; + break; + } + } } + if (passedCheck) + { + // next output should be export in evidence output followed by supplemental reserve transfers for the export + evidenceOutStart = importNotarizationOut + 1; + int afterEvidence; + CNotaryEvidence evidence(importTx, evidenceOutStart, afterEvidence, CNotaryEvidence::TYPE_IMPORT_PROOF); + + if (!evidence.IsValid()) + { + // TODO: remove the line assigning evidence just below, as it is only for debugging + evidence = CNotaryEvidence(importTx, evidenceOutStart, afterEvidence); - std::set validEvidenceTypes; - validEvidenceTypes.insert(CHAINOBJ_TRANSACTION_PROOF); - CNotaryEvidence transactionProof(sysCCITemp.sourceSystemID, evidence.output, evidence.state, evidence.GetSelectEvidence(validEvidenceTypes), CNotaryEvidence::TYPE_IMPORT_PROOF); + return state.Error(strprintf("%s: cannot retrieve export evidence for import", __func__)); + } - /* - // reconstruct evidence if necessary - if (evidence.IsPartialTxProof() && - evidence.evidence.size()) + std::set validEvidenceTypes; + validEvidenceTypes.insert(CHAINOBJ_TRANSACTION_PROOF); + CNotaryEvidence transactionProof(sysCCITemp.sourceSystemID, evidence.output, evidence.state, evidence.GetSelectEvidence(validEvidenceTypes), CNotaryEvidence::TYPE_IMPORT_PROOF); - // reconstruct multipart evidence if necessary - if (evidence.IsMultipartProof()) - { - COptCCParams eP; - CNotaryEvidence supplementalEvidence; - while (importTx.vout.size() > (evidenceOutStart + 1) && - importTx.vout[evidenceOutStart + 1].scriptPubKey.IsPayToCryptoCondition(eP) && - eP.IsValid() && - eP.evalCode == EVAL_NOTARY_EVIDENCE && - eP.vData.size() && - (supplementalEvidence = CNotaryEvidence(eP.vData[0])).IsValid() && - supplementalEvidence.IsPartialTxProof() && - supplementalEvidence.evidence.size() == 1) + /* + // reconstruct evidence if necessary + if (evidence.IsPartialTxProof() && + evidence.evidence.size()) + + // reconstruct multipart evidence if necessary + if (evidence.IsMultipartProof()) { - evidenceOutStart++; - evidence.evidence.push_back(supplementalEvidence.evidence[0]); + COptCCParams eP; + CNotaryEvidence supplementalEvidence; + while (importTx.vout.size() > (evidenceOutStart + 1) && + importTx.vout[evidenceOutStart + 1].scriptPubKey.IsPayToCryptoCondition(eP) && + eP.IsValid() && + eP.evalCode == EVAL_NOTARY_EVIDENCE && + eP.vData.size() && + (supplementalEvidence = CNotaryEvidence(eP.vData[0])).IsValid() && + supplementalEvidence.IsPartialTxProof() && + supplementalEvidence.evidence.size() == 1) + { + evidenceOutStart++; + evidence.evidence.push_back(supplementalEvidence.evidence[0]); + } + if (!eP.IsValid()) + { + return state.Error(strprintf("%s: cannot reconstruct export evidence for import", __func__)); + } + evidence.evidence = std::vector({CPartialTransactionProof(evidence.evidence)}); } - if (!eP.IsValid()) + */ + + CTransaction exportTx; + p = COptCCParams(); + if (!(transactionProof.evidence.chainObjects.size() && + !((CChainObject *)transactionProof.evidence.chainObjects[0])->object.GetPartialTransaction(exportTx).IsNull() && + ((CChainObject *)transactionProof.evidence.chainObjects[0])->object.TransactionHash() == pBaseImport->exportTxId && + exportTx.vout.size() > pBaseImport->exportTxOutNum && + exportTx.vout[pBaseImport->exportTxOutNum].scriptPubKey.IsPayToCryptoCondition(p) && + p.IsValid() && + p.evalCode == EVAL_CROSSCHAIN_EXPORT && + p.vData.size() && + (ccx = CCrossChainExport(p.vData[0])).IsValid())) { - return state.Error(strprintf("%s: cannot reconstruct export evidence for import", __func__)); + return state.Error(strprintf("%s: invalid export evidence for import", __func__)); } - evidence.evidence = std::vector({CPartialTransactionProof(evidence.evidence)}); - } - */ - - CTransaction exportTx; - p = COptCCParams(); - if (!(transactionProof.evidence.chainObjects.size() && - !((CChainObject *)transactionProof.evidence.chainObjects[0])->object.GetPartialTransaction(exportTx).IsNull() && - ((CChainObject *)transactionProof.evidence.chainObjects[0])->object.TransactionHash() == pBaseImport->exportTxId && - exportTx.vout.size() > pBaseImport->exportTxOutNum && - exportTx.vout[pBaseImport->exportTxOutNum].scriptPubKey.IsPayToCryptoCondition(p) && - p.IsValid() && - p.evalCode == EVAL_CROSSCHAIN_EXPORT && - p.vData.size() && - (ccx = CCrossChainExport(p.vData[0])).IsValid())) - { - return state.Error(strprintf("%s: invalid export evidence for import", __func__)); - } - uint160 externalSystemID = ccx.sourceSystemID == ASSETCHAINS_CHAINID ? - ((ccx.destSystemID == ASSETCHAINS_CHAINID) ? uint160() : ccx.destSystemID) : - ccx.sourceSystemID; + uint160 externalSystemID = ccx.sourceSystemID == ASSETCHAINS_CHAINID ? + ((ccx.destSystemID == ASSETCHAINS_CHAINID) ? uint160() : ccx.destSystemID) : + ccx.sourceSystemID; - std::map::iterator proofIt; - if (!externalSystemID.IsNull() && - (proofIt = importNotarization.proofRoots.find(externalSystemID)) != importNotarization.proofRoots.end()) - { - switch (proofIt->second.type) + std::map::iterator proofIt; + if (!externalSystemID.IsNull() && + (proofIt = importNotarization.proofRoots.find(externalSystemID)) != importNotarization.proofRoots.end()) { - case CProofRoot::TYPE_ETHEREUM: + switch (proofIt->second.type) { - hashType = CCurrencyDefinition::EProofProtocol::PROOF_ETHNOTARIZATION; - break; + case CProofRoot::TYPE_ETHEREUM: + { + hashType = CCurrencyDefinition::EProofProtocol::PROOF_ETHNOTARIZATION; + break; + } } } - } - else if (!externalSystemID.IsNull()) - { - return state.Error(strprintf("%s: no proof root to validate export for external system %s", __func__, EncodeDestination(CIdentityID(externalSystemID)).c_str())); - } + else if (!externalSystemID.IsNull()) + { + return state.Error(strprintf("%s: no proof root to validate export for external system %s", __func__, EncodeDestination(CIdentityID(externalSystemID)).c_str())); + } - int32_t nextOutput; - CPBaaSNotarization xNotarization; - int primaryOutNumOut; - if (!ccx.GetExportInfo(importTx, evidenceOutStart, primaryOutNumOut, nextOutput, xNotarization, reserveTransfers, hashType)) - { - //UniValue jsonTx(UniValue::VOBJ); - //TxToUniv(importTx, uint256(), jsonTx); - //printf("%s: importTx:\n%s\n", __func__, jsonTx.write(1,2).c_str()); - return state.Error(strprintf("%s: invalid export evidence for import 1",__func__)); - } + int32_t nextOutput; + CPBaaSNotarization xNotarization; + int primaryOutNumOut; + if (!ccx.GetExportInfo(importTx, evidenceOutStart, primaryOutNumOut, nextOutput, xNotarization, reserveTransfers, hashType)) + { + //UniValue jsonTx(UniValue::VOBJ); + //TxToUniv(importTx, uint256(), jsonTx); + //printf("%s: importTx:\n%s\n", __func__, jsonTx.write(1,2).c_str()); + return state.Error(strprintf("%s: invalid export evidence for import 1",__func__)); + } - // evidence out end points to the last evidence out, not beyond - evidenceOutEnd = nextOutput - 1; + // evidence out end points to the last evidence out, not beyond + evidenceOutEnd = nextOutput - 1; + } + } + if (!passedCheck) + { + return state.Error(strprintf("%s: unable to verify cross-chain export as valid",__func__)); } } // if we may have an arbitrage reserve transfer, look for it - if (importNotarization.IsValid() && - importNotarization.IsLaunchComplete() && - !importNotarization.IsRefunding() && - importNotarization.currencyState.IsValid() && - importNotarization.currencyState.IsFractional() && - ccx.IsValid() && - hashReserveTransfers != ccx.hashReserveTransfers) - { - // if we don't have an arbitrage reserve transfer, this is an error that the hashes don't match - // if we do, they cannot match, so get it - CReserveTransfer arbitrageTransfer = GetArbitrageTransfer(importTx, numImportOut, state, nHeight); - if (!arbitrageTransfer.IsValid()) - { - return state.Error(strprintf("%s: export and import hash mismatch without valid arbitrage transfer",__func__)); - } - reserveTransfers.push_back(arbitrageTransfer); - CNativeHashWriter nhw1(hashType); - CNativeHashWriter nhw2(hashType); - for (int i = 0; i < reserveTransfers.size(); i++) - { - nhw1 << reserveTransfers[i]; - // if this is not the last, add it into the 2nd hash, which should then match the export - if (i + 1 < reserveTransfers.size()) + if (hashReserveTransfers != ccx.hashReserveTransfers) + { + if (importNotarization.IsValid() && + importNotarization.IsLaunchComplete() && + !importNotarization.IsRefunding() && + importNotarization.currencyState.IsValid() && + importNotarization.currencyState.IsFractional() && + ccx.IsValid()) + { + // if we don't have an arbitrage reserve transfer, this is an error that the hashes don't match + // if we do, they cannot match, so get it + CReserveTransfer arbitrageTransfer = GetArbitrageTransfer(importTx, numImportOut, state, nHeight); + if (!arbitrageTransfer.IsValid()) { - nhw2 << reserveTransfers[i]; + return state.Error(strprintf("%s: export and import hash mismatch without valid arbitrage transfer",__func__)); + } + reserveTransfers.push_back(arbitrageTransfer); + CNativeHashWriter nhw1(hashType); + CNativeHashWriter nhw2(hashType); + for (int i = 0; i < reserveTransfers.size(); i++) + { + nhw1 << reserveTransfers[i]; + // if this is not the last, add it into the 2nd hash, which should then match the export + if (i + 1 < reserveTransfers.size()) + { + nhw2 << reserveTransfers[i]; + } + } + if (hashReserveTransfers != nhw1.GetHash() || ccx.hashReserveTransfers != nhw2.GetHash()) + { + return state.Error(strprintf("%s: import hash of transfers does not match actual transfers with arbitrage",__func__)); } } - if (hashReserveTransfers != nhw1.GetHash() || ccx.hashReserveTransfers != nhw2.GetHash()) + else { - return state.Error(strprintf("%s: import hash of transfers does not match actual transfers with arbitrage",__func__)); + return state.Error(strprintf("%s: import hash of transfers does not match export transfers",__func__)); } } @@ -2502,6 +2529,9 @@ CReserveTransactionDescriptor::CReserveTransactionDescriptor(const CTransaction checkState.SetLaunchCompleteMarker(false); } + // TODO: HARDENING - ensure that we match notarization state to account for burns and + // transactions that affect state without outputs + if (!rtxd.AddReserveTransferImportOutputs(sourceSystemDef, ConnectedChains.thisChain, importCurrencyDef, diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index f868b221f..d3525d523 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -2075,7 +2075,7 @@ UniValue getaddressbalance(const UniValue& params, bool fHelp) { UniValue currencyBal(UniValue::VOBJ); UniValue currencyNames(UniValue::VOBJ); - for (auto &oneBalance : reserveBalance.valueMap) + for (auto &oneBalance : reserveReceived.valueMap) { std::string name = EncodeDestination(CIdentityID(oneBalance.first)); currencyBal.push_back(make_pair(name, ValueFromAmount(oneBalance.second))); diff --git a/src/rpc/pbaasrpc.cpp b/src/rpc/pbaasrpc.cpp index 43e6d2d72..79fb82595 100644 --- a/src/rpc/pbaasrpc.cpp +++ b/src/rpc/pbaasrpc.cpp @@ -8252,6 +8252,10 @@ extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& CCurrencyDefinition ValidateNewUnivalueCurrencyDefinition(const UniValue &uniObj, uint32_t height, const uint160 systemID, std::map &requiredDefinitions, bool checkMempool) { CCurrencyDefinition newCurrency(uniObj); + if (find_value(uniObj, "launchsystemid").isNull() && newCurrency.GetID() != ASSETCHAINS_CHAINID && newCurrency.parent != ASSETCHAINS_CHAINID) + { + newCurrency.launchSystemID = systemID; + } if (!newCurrency.IsValid()) { diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 7d964d136..85b644e06 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -178,16 +178,30 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& uint256 hash; CTransaction txFrom; if (GetTransaction(txin.prevout.hash,txFrom,hash,false)) { - if (LogAcceptCategory("signaturehash")) + COptCCParams p; + BlockMap::iterator blockIdxIt = mapBlockIndex.find(hash); + if (!hash.IsNull() && + blockIdxIt != mapBlockIndex.end() && + LogAcceptCategory("signaturehash") && + chainActive.Contains(blockIdxIt->second) && + txFrom.vout[txin.prevout.n].scriptPubKey.IsPayToCryptoCondition(p) && + p.IsValid()) { - // TODO: HARDENING - it would be good to add the signature hash for every input, but we need - // to reliably retrieve the hashtype (ie. SIGHASH_ALL, SIGHASH_SINGLE, etc.) from all transaction input types - // for now, this is temporary for debugging + // TODO: POST HARDENING - it would be good to add the signature hash for every input and improve + // description of signing and eval conditions, decoding the COptCCParams + + // get signature hash and verify signature + auto consensusBranchID = CurrentEpochBranchId(blockIdxIt->second->GetHeight(), Params().GetConsensus()); + CSmartTransactionSignatures smartSigs; + bool signedByDefaultKey = false; + std::vector ffVec = GetFulfillmentVector(tx.vin[i].scriptSig); + smartSigs = CSmartTransactionSignatures(std::vector(ffVec.begin(), ffVec.end())); + UniValue signatureHashInfo(UniValue::VOBJ); SignatureHash(txFrom.vout[txin.prevout.n].scriptPubKey, tx, i, - SIGHASH_ALL, + smartSigs.sigHashType, txFrom.vout[txin.prevout.n].nValue, CurrentEpochBranchId(nHeight, Params().GetConsensus()), nullptr, diff --git a/src/script/script.cpp b/src/script/script.cpp index f332030d5..7d870f22c 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -854,10 +854,17 @@ CCurrencyValueMap CScript::ReserveOutValue(COptCCParams &p, bool spendableOnly) // larger in a way that matters is on testnet for now. CCommitmentHash ch(p.vData[0]); - // TODO: HARDENING - once Verus Vault activates on mainnet, support currencies - if (ch.IsValid() && !_IsVerusMainnetActive()) + if (ch.IsValid()) { retVal = ch.reserveValues; + + // TODO: HARDENING - once Verus Vault activates on mainnet, support currencies and remove this if statement just below + // until PBaaS, we should have no valid currency outputs on mainnet + if (_IsVerusMainnetActive() && retVal.valueMap.size()) + { + LogPrintf("%s: invalid identity commitment output detected\n", __func__); + printf("%s: invalid identity commitment output detected\n", __func__); + } } } } @@ -1146,6 +1153,7 @@ std::set COptCCParams::GetIndexKeys() const } if (!checkNotarization.IsMirror()) { + // TODO: POST HARDENING consider whether this can use the native hash writer with an alternate hash CNativeHashWriter hw; hw << checkNotarization; uint256 objHash = hw.GetHash(); diff --git a/src/script/serverchecker.cpp b/src/script/serverchecker.cpp index 59af223ef..7b1cdbc5f 100644 --- a/src/script/serverchecker.cpp +++ b/src/script/serverchecker.cpp @@ -135,7 +135,7 @@ std::map>>> Serve } if (id.IsValidUnrevoked() && (isStake || sourceIsSelf || !id.IsLocked(spendHeight))) { - // TODO: HARDENING - in next upgrade, consider adding limits on what can be modified in an ID + // TODO: POST HARDENING - in next upgrade, consider adding limits on what can be modified in an ID std::vector> idAddrBytes; for (auto &oneAddr : id.primaryAddresses) diff --git a/src/version.h b/src/version.h index b8b2e67e9..a55079549 100644 --- a/src/version.h +++ b/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-1" +#define VERUS_VERSION "0.9.4-2" #endif // BITCOIN_VERSION_H