std::error_code TestWalletLegacy::init() { CryptoNote::AccountBase walletAccount; walletAccount.generate(); m_wallet->initWithKeys(walletAccount.getAccountKeys(), TEST_PASSWORD); m_synchronizationCompleted.wait(); return m_lastSynchronizationResult; }
TEST_F(TransfersTest, base) { uint64_t TRANSFER_AMOUNT; currency.parseAmount("500000.5", TRANSFER_AMOUNT); launchTestnet(2); std::unique_ptr<CryptoNote::INode> node1; std::unique_ptr<CryptoNote::INode> node2; nodeDaemons[0]->makeINode(node1); nodeDaemons[1]->makeINode(node2); CryptoNote::AccountBase dstAcc; dstAcc.generate(); AccountKeys dstKeys = reinterpret_cast<const AccountKeys&>(dstAcc.getAccountKeys()); BlockchainSynchronizer blockSync(*node2.get(), currency.genesisBlockHash()); TransfersSyncronizer transferSync(currency, blockSync, *node2.get()); TransfersObserver transferObserver; WalletLegacyObserver walletObserver; AccountSubscription sub; sub.syncStart.timestamp = 0; sub.syncStart.height = 0; sub.keys = dstKeys; sub.transactionSpendableAge = 5; ITransfersSubscription& transferSub = transferSync.addSubscription(sub); ITransfersContainer& transferContainer = transferSub.getContainer(); transferSub.addObserver(&transferObserver); Tests::Common::TestWalletLegacy wallet1(m_dispatcher, m_currency, *node1); ASSERT_FALSE(static_cast<bool>(wallet1.init())); wallet1.wallet()->addObserver(&walletObserver); ASSERT_TRUE(mineBlocks(*nodeDaemons[0], wallet1.address(), 1)); ASSERT_TRUE(mineBlocks(*nodeDaemons[0], wallet1.address(), currency.minedMoneyUnlockWindow())); wallet1.waitForSynchronizationToHeight(static_cast<uint32_t>(2 + currency.minedMoneyUnlockWindow())); // start syncing and wait for a transfer FutureGuard<bool> waitFuture(std::async(std::launch::async, [&transferObserver] { return transferObserver.waitTransfer(); })); Interrupter transferObserverInterrupter(transferObserver); blockSync.start(); Hash txId; ASSERT_FALSE(static_cast<bool>(wallet1.sendTransaction(currency.accountAddressAsString(dstAcc), TRANSFER_AMOUNT, txId))); ASSERT_TRUE(mineBlocks(*nodeDaemons[0], wallet1.address(), 1)); ASSERT_TRUE(waitFuture.get()); transferObserverInterrupter.cancel(); std::cout << "Received transfer: " << currency.formatAmount(transferContainer.balance(ITransfersContainer::IncludeAll)) << std::endl; ASSERT_EQ(TRANSFER_AMOUNT, transferContainer.balance(ITransfersContainer::IncludeAll)); ASSERT_GT(transferContainer.getTransactionOutputs(txId, ITransfersContainer::IncludeAll).size(), 0); blockSync.stop(); }
void generateAccounts(size_t count) { CryptoNote::AccountBase acc; while (count--) { acc.generate(); AccountSubscription sub; sub.keys = reinterpret_cast<const AccountKeys&>(acc.getAccountKeys()); sub.syncStart.timestamp = 0; sub.syncStart.height = 0; sub.transactionSpendableAge = TRANSACTION_SPENDABLE_AGE; m_accounts.push_back(sub); m_addresses.push_back(currency.accountAddressAsString(acc)); } }
bool test_generator::constructMaxSizeBlock(CryptoNote::Block& blk, const CryptoNote::Block& blkPrev, const CryptoNote::AccountBase& minerAccount, size_t medianBlockCount/* = 0*/, const std::list<CryptoNote::Transaction>& txList/* = std::list<CryptoNote::Transaction>()*/) { std::vector<size_t> blockSizes; medianBlockCount = medianBlockCount == 0 ? m_currency.rewardBlocksWindow() : medianBlockCount; getLastNBlockSizes(blockSizes, get_block_hash(blkPrev), medianBlockCount); size_t median = Common::medianValue(blockSizes); size_t blockGrantedFullRewardZone = m_currency.blockGrantedFullRewardZoneByBlockVersion(defaultMajorVersion); median = std::max(median, blockGrantedFullRewardZone); uint64_t totalFee = 0; size_t txsSize = 0; std::vector<Crypto::Hash> transactionHashes; for (auto& tx : txList) { uint64_t fee = 0; bool r = get_tx_fee(tx, fee); CHECK_AND_ASSERT_MES(r, false, "wrong transaction passed to construct_max_size_block"); totalFee += fee; txsSize += getObjectBinarySize(tx); transactionHashes.push_back(getObjectHash(tx)); } Transaction baseTransaction; bool r = constructMinerTxBySize(m_currency, baseTransaction, defaultMajorVersion, get_block_height(blkPrev) + 1, getAlreadyGeneratedCoins(blkPrev), minerAccount.getAccountKeys().address, blockSizes, 2 * median - txsSize, 2 * median, totalFee); if (!r) { return false; } return constructBlockManually(blk, blkPrev, minerAccount, test_generator::bf_miner_tx | test_generator::bf_tx_hashes, 0, 0, 0, Crypto::Hash(), 0, baseTransaction, transactionHashes, txsSize, totalFee); }
bool init_output_indices(map_output_idx_t& outs, std::map<uint64_t, std::vector<size_t> >& outs_mine, const std::vector<CryptoNote::Block>& blockchain, const map_hash2tx_t& mtx, const CryptoNote::AccountBase& from) { BOOST_FOREACH (const Block& blk, blockchain) { vector<const Transaction*> vtx; vtx.push_back(&blk.baseTransaction); for (const Crypto::Hash& h : blk.transactionHashes) { const map_hash2tx_t::const_iterator cit = mtx.find(h); if (mtx.end() == cit) throw std::runtime_error("block contains an unknown tx hash"); vtx.push_back(cit->second); } //vtx.insert(vtx.end(), blk.); // TODO: add all other txes for (size_t i = 0; i < vtx.size(); i++) { const Transaction &tx = *vtx[i]; size_t keyIndex = 0; for (size_t j = 0; j < tx.outputs.size(); ++j) { const TransactionOutput &out = tx.outputs[j]; if (out.target.type() == typeid(KeyOutput)) { output_index oi(out.target, out.amount, boost::get<BaseInput>(*blk.baseTransaction.inputs.begin()).blockIndex, i, j, &blk, vtx[i]); outs[out.amount].push_back(oi); uint32_t tx_global_idx = static_cast<uint32_t>(outs[out.amount].size() - 1); outs[out.amount][tx_global_idx].idx = tx_global_idx; // Is out to me? if (is_out_to_acc(from.getAccountKeys(), boost::get<KeyOutput>(out.target), getTransactionPublicKeyFromExtra(tx.extra), keyIndex)) { outs_mine[out.amount].push_back(tx_global_idx); } ++keyIndex; } else if (out.target.type() == typeid(MultisignatureOutput)) { keyIndex += boost::get<MultisignatureOutput>(out.target).keys.size(); } } } }
void run() { if (m_config.daemons.empty()) { logger(ERROR, BRIGHT_RED) << "No daemons configured, exiting"; return; } launchTestnet(m_nodeCount, Tests::Common::BaseFunctionalTests::Line); createWallets(); miningTest(); // create some address for mining CryptoNote::AccountBase stashAddress; stashAddress.generate(); auto stashAddressStr = m_currency.accountAddressAsString(stashAddress); unlockMoney(stashAddressStr); std::vector<uint64_t> balances; for (auto& o : m_observers) { balances.push_back(o->totalBalance()); } printBalances(); // transfer money from each wallet to each other for (size_t i = 0; i < m_nodeCount; ++i) { auto& srcWallet = *m_wallets[i]; for (size_t wi = 0; wi < m_nodeCount; ++wi) { if (i != wi) { CryptoNote::WalletLegacyTransfer transfer; transfer.address = m_wallets[wi]->getAddress(); transfer.amount = (i * 1000 + wi * 100) * m_currency.coin(); logger(INFO, BRIGHT_YELLOW) << "Sending from " << shortAddress(srcWallet.getAddress()) << " to " << shortAddress(transfer.address) << " amount = " << m_currency.formatAmount(transfer.amount); auto txid = srcWallet.sendTransaction(transfer, m_currency.minimumFee()); balances[i] -= transfer.amount + m_currency.minimumFee(); balances[wi] += transfer.amount; auto res = m_observers[i]->waitSendResult(txid); if (res) { logger(ERROR, BRIGHT_RED) << "Failed to send transaction: " << res.message(); throw std::runtime_error("Failed to send transaction: " + res.message()); } logger(INFO) << "Sent successfully"; } } } nodeDaemons[0]->startMining(1, stashAddressStr); for (size_t i = 0; i < m_nodeCount; ++i) { uint64_t total; logger(INFO) << i << " Expected target balance: " << m_currency.formatAmount(balances[i]); while ((total = m_wallets[i]->pendingBalance() + m_wallets[i]->actualBalance()) != balances[i]) { logger(INFO) << i << " - total: " << m_currency.formatAmount(total) << ", waiting"; m_observers[i]->waitTotalBalanceChange(); } } nodeDaemons[0]->stopMining(); printBalances(); }
bool test_generator::constructBlock(CryptoNote::Block& blk, uint32_t height, const Crypto::Hash& previousBlockHash, const CryptoNote::AccountBase& minerAcc, uint64_t timestamp, uint64_t alreadyGeneratedCoins, std::vector<size_t>& blockSizes, const std::list<CryptoNote::Transaction>& txList) { blk.majorVersion = defaultMajorVersion; blk.minorVersion = defaultMinorVersion; blk.timestamp = timestamp; blk.previousBlockHash = previousBlockHash; blk.transactionHashes.reserve(txList.size()); for (const Transaction &tx : txList) { Crypto::Hash tx_hash; getObjectHash(tx, tx_hash); blk.transactionHashes.push_back(tx_hash); } uint64_t totalFee = 0; size_t txsSize = 0; for (auto& tx : txList) { uint64_t fee = 0; bool r = get_tx_fee(tx, fee); CHECK_AND_ASSERT_MES(r, false, "wrong transaction passed to construct_block"); totalFee += fee; txsSize += getObjectBinarySize(tx); } blk.baseTransaction = boost::value_initialized<Transaction>(); size_t targetBlockSize = txsSize + getObjectBinarySize(blk.baseTransaction); while (true) { if (!m_currency.constructMinerTx(blk.majorVersion, height, Common::medianValue(blockSizes), alreadyGeneratedCoins, targetBlockSize, totalFee, minerAcc.getAccountKeys().address, blk.baseTransaction, BinaryArray(), 10)) { return false; } size_t actualBlockSize = txsSize + getObjectBinarySize(blk.baseTransaction); if (targetBlockSize < actualBlockSize) { targetBlockSize = actualBlockSize; } else if (actualBlockSize < targetBlockSize) { size_t delta = targetBlockSize - actualBlockSize; blk.baseTransaction.extra.resize(blk.baseTransaction.extra.size() + delta, 0); actualBlockSize = txsSize + getObjectBinarySize(blk.baseTransaction); if (actualBlockSize == targetBlockSize) { break; } else { CHECK_AND_ASSERT_MES(targetBlockSize < actualBlockSize, false, "Unexpected block size"); delta = actualBlockSize - targetBlockSize; blk.baseTransaction.extra.resize(blk.baseTransaction.extra.size() - delta); actualBlockSize = txsSize + getObjectBinarySize(blk.baseTransaction); if (actualBlockSize == targetBlockSize) { break; } else { CHECK_AND_ASSERT_MES(actualBlockSize < targetBlockSize, false, "Unexpected block size"); blk.baseTransaction.extra.resize(blk.baseTransaction.extra.size() + delta, 0); targetBlockSize = txsSize + getObjectBinarySize(blk.baseTransaction); } } } else { break; } } if (blk.majorVersion >= BLOCK_MAJOR_VERSION_2) { blk.parentBlock.majorVersion = BLOCK_MAJOR_VERSION_1; blk.parentBlock.minorVersion = BLOCK_MINOR_VERSION_0; blk.parentBlock.transactionCount = 1; blk.parentBlock.baseTransaction.version = 0; blk.parentBlock.baseTransaction.unlockTime = 0; CryptoNote::TransactionExtraMergeMiningTag mmTag; mmTag.depth = 0; if (!CryptoNote::get_aux_block_header_hash(blk, mmTag.merkleRoot)) { return false; } blk.parentBlock.baseTransaction.extra.clear(); if (!CryptoNote::appendMergeMiningTagToExtra(blk.parentBlock.baseTransaction.extra, mmTag)) { return false; } } // Nonce search... blk.nonce = 0; Crypto::cn_context context; while (!miner::find_nonce_for_given_block(context, blk, getTestDifficulty())) { blk.timestamp++; } addBlock(blk, txsSize, totalFee, blockSizes, alreadyGeneratedCoins); return true; }