From c5a8adb3e4c51859eb41bbac8974f2751a46f867 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Thu, 16 Jan 2020 01:12:55 +0100 Subject: [PATCH] [Core][Cleanup] Add IsRegTestNet() function in chainparams --- src/activemasternode.cpp | 2 +- src/chainparams.h | 1 + src/kernel.cpp | 12 ++++++------ src/main.cpp | 15 ++++++++------- src/masternode-sync.cpp | 7 ++++--- src/masternode.cpp | 5 ++--- src/masternodeman.cpp | 2 +- src/net.cpp | 3 ++- src/pow.cpp | 2 +- src/qt/walletmodel.cpp | 2 +- src/rpc/rawtransaction.cpp | 10 +++++----- src/stakeinput.cpp | 2 +- src/timedata.cpp | 2 +- src/wallet/rpcdump.cpp | 2 +- src/wallet/rpcwallet.cpp | 10 +++++----- src/wallet/wallet.cpp | 2 +- src/zpiv/accumulators.cpp | 8 ++++---- 17 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 6084405111a2f..d0b6e1b2ead4f 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -24,7 +24,7 @@ void CActiveMasternode::ManageStatus() if (fDebug) LogPrintf("CActiveMasternode::ManageStatus() - Begin\n"); //need correct blocks to send ping - if (Params().NetworkID() != CBaseChainParams::REGTEST && !masternodeSync.IsBlockchainSynced()) { + if (!Params().IsRegTestNet() && !masternodeSync.IsBlockchainSynced()) { status = ACTIVE_MASTERNODE_SYNC_IN_PROCESS; LogPrintf("CActiveMasternode::ManageStatus() - %s\n", GetStatus()); return; diff --git a/src/chainparams.h b/src/chainparams.h index 28298dac2389a..c91a78d121698 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -122,6 +122,7 @@ class CChainParams int64_t Budget_Fee_Confirmations() const { return nBudget_Fee_Confirmations; } CBaseChainParams::Network NetworkID() const { return networkID; } + bool IsRegTestNet() const { return NetworkID() == CBaseChainParams::REGTEST; } /** Zerocoin **/ std::string Zerocoin_Modulus() const { return zerocoinModulus; } diff --git a/src/kernel.cpp b/src/kernel.cpp index 48eb02a01f399..94596d2ca2a6a 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -119,7 +119,7 @@ uint256 ComputeStakeModifier(const CBlockIndex* pindexPrev, const uint256& kerne { // genesis block's modifier is 0 // all block's modifiers are 0 on regtest - if (!pindexPrev || Params().NetworkID() == CBaseChainParams::REGTEST) + if (!pindexPrev || Params().IsRegTestNet()) return uint256(); CHashWriter ss(SER_GETHASH, 0); @@ -153,7 +153,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeMod fGeneratedStakeModifier = false; // modifier 0 on RegTest - if (Params().NetworkID() == CBaseChainParams::REGTEST) { + if (Params().IsRegTestNet()) { return true; } if (!pindexPrev) { @@ -250,7 +250,7 @@ bool GetKernelStakeModifier(const uint256& hashBlockFrom, uint64_t& nStakeModifi { nStakeModifier = 0; // modifier 0 on RegTest - if (Params().NetworkID() == CBaseChainParams::REGTEST) { + if (Params().IsRegTestNet()) { return true; } if (!mapBlockIndex.count(hashBlockFrom)) @@ -259,7 +259,7 @@ bool GetKernelStakeModifier(const uint256& hashBlockFrom, uint64_t& nStakeModifi nStakeModifierHeight = pindexFrom->nHeight; nStakeModifierTime = pindexFrom->GetBlockTime(); // Fixed stake modifier only for regtest - if (Params().NetworkID() == CBaseChainParams::REGTEST) { + if (Params().IsRegTestNet()) { nStakeModifier = pindexFrom->nStakeModifier; return true; } @@ -370,7 +370,7 @@ bool Stake(const CBlockIndex* pindexPrev, CStakeInput* stakeInput, unsigned int nTimeTx = GetCurrentTimeSlot(); // double check that we are not on the same slot as prev block - if (nTimeTx <= pindexPrev->nTime && Params().NetworkID() != CBaseChainParams::REGTEST) + if (!Params().IsRegTestNet() && nTimeTx <= pindexPrev->nTime) return false; // check stake kernel @@ -389,7 +389,7 @@ bool StakeV1(const CBlockIndex* pindexPrev, CStakeInput* stakeInput, const uint3 const unsigned int prevBlockTime = pindexPrev->nTime; const unsigned int maxTime = pindexPrev->MaxFutureBlockTime(); unsigned int minTime = std::max(prevBlockTime, nTimeBlockFrom + 3600); - if (Params().NetworkID() == CBaseChainParams::REGTEST) + if (Params().IsRegTestNet()) minTime = prevBlockTime; unsigned int nTryTime = maxTime; diff --git a/src/main.cpp b/src/main.cpp index 9360936b205cc..986a40df146ac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1580,8 +1580,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa // As zero fee transactions are not going to be accepted in the near future (4.0) and the code will be fully refactored soon. // This is just a quick inline towards that goal, the mempool by default will not accept them. Blocking // any subsequent network relay. - if ((Params().NetworkID() != CBaseChainParams::REGTEST) && - nFees == 0 && !hasZcSpendInputs) { + if (!Params().IsRegTestNet() && nFees == 0 && !hasZcSpendInputs) { return error("%s : zero fees not accepted %s, %d > %d", __func__, hash.ToString(), nFees, ::minRelayTxFee.GetFee(nSize) * 10000); } @@ -1999,7 +1998,7 @@ int64_t GetBlockValue(int nHeight) return 250000 * COIN; } - if (Params().NetworkID() == CBaseChainParams::REGTEST) { + if (Params().IsRegTestNet()) { if (nHeight == 0) return 250 * COIN; @@ -4320,13 +4319,15 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f return state.DoS(50, error("CheckBlockHeader() : proof of work failed"), REJECT_INVALID, "high-hash"); + if (Params().IsRegTestNet()) return true; + // Version 4 header must be used after Params().Zerocoin_StartHeight(). And never before. if (block.GetBlockTime() > Params().Zerocoin_StartTime()) { - if(block.nVersion < Params().Zerocoin_HeaderVersion() && Params().NetworkID() != CBaseChainParams::REGTEST) + if(block.nVersion < Params().Zerocoin_HeaderVersion()) return state.DoS(50, error("CheckBlockHeader() : block version must be above 4 after ZerocoinStartHeight"), REJECT_INVALID, "block-version"); } else { - if (block.nVersion >= Params().Zerocoin_HeaderVersion() && Params().NetworkID() != CBaseChainParams::REGTEST) + if (block.nVersion >= Params().Zerocoin_HeaderVersion()) return state.DoS(50, error("CheckBlockHeader() : block version must be below 4 before ZerocoinStartHeight"), REJECT_INVALID, "block-version"); } @@ -4559,7 +4560,7 @@ bool CheckWork(const CBlock block, CBlockIndex* const pindexPrev) unsigned int nBitsRequired = GetNextWorkRequired(pindexPrev, &block); - if ((Params().NetworkID() != CBaseChainParams::REGTEST) && block.IsProofOfWork() && (pindexPrev->nHeight + 1 <= 68589)) { + if (!Params().IsRegTestNet() && block.IsProofOfWork() && (pindexPrev->nHeight + 1 <= 68589)) { double n1 = ConvertBitsToDouble(block.nBits); double n2 = ConvertBitsToDouble(nBitsRequired); @@ -4585,7 +4586,7 @@ bool CheckWork(const CBlock block, CBlockIndex* const pindexPrev) bool CheckBlockTime(const CBlockHeader& block, CValidationState& state, CBlockIndex* const pindexPrev) { // Not enforced on RegTest - if (Params().NetworkID() == CBaseChainParams::REGTEST) + if (Params().IsRegTestNet()) return true; const int64_t blockTime = block.GetBlockTime(); diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp index 029f7c47e7678..e18dfa444c92f 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode-sync.cpp @@ -255,6 +255,7 @@ void CMasternodeSync::ClearFulfilledRequest() void CMasternodeSync::Process() { static int tick = 0; + const bool isRegTestNet = Params().IsRegTestNet(); if (tick++ % MASTERNODE_SYNC_TIMEOUT != 0) return; @@ -280,14 +281,14 @@ void CMasternodeSync::Process() if (RequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) GetNextAsset(); // sporks synced but blockchain is not, wait until we're almost at a recent block to continue - if (Params().NetworkID() != CBaseChainParams::REGTEST && - !IsBlockchainSynced() && RequestedMasternodeAssets > MASTERNODE_SYNC_SPORKS) return; + if (!isRegTestNet && !IsBlockchainSynced() && + RequestedMasternodeAssets > MASTERNODE_SYNC_SPORKS) return; TRY_LOCK(cs_vNodes, lockRecv); if (!lockRecv) return; for (CNode* pnode : vNodes) { - if (Params().NetworkID() == CBaseChainParams::REGTEST) { + if (isRegTestNet) { if (RequestedMasternodeAttempt <= 2) { pnode->PushMessage("getsporks"); //get current network sporks } else if (RequestedMasternodeAttempt < 4) { diff --git a/src/masternode.cpp b/src/masternode.cpp index c3bf63d48c19a..24411404911aa 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -324,7 +324,7 @@ bool CMasternode::IsValidNetAddr() { // TODO: regtest is fine with any addresses for now, // should probably be a bit smarter if one day we start to implement tests for this - return Params().NetworkID() == CBaseChainParams::REGTEST || + return Params().IsRegTestNet() || (IsReachable(addr) && addr.IsRoutable()); } @@ -670,8 +670,7 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS) activeMasternode.EnableHotColdMasterNode(vin, addr); } - bool isLocal = addr.IsRFC1918() || addr.IsLocal(); - if (Params().NetworkID() == CBaseChainParams::REGTEST) isLocal = false; + bool isLocal = (addr.IsRFC1918() || addr.IsLocal()) && !Params().IsRegTestNet(); if (!isLocal) Relay(); diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 2917f6b6b39e1..350fcb8c59b4f 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -709,7 +709,7 @@ CMasternode* CMasternodeMan::GetMasternodeByRank(int nRank, int64_t nBlockHeight void CMasternodeMan::ProcessMasternodeConnections() { //we don't care about this for regtest - if (Params().NetworkID() == CBaseChainParams::REGTEST) return; + if (Params().IsRegTestNet()) return; LOCK(cs_vNodes); for (CNode* pnode : vNodes) { diff --git a/src/net.cpp b/src/net.cpp index a460a378b90b9..354dd639018d6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -371,8 +371,9 @@ CNode* FindNode(const std::string& addrName) CNode* FindNode(const CService& addr) { LOCK(cs_vNodes); + const bool isRegTestNet = Params().IsRegTestNet(); for (CNode* pnode : vNodes) { - if (Params().NetworkID() == CBaseChainParams::REGTEST) { + if (isRegTestNet) { //if using regtest, just check the IP if ((CNetAddr)pnode->addr == (CNetAddr)addr) return (pnode); diff --git a/src/pow.cpp b/src/pow.cpp index 752dea73f077e..e71a4b19a9100 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -19,7 +19,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader* pblock) { - if (Params().NetworkID() == CBaseChainParams::REGTEST) + if (Params().IsRegTestNet()) return pindexLast->nBits; /* current difficulty formula, pivx - DarkGravity v3, written by Evan Duffield - evan@dashpay.io */ diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index a3c888f3558c2..2a7581a133d4d 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -59,7 +59,7 @@ WalletModel::~WalletModel() } bool WalletModel::isTestNetwork() const { - return Params().NetworkID() == CBaseChainParams::TESTNET || Params().NetworkID() == CBaseChainParams::REGTEST; + return Params().NetworkID() == CBaseChainParams::TESTNET || Params().IsRegTestNet(); } bool WalletModel::isColdStakingNetworkelyEnabled() const { diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 65aec16f4902d..ab9314123908a 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -631,7 +631,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) // Fetch previous transactions (inputs): std::map mapPrevOut; - if (Params().NetworkID() == CBaseChainParams::REGTEST) { + if (Params().IsRegTestNet()) { for (const CTxIn &txbase : mergedTx.vin) { CTransaction tempTx; @@ -756,7 +756,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) for (unsigned int i = 0; i < mergedTx.vin.size(); i++) { CTxIn& txin = mergedTx.vin[i]; const CCoins* coins = view.AccessCoins(txin.prevout.hash); - if (Params().NetworkID() == CBaseChainParams::REGTEST) { + if (Params().IsRegTestNet()) { if (mapPrevOut.count(txin.prevout) == 0 && (coins == NULL || !coins->IsAvailable(txin.prevout.n))) { TxInErrorToJSON(txin, vErrors, "Input not found"); @@ -768,7 +768,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) continue; } } - const CScript& prevPubKey = (Params().NetworkID() == CBaseChainParams::REGTEST && mapPrevOut.count(txin.prevout) != 0 ? mapPrevOut[txin.prevout] : coins->vout[txin.prevout.n].scriptPubKey); + const CScript& prevPubKey = (Params().IsRegTestNet() && mapPrevOut.count(txin.prevout) != 0 ? mapPrevOut[txin.prevout] : coins->vout[txin.prevout.n].scriptPubKey); txin.scriptSig.clear(); @@ -939,7 +939,7 @@ UniValue createrawzerocoinstake(const UniValue& params, bool fHelp) HelpExampleRpc("createrawzerocoinstake", "0d8c16eee7737e3cc1e4e70dc006634182b175e039700931283b202715a0818f")); - if (Params().NetworkID() != CBaseChainParams::REGTEST) + if (!Params().IsRegTestNet()) throw JSONRPCError(RPC_WALLET_ERROR, "createrawzerocoinstake is available only on regtest net"); assert(pwalletMain != NULL); @@ -1041,7 +1041,7 @@ UniValue createrawzerocoinspend(const UniValue& params, bool fHelp) addr_ptr = &address; } - if (Params().NetworkID() != CBaseChainParams::REGTEST && !isPublicSpend) + if (!Params().IsRegTestNet() && !isPublicSpend) throw JSONRPCError(RPC_WALLET_ERROR, "zPIV old spend only available in regtest for tests purposes"); assert(pwalletMain != NULL); diff --git a/src/stakeinput.cpp b/src/stakeinput.cpp index 68000e2323406..fca783db6648e 100644 --- a/src/stakeinput.cpp +++ b/src/stakeinput.cpp @@ -78,7 +78,7 @@ bool CZPivStake::GetModifier(uint64_t& nStakeModifier) if (!pindex) return error("%s: failed to get index from", __func__); - if(Params().NetworkID() == CBaseChainParams::REGTEST) { + if(Params().IsRegTestNet()) { // Stake modifier is fixed for now, move it to 60 blocks after this pindex in the future.. nStakeModifier = pindexFrom->nStakeModifier; return true; diff --git a/src/timedata.cpp b/src/timedata.cpp index 97f237d8aecb1..e4889b63084e0 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -43,7 +43,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample, int nOffsetLimit) static std::set setKnown; if (setKnown.size() == BITCOIN_TIMEDATA_MAX_SAMPLES) return; - if (!setKnown.insert(ip).second && Params().NetworkID() != CBaseChainParams::REGTEST) + if (!Params().IsRegTestNet() && !setKnown.insert(ip).second) return; // Add data diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 1e657f770b1b7..248ef45bd5d41 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -139,7 +139,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp) if (fRescan) { CBlockIndex *pindex = chainActive.Genesis(); - if (fStakingAddress && Params().NetworkID() != CBaseChainParams::REGTEST) { + if (fStakingAddress && !Params().IsRegTestNet()) { // cold staking was activated after nBlockTimeProtocolV2. No need to scan the whole chain pindex = chainActive[Params().BlockStartTimeProtocolV2()]; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 9f7ced3312407..d4ae6ca55dc7f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3363,7 +3363,7 @@ UniValue mintzerocoin(const UniValue& params, bool fHelp) HelpExampleRpc("mintzerocoin", "13, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")); - if (Params().NetworkID() != CBaseChainParams::REGTEST) + if (!Params().IsRegTestNet()) throw JSONRPCError(RPC_WALLET_ERROR, "zPIV minting is DISABLED"); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -3493,7 +3493,7 @@ UniValue spendzerocoin(const UniValue& params, bool fHelp) const std::string address_str = (params.size() > 3 ? params[3].get_str() : ""); const bool isPublicSpend = (params.size() > 4 ? params[4].get_bool() : true); - if (Params().NetworkID() != CBaseChainParams::REGTEST) { + if (!Params().IsRegTestNet()) { if (fMintChange) throw JSONRPCError(RPC_WALLET_ERROR, "zPIV minting is DISABLED (except for regtest), cannot mint change"); @@ -3559,7 +3559,7 @@ UniValue spendzerocoinmints(const UniValue& params, bool fHelp) if (arrMints.size() == 0) throw JSONRPCError(RPC_WALLET_ERROR, "No zerocoin selected"); - if (!isPublicSpend && Params().NetworkID() != CBaseChainParams::REGTEST) { + if (!isPublicSpend && !Params().IsRegTestNet()) { throw JSONRPCError(RPC_WALLET_ERROR, "zPIV old spend only available in regtest for tests purposes"); } @@ -3592,7 +3592,7 @@ UniValue spendzerocoinmints(const UniValue& params, bool fHelp) extern UniValue DoZpivSpend(const CAmount nAmount, bool fMintChange, bool fMinimizeChange, std::vector& vMintsSelected, std::string address_str, bool isPublicSpend) { // zerocoin mint / v2 spend is disabled. fMintChange/isPublicSpend should be false here. Double check - if (Params().NetworkID() != CBaseChainParams::REGTEST) { + if (!Params().IsRegTestNet()) { if (fMintChange) throw JSONRPCError(RPC_WALLET_ERROR, "zPIV minting is DISABLED (except for regtest), cannot mint change"); @@ -4298,7 +4298,7 @@ UniValue spendrawzerocoin(const UniValue& params, bool fHelp) HelpExampleRpc("spendrawzerocoin", "\"f80892e78c30a393ef4ab4d5a9d5a2989de6ebc7b976b241948c7f489ad716a2\", \"a4fd4d7248e6a51f1d877ddd2a4965996154acc6b8de5aa6c83d4775b283b600\", 100, \"xxx\"")); const bool isPublicSpend = (params.size() > 6 ? params[6].get_bool() : true); - if (Params().NetworkID() != CBaseChainParams::REGTEST && !isPublicSpend) + if (!Params().IsRegTestNet() && !isPublicSpend) throw JSONRPCError(RPC_WALLET_ERROR, "zPIV old spend only available in regtest for tests purposes"); LOCK2(cs_main, pwalletMain->cs_wallet); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3c2d8fdb44ed6..302c75ce2a905 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3974,7 +3974,7 @@ bool CWallet::CheckCoinSpend(libzerocoin::CoinSpend& spend, libzerocoin::Accumul return error("%s : The transaction did not verify", __func__); } - if (Params().NetworkID() != CBaseChainParams::REGTEST && IsSerialKnown(spend.getCoinSerialNumber())) { + if (IsSerialKnown(spend.getCoinSerialNumber())) { //Tried to spend an already spent zPIV receipt.SetStatus(_("The coin spend has been used"), ZPIV_SPENT_USED_ZPIV); uint256 hashSerial = GetSerialHash(spend.getCoinSerialNumber()); diff --git a/src/zpiv/accumulators.cpp b/src/zpiv/accumulators.cpp index 124308eaf5c05..866128002fb82 100644 --- a/src/zpiv/accumulators.cpp +++ b/src/zpiv/accumulators.cpp @@ -202,7 +202,7 @@ bool InitializeAccumulators(const int nHeight, int& nHeightCheckpoint, Accumulat return error("%s: height is above last accumulator checkpoint", __func__); //On a specific block, a recalculation of the accumulators will be forced - if (nHeight == Params().Zerocoin_Block_RecalculateAccumulators() && Params().NetworkID() != CBaseChainParams::REGTEST) { + if (!Params().IsRegTestNet() && nHeight == Params().Zerocoin_Block_RecalculateAccumulators()) { mapAccumulators.Reset(); if (!mapAccumulators.Load(chainActive[Params().Zerocoin_Block_LastGoodCheckpoint()]->nAccumulatorCheckpoint)) return error("%s: failed to reset to previous checkpoint when recalculating accumulators", __func__); @@ -220,7 +220,7 @@ bool InitializeAccumulators(const int nHeight, int& nHeightCheckpoint, Accumulat mapAccumulators.Reset(Params().Zerocoin_Params(false)); // 20 after v2 start is when the new checkpoints will be in the block, so don't need to load hard checkpoints - if (nHeight <= Params().Zerocoin_Block_V2_Start() + 20 && Params().NetworkID() != CBaseChainParams::REGTEST) { + if (!Params().IsRegTestNet() && nHeight <= Params().Zerocoin_Block_V2_Start() + 20) { //Load hard coded checkpointed value AccumulatorCheckpoints::Checkpoint checkpoint = AccumulatorCheckpoints::GetClosestCheckpoint(nHeight, nHeightCheckpoint); @@ -728,10 +728,10 @@ bool GenerateAccumulatorWitness( //Get the accumulator that is right before the cluster of blocks containing our mint was added to the accumulator CBigNum bnAccValue = 0; if (GetAccumulatorValue(nHeightCheckpoint, coin.getDenomination(), bnAccValue)) { - if(!bnAccValue && Params().NetworkID() == CBaseChainParams::REGTEST){ + if(!bnAccValue && Params().IsRegTestNet()){ accumulator.setInitialValue(); witness.resetValue(accumulator, coin); - }else { + } else { accumulator.setValue(bnAccValue); witness.resetValue(accumulator, coin); }