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));
    }
  }
Exemple #4
0
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);
}
Exemple #5
0
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();
  }
Exemple #7
0
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;
}