TEST(parse_and_validate_tx_extra, fails_on_big_extra_nonce) { Logging::LoggerGroup logger; CryptoNote::Currency currency = CryptoNote::CurrencyBuilder(logger).currency(); CryptoNote::Transaction tx = AUTO_VAL_INIT(tx); CryptoNote::account_base acc; acc.generate(); CryptoNote::blobdata b(TX_EXTRA_NONCE_MAX_COUNT + 1, 0); ASSERT_FALSE(currency.constructMinerTx(0, 0, 10000000000000, 1000, currency.minimumFee(), acc.get_keys().m_account_address, tx, b, 1)); }
TEST(parseAccountAddressString, fails_on_invalid_address_prefix) { std::string addr_str = base58::encode_addr(0, test_serialized_keys); Logging::LoggerGroup logger; CryptoNote::Currency currency = CryptoNote::CurrencyBuilder(logger).currency(); CryptoNote::AccountPublicAddress addr; ASSERT_FALSE(currency.parseAccountAddressString(addr_str, addr)); }
TEST(parse_and_validate_tx_extra, is_valid_tx_extra_parsed) { Logging::LoggerGroup logger; CryptoNote::Currency currency = CryptoNote::CurrencyBuilder(logger).currency(); CryptoNote::Transaction tx = AUTO_VAL_INIT(tx); CryptoNote::account_base acc; acc.generate(); CryptoNote::blobdata b = "dsdsdfsdfsf"; ASSERT_TRUE(currency.constructMinerTx(0, 0, 10000000000000, 1000, currency.minimumFee(), acc.get_keys().m_account_address, tx, b, 1)); crypto::public_key tx_pub_key = CryptoNote::get_tx_pub_key_from_extra(tx); ASSERT_NE(tx_pub_key, CryptoNote::null_pkey); }
bool test_block_creation() { Logging::ConsoleLogger logger; uint64_t vszs[] = {80,476,476,475,475,474,475,474,474,475,472,476,476,475,475,474,475,474,474,475,472,476,476,475,475,474,475,474,474,475,9391,476,476,475,475,474,475,8819,8301,475,472,4302,5316,14347,16620,19583,19403,19728,19442,19852,19015,19000,19016,19795,19749,18087,19787,19704,19750,19267,19006,19050,19445,19407,19522,19546,19788,19369,19486,19329,19370,18853,19600,19110,19320,19746,19474,19474,19743,19494,19755,19715,19769,19620,19368,19839,19532,23424,28287,30707}; std::vector<uint64_t> szs(&vszs[0], &vszs[90]); CryptoNote::Currency currency = CryptoNote::CurrencyBuilder(logger).currency(); AccountPublicAddress adr; bool r = currency.parseAccountAddressString("272xWzbWsP4cfNFfxY5ETN5moU8x81PKfWPwynrrqsNGDBQGLmD1kCkKCvPeDUXu5XfmZkCrQ53wsWmdfvHBGLNjGcRiDcK", adr); CHECK_AND_ASSERT_MES(r, false, "failed to import"); BlockTemplate b; r = currency.constructMinerTx(BLOCK_MAJOR_VERSION_1, 90, Common::medianValue(szs), 3553616528562147, 33094, 10000000, adr, b.baseTransaction, BinaryArray(), 11); return r; }
bool constructMinerTxBySize(const CryptoNote::Currency& currency, CryptoNote::Transaction& minerTx, uint32_t height, uint64_t alreadyGeneratedCoins, const CryptoNote::AccountPublicAddress& minerAddress, std::vector<size_t>& blockSizes, size_t targetTxSize, size_t targetBlockSize, uint64_t fee/* = 0*/, bool penalizeFee/* = false*/) { if (!currency.constructMinerTx(height, Common::medianValue(blockSizes), alreadyGeneratedCoins, targetBlockSize, fee, minerAddress, minerTx, CryptoNote::blobdata(), 1, penalizeFee)) { return false; } size_t currentSize = get_object_blobsize(minerTx); size_t tryCount = 0; while (targetTxSize != currentSize) { ++tryCount; if (10 < tryCount) { return false; } if (targetTxSize < currentSize) { size_t diff = currentSize - targetTxSize; if (diff <= minerTx.extra.size()) { minerTx.extra.resize(minerTx.extra.size() - diff); } else { return false; } } else { size_t diff = targetTxSize - currentSize; minerTx.extra.resize(minerTx.extra.size() + diff); } currentSize = get_object_blobsize(minerTx); } return true; }
bool constructMinerTxBySize(const CryptoNote::Currency& currency, CryptoNote::Transaction& baseTransaction, uint8_t blockMajorVersion, uint32_t height, uint64_t alreadyGeneratedCoins, const CryptoNote::AccountPublicAddress& minerAddress, std::vector<size_t>& blockSizes, size_t targetTxSize, size_t targetBlockSize, uint64_t fee/* = 0*/) { if (!currency.constructMinerTx(blockMajorVersion, height, Common::medianValue(blockSizes), alreadyGeneratedCoins, targetBlockSize, fee, minerAddress, baseTransaction, CryptoNote::BinaryArray(), 1)) { return false; } size_t currentSize = getObjectBinarySize(baseTransaction); size_t tryCount = 0; while (targetTxSize != currentSize) { ++tryCount; if (10 < tryCount) { return false; } if (targetTxSize < currentSize) { size_t diff = currentSize - targetTxSize; if (diff <= baseTransaction.extra.size()) { baseTransaction.extra.resize(baseTransaction.extra.size() - diff); } else { return false; } } else { size_t diff = targetTxSize - currentSize; baseTransaction.extra.resize(baseTransaction.extra.size() + diff); } currentSize = getObjectBinarySize(baseTransaction); } return true; }
bool constructMinerTxManually(const CryptoNote::Currency& currency, uint32_t height, uint64_t alreadyGeneratedCoins, const AccountPublicAddress& minerAddress, Transaction& tx, uint64_t fee, KeyPair* pTxKey/* = 0*/) { KeyPair txkey; txkey = KeyPair::generate(); add_tx_pub_key_to_extra(tx, txkey.pub); if (0 != pTxKey) { *pTxKey = txkey; } TransactionInputGenerate in; in.height = height; tx.vin.push_back(in); // This will work, until size of constructed block is less then currency.blockGrantedFullRewardZone() int64_t emissionChange; uint64_t blockReward; if (!currency.getBlockReward(0, 0, alreadyGeneratedCoins, fee, false, blockReward, emissionChange)) { std::cerr << "Block is too big" << std::endl; return false; } crypto::key_derivation derivation; crypto::public_key outEphPublicKey; crypto::generate_key_derivation(minerAddress.m_viewPublicKey, txkey.sec, derivation); crypto::derive_public_key(derivation, 0, minerAddress.m_spendPublicKey, outEphPublicKey); TransactionOutput out; out.amount = blockReward; out.target = TransactionOutputToKey(outEphPublicKey); tx.vout.push_back(out); tx.version = CURRENT_TRANSACTION_VERSION; tx.unlockTime = height + currency.minedMoneyUnlockWindow(); return true; }
bool constructMinerTxManually(const CryptoNote::Currency& currency, uint32_t height, uint64_t alreadyGeneratedCoins, const AccountPublicAddress& minerAddress, Transaction& tx, uint64_t fee, KeyPair* pTxKey/* = 0*/) { KeyPair txkey = generateKeyPair(); addTransactionPublicKeyToExtra(tx.extra, txkey.publicKey); if (0 != pTxKey) { *pTxKey = txkey; } BaseInput in; in.blockIndex = height; tx.inputs.push_back(in); // This will work, until size of constructed block is less then currency.blockGrantedFullRewardZone() int64_t emissionChange; uint64_t blockReward; if (!currency.getBlockReward(0, 0, alreadyGeneratedCoins, fee, height, blockReward, emissionChange)) { std::cerr << "Block is too big" << std::endl; return false; } Crypto::KeyDerivation derivation; Crypto::PublicKey outEphPublicKey; Crypto::generate_key_derivation(minerAddress.viewPublicKey, txkey.secretKey, derivation); Crypto::derive_public_key(derivation, 0, minerAddress.spendPublicKey, outEphPublicKey); TransactionOutput out; out.amount = blockReward; out.target = KeyOutput{outEphPublicKey}; tx.outputs.push_back(out); tx.version = TRANSACTION_VERSION_1; tx.unlockTime = height + currency.minedMoneyUnlockWindow(); return true; }
WalletLegacy::WalletLegacy(const CryptoNote::Currency& currency, INode& node) : m_state(NOT_INITIALIZED), m_currency(currency), m_node(node), m_isStopping(false), m_lastNotifiedActualBalance(0), m_lastNotifiedPendingBalance(0), m_blockchainSync(node, currency.genesisBlockHash()), m_transfersSync(currency, m_blockchainSync, node), m_transferDetails(nullptr), m_transactionsCache(m_currency.mempoolTxLiveTime()), m_sender(nullptr), m_onInitSyncStarter(new SyncStarter(m_blockchainSync)) { addObserver(m_onInitSyncStarter.get()); }
int main(int argc, char *argv[]) { if (argc != 2) { cerr << "Wrong arguments" << endl; return 1; } Logging::ConsoleLogger logger; CryptoNote::CurrencyBuilder currencyBuilder(logger); currencyBuilder.difficultyTarget(120); currencyBuilder.difficultyWindow(720); currencyBuilder.difficultyCut(60); currencyBuilder.difficultyLag(15); CryptoNote::Currency currency = currencyBuilder.currency(); vector<uint64_t> timestamps, cumulative_difficulties; fstream data(argv[1], fstream::in); data.exceptions(fstream::badbit); data.clear(data.rdstate()); uint64_t timestamp, difficulty, cumulative_difficulty = 0; size_t n = 0; while (data >> timestamp >> difficulty) { size_t begin, end; if (n < currency.difficultyWindow() + currency.difficultyLag()) { begin = 0; end = min(n, currency.difficultyWindow()); } else { end = n - currency.difficultyLag(); begin = end - currency.difficultyWindow(); } uint64_t res = currency.nextDifficulty( vector<uint64_t>(timestamps.begin() + begin, timestamps.begin() + end), vector<uint64_t>(cumulative_difficulties.begin() + begin, cumulative_difficulties.begin() + end)); if (res != difficulty) { cerr << "Wrong difficulty for block " << n << endl << "Expected: " << difficulty << endl << "Found: " << res << endl; return 1; } timestamps.push_back(timestamp); cumulative_difficulties.push_back(cumulative_difficulty += difficulty); ++n; } if (!data.eof()) { data.clear(fstream::badbit); } return 0; }
bool test_transaction_generation_and_ring_signature() { Logging::ConsoleLogger logger; CryptoNote::Currency currency = CryptoNote::CurrencyBuilder(logger).currency(); AccountBase miner_acc1; miner_acc1.generate(); AccountBase miner_acc2; miner_acc2.generate(); AccountBase miner_acc3; miner_acc3.generate(); AccountBase miner_acc4; miner_acc4.generate(); AccountBase miner_acc5; miner_acc5.generate(); AccountBase miner_acc6; miner_acc6.generate(); std::string add_str = currency.accountAddressAsString(miner_acc3); AccountBase rv_acc; rv_acc.generate(); AccountBase rv_acc2; rv_acc2.generate(); Transaction tx_mine_1; currency.constructMinerTx(BLOCK_MAJOR_VERSION_1, 0, 0, 0, 10, 0, miner_acc1.getAccountKeys().address, tx_mine_1); Transaction tx_mine_2; currency.constructMinerTx(BLOCK_MAJOR_VERSION_1, 0, 0, 0, 0, 0, miner_acc2.getAccountKeys().address, tx_mine_2); Transaction tx_mine_3; currency.constructMinerTx(BLOCK_MAJOR_VERSION_1, 0, 0, 0, 0, 0, miner_acc3.getAccountKeys().address, tx_mine_3); Transaction tx_mine_4; currency.constructMinerTx(BLOCK_MAJOR_VERSION_1, 0, 0, 0, 0, 0, miner_acc4.getAccountKeys().address, tx_mine_4); Transaction tx_mine_5; currency.constructMinerTx(BLOCK_MAJOR_VERSION_1, 0, 0, 0, 0, 0, miner_acc5.getAccountKeys().address, tx_mine_5); Transaction tx_mine_6; currency.constructMinerTx(BLOCK_MAJOR_VERSION_1, 0, 0, 0, 0, 0, miner_acc6.getAccountKeys().address, tx_mine_6); //fill inputs entry typedef TransactionSourceEntry::OutputEntry tx_output_entry; std::vector<TransactionSourceEntry> sources; sources.resize(sources.size()+1); TransactionSourceEntry& src = sources.back(); src.amount = 70368744177663; { tx_output_entry oe; oe.first = 0; oe.second = boost::get<KeyOutput>(tx_mine_1.outputs[0].target).key; src.outputs.push_back(oe); oe.first = 1; oe.second = boost::get<KeyOutput>(tx_mine_2.outputs[0].target).key; src.outputs.push_back(oe); oe.first = 2; oe.second = boost::get<KeyOutput>(tx_mine_3.outputs[0].target).key; src.outputs.push_back(oe); oe.first = 3; oe.second = boost::get<KeyOutput>(tx_mine_4.outputs[0].target).key; src.outputs.push_back(oe); oe.first = 4; oe.second = boost::get<KeyOutput>(tx_mine_5.outputs[0].target).key; src.outputs.push_back(oe); oe.first = 5; oe.second = boost::get<KeyOutput>(tx_mine_6.outputs[0].target).key; src.outputs.push_back(oe); src.realTransactionPublicKey = CryptoNote::getTransactionPublicKeyFromExtra(tx_mine_2.extra); src.realOutput = 1; src.realOutputIndexInTransaction = 0; } //fill outputs entry TransactionDestinationEntry td; td.addr = rv_acc.getAccountKeys().address; td.amount = 69368744177663; std::vector<TransactionDestinationEntry> destinations; destinations.push_back(td); Transaction tx_rc1; bool r = constructTransaction(miner_acc2.getAccountKeys(), sources, destinations, std::vector<uint8_t>(), tx_rc1, 0, logger); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); Crypto::Hash pref_hash = getObjectHash(*static_cast<TransactionPrefix*>(&tx_rc1)); std::vector<const Crypto::PublicKey *> output_keys; output_keys.push_back(&boost::get<KeyOutput>(tx_mine_1.outputs[0].target).key); output_keys.push_back(&boost::get<KeyOutput>(tx_mine_2.outputs[0].target).key); output_keys.push_back(&boost::get<KeyOutput>(tx_mine_3.outputs[0].target).key); output_keys.push_back(&boost::get<KeyOutput>(tx_mine_4.outputs[0].target).key); output_keys.push_back(&boost::get<KeyOutput>(tx_mine_5.outputs[0].target).key); output_keys.push_back(&boost::get<KeyOutput>(tx_mine_6.outputs[0].target).key); r = Crypto::check_ring_signature(pref_hash, boost::get<KeyInput>(tx_rc1.inputs[0]).keyImage, output_keys, &tx_rc1.signatures[0][0]); CHECK_AND_ASSERT_MES(r, false, "failed to check ring signature"); std::vector<size_t> outs; uint64_t money = 0; r = lookup_acc_outs(rv_acc.getAccountKeys(), tx_rc1, getTransactionPublicKeyFromExtra(tx_rc1.extra), outs, money); CHECK_AND_ASSERT_MES(r, false, "failed to lookup_acc_outs"); CHECK_AND_ASSERT_MES(td.amount == money, false, "wrong money amount in new transaction"); money = 0; r = lookup_acc_outs(rv_acc2.getAccountKeys(), tx_rc1, getTransactionPublicKeyFromExtra(tx_rc1.extra), outs, money); CHECK_AND_ASSERT_MES(r, false, "failed to lookup_acc_outs"); CHECK_AND_ASSERT_MES(0 == money, false, "wrong money amount in new transaction"); return true; }
//-------------------------------------------------------------------------------- uint64_t DaemonCommandsHandler::calculatePercent(const CryptoNote::Currency& currency, uint64_t value, uint64_t total) { return static_cast<uint64_t>(100.0 * currency.coin() * static_cast<double>(value) / static_cast<double>(total)); }
bool validateAddress(const std::string& address, const CryptoNote::Currency& currency) { CryptoNote::AccountPublicAddress ignore; return currency.parseAccountAddressString(address, ignore); }
TEST(validate_parse_amount_case, validate_parse_amount) { Logging::LoggerGroup logger; CryptoNote::Currency currency = CryptoNote::CurrencyBuilder(logger).numberOfDecimalPlaces(8).currency(); uint64_t res = 0; bool r = currency.parseAmount("0.0001", res); ASSERT_TRUE(r); ASSERT_EQ(res, 10000); r = currency.parseAmount("100.0001", res); ASSERT_TRUE(r); ASSERT_EQ(res, 10000010000); r = currency.parseAmount("000.0000", res); ASSERT_TRUE(r); ASSERT_EQ(res, 0); r = currency.parseAmount("0", res); ASSERT_TRUE(r); ASSERT_EQ(res, 0); r = currency.parseAmount(" 100.0001 ", res); ASSERT_TRUE(r); ASSERT_EQ(res, 10000010000); r = currency.parseAmount(" 100.0000 ", res); ASSERT_TRUE(r); ASSERT_EQ(res, 10000000000); r = currency.parseAmount(" 100. 0000 ", res); ASSERT_FALSE(r); r = currency.parseAmount("100. 0000", res); ASSERT_FALSE(r); r = currency.parseAmount("100 . 0000", res); ASSERT_FALSE(r); r = currency.parseAmount("100.00 00", res); ASSERT_FALSE(r); r = currency.parseAmount("1 00.00 00", res); ASSERT_FALSE(r); }
void WalletApi::GetOneBlockReward(CryptoNote::Wallet& wallet) { cryptonote::AccountPublicAddress address; ASSERT_TRUE(m_currency.parseAccountAddressString(wallet.getAddress(), address)); generator.getBlockRewardForAddress(address); }
int main(int argc, char* argv[]) { #ifdef WIN32 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif po::options_description desc_general("General options"); command_line::add_arg(desc_general, command_line::arg_help); command_line::add_arg(desc_general, command_line::arg_version); po::options_description desc_params("Wallet options"); command_line::add_arg(desc_params, arg_wallet_file); command_line::add_arg(desc_params, arg_generate_new_wallet); command_line::add_arg(desc_params, arg_password); command_line::add_arg(desc_params, arg_daemon_address); command_line::add_arg(desc_params, arg_daemon_host); command_line::add_arg(desc_params, arg_daemon_port); command_line::add_arg(desc_params, arg_command); command_line::add_arg(desc_params, arg_log_level); command_line::add_arg(desc_params, arg_testnet); Tools::wallet_rpc_server::init_options(desc_params); po::positional_options_description positional_options; positional_options.add(arg_command.name, -1); po::options_description desc_all; desc_all.add(desc_general).add(desc_params); Logging::LoggerManager logManager; Logging::LoggerRef logger(logManager, "simplewallet"); System::Dispatcher dispatcher; po::variables_map vm; bool r = command_line::handle_error_helper(desc_all, [&]() { po::store(command_line::parse_command_line(argc, argv, desc_general, true), vm); if (command_line::get_arg(vm, command_line::arg_help)) { CryptoNote::Currency tmp_currency = CryptoNote::CurrencyBuilder(logManager).currency(); CryptoNote::simple_wallet tmp_wallet(dispatcher, tmp_currency, logManager); std::cout << CRYPTONOTE_NAME << " wallet v" << PROJECT_VERSION_LONG << std::endl; std::cout << "Usage: simplewallet [--wallet-file=<file>|--generate-new-wallet=<file>] [--daemon-address=<host>:<port>] [<COMMAND>]"; std::cout << desc_all << '\n' << tmp_wallet.get_commands_str(); return false; } else if (command_line::get_arg(vm, command_line::arg_version)) { std::cout << CRYPTONOTE_NAME << " wallet v" << PROJECT_VERSION_LONG; return false; } auto parser = po::command_line_parser(argc, argv).options(desc_params).positional(positional_options); po::store(parser.run(), vm); po::notify(vm); return true; }); if (!r) return 1; //set up logging options Level logLevel = DEBUGGING; if (command_line::has_arg(vm, arg_log_level)) { logLevel = static_cast<Level>(command_line::get_arg(vm, arg_log_level)); } logManager.configure(buildLoggerConfiguration(logLevel, Common::ReplaceExtenstion(argv[0], ".log"))); logger(INFO, BRIGHT_WHITE) << CRYPTONOTE_NAME << " wallet v" << PROJECT_VERSION_LONG; CryptoNote::Currency currency = CryptoNote::CurrencyBuilder(logManager). testnet(command_line::get_arg(vm, arg_testnet)).currency(); if (command_line::has_arg(vm, Tools::wallet_rpc_server::arg_rpc_bind_port)) { //runs wallet with rpc interface if (!command_line::has_arg(vm, arg_wallet_file)) { logger(ERROR, BRIGHT_RED) << "Wallet file not set."; return 1; } if (!command_line::has_arg(vm, arg_daemon_address)) { logger(ERROR, BRIGHT_RED) << "Daemon address not set."; return 1; } if (!command_line::has_arg(vm, arg_password)) { logger(ERROR, BRIGHT_RED) << "Wallet password not set."; return 1; } std::string wallet_file = command_line::get_arg(vm, arg_wallet_file); std::string wallet_password = command_line::get_arg(vm, arg_password); std::string daemon_address = command_line::get_arg(vm, arg_daemon_address); std::string daemon_host = command_line::get_arg(vm, arg_daemon_host); uint16_t daemon_port = command_line::get_arg(vm, arg_daemon_port); if (daemon_host.empty()) daemon_host = "localhost"; if (!daemon_port) daemon_port = RPC_DEFAULT_PORT; if (!daemon_address.empty()) { if (!parseUrlAddress(daemon_address, daemon_host, daemon_port)) { logger(ERROR, BRIGHT_RED) << "failed to parse daemon address: " << daemon_address; return 1; } } std::unique_ptr<INode> node(new NodeRpcProxy(daemon_host, daemon_port)); std::promise<std::error_code> errorPromise; std::future<std::error_code> error = errorPromise.get_future(); auto callback = [&errorPromise](std::error_code e) {errorPromise.set_value(e); }; node->init(callback); if (error.get()) { logger(ERROR, BRIGHT_RED) << ("failed to init NodeRPCProxy"); return 1; } std::unique_ptr<IWalletLegacy> wallet(new WalletLegacy(currency, *node.get())); std::string walletFileName; try { walletFileName = ::tryToOpenWalletOrLoadKeysOrThrow(logger, wallet, wallet_file, wallet_password); logger(INFO) << "available balance: " << currency.formatAmount(wallet->actualBalance()) << ", locked amount: " << currency.formatAmount(wallet->pendingBalance()); logger(INFO, BRIGHT_GREEN) << "Loaded ok"; } catch (const std::exception& e) { logger(ERROR, BRIGHT_RED) << "Wallet initialize failed: " << e.what(); return 1; } Tools::wallet_rpc_server wrpc(dispatcher, logManager, *wallet, *node, currency, walletFileName); if (!wrpc.init(vm)) { logger(ERROR, BRIGHT_RED) << "Failed to initialize wallet rpc server"; return 1; } Tools::SignalHandler::install([&wrpc, &wallet] { wrpc.send_stop_signal(); }); logger(INFO) << "Starting wallet rpc server"; wrpc.run(); logger(INFO) << "Stopped wallet rpc server"; try { logger(INFO) << "Storing wallet..."; CryptoNote::WalletHelper::storeWallet(*wallet, walletFileName); logger(INFO, BRIGHT_GREEN) << "Stored ok"; } catch (const std::exception& e) { logger(ERROR, BRIGHT_RED) << "Failed to store wallet: " << e.what(); return 1; } } else { //runs wallet with console interface CryptoNote::simple_wallet wal(dispatcher, currency, logManager); if (!wal.init(vm)) { logger(ERROR, BRIGHT_RED) << "Failed to initialize wallet"; return 1; } std::vector<std::string> command = command_line::get_arg(vm, arg_command); if (!command.empty()) wal.process_command(command); Tools::SignalHandler::install([&wal] { wal.stop(); }); wal.run(); if (!wal.deinit()) { logger(ERROR, BRIGHT_RED) << "Failed to close wallet"; } else { logger(INFO) << "Wallet closed"; } } return 1; //CATCH_ENTRY_L0("main", 1); }
bool test_transaction_generation_and_ring_signature() { Logging::ConsoleLogger logger; CryptoNote::Currency currency = CryptoNote::CurrencyBuilder(logger).currency(); account_base miner_acc1; miner_acc1.generate(); account_base miner_acc2; miner_acc2.generate(); account_base miner_acc3; miner_acc3.generate(); account_base miner_acc4; miner_acc4.generate(); account_base miner_acc5; miner_acc5.generate(); account_base miner_acc6; miner_acc6.generate(); std::string add_str = currency.accountAddressAsString(miner_acc3); account_base rv_acc; rv_acc.generate(); account_base rv_acc2; rv_acc2.generate(); Transaction tx_mine_1; currency.constructMinerTx(0, 0, 0, 10, 0, miner_acc1.get_keys().m_account_address, tx_mine_1); Transaction tx_mine_2; currency.constructMinerTx(0, 0, 0, 0, 0, miner_acc2.get_keys().m_account_address, tx_mine_2); Transaction tx_mine_3; currency.constructMinerTx(0, 0, 0, 0, 0, miner_acc3.get_keys().m_account_address, tx_mine_3); Transaction tx_mine_4; currency.constructMinerTx(0, 0, 0, 0, 0, miner_acc4.get_keys().m_account_address, tx_mine_4); Transaction tx_mine_5; currency.constructMinerTx(0, 0, 0, 0, 0, miner_acc5.get_keys().m_account_address, tx_mine_5); Transaction tx_mine_6; currency.constructMinerTx(0, 0, 0, 0, 0, miner_acc6.get_keys().m_account_address, tx_mine_6); //fill inputs entry typedef tx_source_entry::output_entry tx_output_entry; std::vector<tx_source_entry> sources; sources.resize(sources.size()+1); tx_source_entry& src = sources.back(); src.amount = 70368744177663; { tx_output_entry oe; oe.first = 0; oe.second = boost::get<TransactionOutputToKey>(tx_mine_1.vout[0].target).key; src.outputs.push_back(oe); oe.first = 1; oe.second = boost::get<TransactionOutputToKey>(tx_mine_2.vout[0].target).key; src.outputs.push_back(oe); oe.first = 2; oe.second = boost::get<TransactionOutputToKey>(tx_mine_3.vout[0].target).key; src.outputs.push_back(oe); oe.first = 3; oe.second = boost::get<TransactionOutputToKey>(tx_mine_4.vout[0].target).key; src.outputs.push_back(oe); oe.first = 4; oe.second = boost::get<TransactionOutputToKey>(tx_mine_5.vout[0].target).key; src.outputs.push_back(oe); oe.first = 5; oe.second = boost::get<TransactionOutputToKey>(tx_mine_6.vout[0].target).key; src.outputs.push_back(oe); src.real_out_tx_key = CryptoNote::get_tx_pub_key_from_extra(tx_mine_2); src.real_output = 1; src.real_output_in_tx_index = 0; } //fill outputs entry tx_destination_entry td; td.addr = rv_acc.get_keys().m_account_address; td.amount = 69368744177663; std::vector<tx_destination_entry> destinations; destinations.push_back(td); Transaction tx_rc1; bool r = construct_tx(miner_acc2.get_keys(), sources, destinations, std::vector<uint8_t>(), tx_rc1, 0, logger); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); crypto::hash pref_hash = get_transaction_prefix_hash(tx_rc1); std::vector<const crypto::public_key *> output_keys; output_keys.push_back(&boost::get<TransactionOutputToKey>(tx_mine_1.vout[0].target).key); output_keys.push_back(&boost::get<TransactionOutputToKey>(tx_mine_2.vout[0].target).key); output_keys.push_back(&boost::get<TransactionOutputToKey>(tx_mine_3.vout[0].target).key); output_keys.push_back(&boost::get<TransactionOutputToKey>(tx_mine_4.vout[0].target).key); output_keys.push_back(&boost::get<TransactionOutputToKey>(tx_mine_5.vout[0].target).key); output_keys.push_back(&boost::get<TransactionOutputToKey>(tx_mine_6.vout[0].target).key); r = crypto::check_ring_signature(pref_hash, boost::get<TransactionInputToKey>(tx_rc1.vin[0]).keyImage, output_keys, &tx_rc1.signatures[0][0]); CHECK_AND_ASSERT_MES(r, false, "failed to check ring signature"); std::vector<size_t> outs; uint64_t money = 0; r = lookup_acc_outs(rv_acc.get_keys(), tx_rc1, get_tx_pub_key_from_extra(tx_rc1), outs, money); CHECK_AND_ASSERT_MES(r, false, "failed to lookup_acc_outs"); CHECK_AND_ASSERT_MES(td.amount == money, false, "wrong money amount in new transaction"); money = 0; r = lookup_acc_outs(rv_acc2.get_keys(), tx_rc1, get_tx_pub_key_from_extra(tx_rc1), outs, money); CHECK_AND_ASSERT_MES(r, false, "failed to lookup_acc_outs"); CHECK_AND_ASSERT_MES(0 == money, false, "wrong money amount in new transaction"); return true; }