diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index e8ae14ec53..2a2fcd0485 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -10,10 +10,6 @@ #include "utils.h" #include "Log.h" -typedef SerializedLedgerEntry SLE; - - - #define DIR_NODE_MAX 32 // We return the uNodeDir so that on delete we can quickly know where the element is mentioned in the directory. @@ -231,6 +227,62 @@ TransactionEngineResult TransactionEngine::dirDelete( } } +TransactionEngineResult TransactionEngine::setAuthorized(const SerializedTransaction& txn, std::vector& accounts, bool bSet) +{ + // + // Verify that submitter knows the private key for the generator. + // Otherwise, people could deny access to generators. + // + + std::vector vucCipher = txn.getITFieldVL(sfGenerator); + std::vector vucPubKey = txn.getITFieldVL(sfPubKey); + std::vector vucSignature = txn.getITFieldVL(sfSignature); + NewcoinAddress naAccountPublic = NewcoinAddress::createAccountPublic(vucPubKey); + + if (!naAccountPublic.accountPublicVerify(Serializer::getSHA512Half(vucCipher), vucSignature)) + { + std::cerr << "createGenerator: bad signature unauthorized generator claim" << std::endl; + + return tenBAD_GEN_AUTH; + } + + // Create generator. + uint160 hGeneratorID = naAccountPublic.getAccountID(); + + LedgerStateParms qry = lepNONE; + SLE::pointer sleGen = mLedger->getGenerator(qry, hGeneratorID); + if (!sleGen) + { + // Create the generator. + sleGen = boost::make_shared(ltGENERATOR_MAP); + + sleGen->setIndex(Ledger::getGeneratorIndex(hGeneratorID)); + sleGen->setIFieldH160(sfGeneratorID, hGeneratorID); + sleGen->setIFieldVL(sfGenerator, vucCipher); + + accounts.push_back(std::make_pair(taaCREATE, sleGen)); + } + else if (!bSet) + { + // Doing a claim. Must set generator. + // Generator is already in use. Regular passphrases limited to one wallet. + std::cerr << "createGenerator: generator already in use" << std::endl; + + return tenGEN_IN_USE; + } + + // Set the public key needed to use the account. + SLE::pointer sleDst = accounts[0].second; + + uint160 uAuthKeyID = bSet + ? hGeneratorID + : txn.getITFieldAccount(sfAuthorizedKey); + + sleDst->setIFieldAccount(sfAuthorizedKey, uAuthKeyID); + + return terSUCCESS; +} + TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn, TransactionEngineParams params) { @@ -287,6 +339,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran switch(txn.getTxnType()) { case ttCLAIM: + case ttPASSWORD_SET: saCost = 0; break; @@ -301,6 +354,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran case ttCREDIT_SET: case ttINVOICE: case ttOFFER: + case ttPASSWORD_FUND: case ttTRANSIT_SET: case ttWALLET_ADD: nothing(); @@ -363,28 +417,60 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran return terNO_ACCOUNT; } - // Consistency: Check signature + // Check if account cliamed. switch (txn.getTxnType()) { case ttCLAIM: - if (naSigningPubKey.getAccountID() != srcAccountID) + if (sleSrc->getIFieldPresent(sfAuthorizedKey)) { - // Signing Pub Key must be for Source Account ID. - std::cerr << "sourceAccountID: " << naSigningPubKey.humanAccountID() << std::endl; - std::cerr << "txn accountID: " << txn.getSourceAccount().humanAccountID() << std::endl; + std::cerr << "applyTransaction: Account already claimed." << std::endl; - return tenINVALID; + return tenCLAIMED; } break; default: if (!sleSrc->getIFieldPresent(sfAuthorizedKey)) { - std::cerr << "applyTransaction: Can not use unclaimed account." << std::endl; + std::cerr << "applyTransaction: Souce is an unclaimed account." << std::endl; return tenUNCLAIMED; } - else if (naSigningPubKey.getAccountID() != sleSrc->getIValueFieldAccount(sfAuthorizedKey).getAccountID()) + break; + } + + // Consistency: Check signature + switch (txn.getTxnType()) + { + case ttCLAIM: + // Transaction's signing public key must be for the source account. + // To prove the master private key made this transaction. + if (naSigningPubKey.getAccountID() != srcAccountID) + { + // Signing Pub Key must be for Source Account ID. + std::cerr << "sourceAccountID: " << naSigningPubKey.humanAccountID() << std::endl; + std::cerr << "txn accountID: " << txn.getSourceAccount().humanAccountID() << std::endl; + + return tenBAD_CLAIM_ID; + } + break; + + case ttPASSWORD_SET: + // Transaction's signing public key must be for the source account. + // To prove the master private key made this transaction. + if (naSigningPubKey.getAccountID() != srcAccountID) + { + // Signing Pub Key must be for Source Account ID. + std::cerr << "sourceAccountID: " << naSigningPubKey.humanAccountID() << std::endl; + std::cerr << "txn accountID: " << txn.getSourceAccount().humanAccountID() << std::endl; + + return tenBAD_SET_ID; + } + break; + + default: + // Verify the transaction's signing public key is the key authorized for signing. + if (naSigningPubKey.getAccountID() != sleSrc->getIValueFieldAccount(sfAuthorizedKey).getAccountID()) { std::cerr << "applyTransaction: Not authorized to use account." << std::endl; @@ -481,6 +567,14 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran result = doOffer(txn, accounts); break; + case ttPASSWORD_FUND: + result = doPasswordFund(txn, accounts, srcAccountID); + break; + + case ttPASSWORD_SET: + result = doPasswordSet(txn, accounts); + break; + case ttPAYMENT: result = doPayment(txn, accounts, srcAccountID); break; @@ -545,13 +639,13 @@ TransactionEngineResult TransactionEngine::doAccountSet(const SerializedTransact if (txFlags & tfUnsetEmailHash) { - std::cerr << "doClaim: unset email hash" << std::endl; + std::cerr << "doAccountSet: unset email hash" << std::endl; sleSrc->makeIFieldAbsent(sfEmailHash); } else if (txn.getITFieldPresent(sfEmailHash)) { - std::cerr << "doClaim: set email hash" << std::endl; + std::cerr << "doAccountSet: set email hash" << std::endl; sleSrc->setIFieldH128(sfEmailHash, txn.getITFieldH128(sfEmailHash)); } @@ -562,13 +656,13 @@ TransactionEngineResult TransactionEngine::doAccountSet(const SerializedTransact if (txFlags & tfUnsetWalletLocator) { - std::cerr << "doClaim: unset wallet locator" << std::endl; + std::cerr << "doAccountSet: unset wallet locator" << std::endl; sleSrc->makeIFieldAbsent(sfWalletLocator); } else if (txn.getITFieldPresent(sfWalletLocator)) { - std::cerr << "doClaim: set wallet locator" << std::endl; + std::cerr << "doAccountSet: set wallet locator" << std::endl; sleSrc->setIFieldH256(sfWalletLocator, txn.getITFieldH256(sfWalletLocator)); } @@ -584,13 +678,13 @@ TransactionEngineResult TransactionEngine::doAccountSet(const SerializedTransact } else if (sleSrc->getIFieldPresent(sfMessageKey)) { - std::cerr << "doClaim: can not change message key" << std::endl; + std::cerr << "doAccountSet: can not change message key" << std::endl; return tenMSG_SET; } else { - std::cerr << "doClaim: set message key" << std::endl; + std::cerr << "doAccountSet: set message key" << std::endl; sleSrc->setIFieldVL(sfMessageKey, txn.getITFieldVL(sfMessageKey)); } @@ -605,71 +699,11 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& { std::cerr << "doClaim>" << std::endl; - SLE::pointer sleDst = accounts[0].second; - - std::cerr << str(boost::format("doClaim: %s") % sleDst->getFullText()) << std::endl; - - // Verify not already claimed. - if (sleDst->getIFieldPresent(sfAuthorizedKey)) - { - std::cerr << "doClaim: source already claimed" << std::endl; - - return terCLAIMED; - } - - // - // Generator ID is based on regular account #0 public key. - // Verify that submitter knows the private key for the generator. - // Otherwise, people could deny access to generators. - // - - std::vector vucCipher = txn.getITFieldVL(sfGenerator); - std::vector vucPubKey = txn.getITFieldVL(sfPubKey); - std::vector vucSignature = txn.getITFieldVL(sfSignature); - NewcoinAddress naAccountPublic = NewcoinAddress::createAccountPublic(vucPubKey); - - if (!naAccountPublic.accountPublicVerify(Serializer::getSHA512Half(vucCipher), vucSignature)) - { - std::cerr << "doClaim: bad signature unauthorized generator claim" << std::endl; - - return tenBAD_GEN_AUTH; - } - - // - // Verify generator not already in use. - // - - uint160 hGeneratorID = naAccountPublic.getAccountID(); - - LedgerStateParms qry = lepNONE; - SLE::pointer sleGen = mLedger->getGenerator(qry, hGeneratorID); - if (sleGen) - { - // Generator is already in use. Regular passphrases limited to one wallet. - std::cerr << "doClaim: generator already in use" << std::endl; - - return tenGEN_IN_USE; - } - - // - // Claim the account. - // - - // Set the public key needed to use the account. - sleDst->setIFieldAccount(sfAuthorizedKey, hGeneratorID); - - // Construct a generator map entry. - sleGen = boost::make_shared(ltGENERATOR_MAP); - - sleGen->setIndex(Ledger::getGeneratorIndex(hGeneratorID)); - sleGen->setIFieldH160(sfGeneratorID, hGeneratorID); - sleGen->setIFieldVL(sfGenerator, vucCipher); - - accounts.push_back(std::make_pair(taaCREATE, sleGen)); + TransactionEngineResult result = setAuthorized(txn, accounts, true); std::cerr << "doClaim<" << std::endl; - return terSUCCESS; + return result; } TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransaction& txn, @@ -771,6 +805,44 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti return terResult; } +TransactionEngineResult TransactionEngine::doPasswordFund(const SerializedTransaction& txn, std::vector& accounts, const uint160& uSrcAccountID) +{ + std::cerr << "doPasswordFund>" << std::endl; + uint160 uDstAccountID = txn.getITFieldAccount(sfDestination); + LedgerStateParms qry = lepNONE; + SLE::pointer sleDst = mLedger->getAccountRoot(qry, uDstAccountID); + if (!sleDst) + { + // Destination account does not exist. + std::cerr << "doPasswordFund: Delay transaction: Destination account does not exist." << std::endl; + + return terSET_MISSING_DST; + } + + bool bSpent = !!(sleDst->getFlags() & lsfPasswordSpent); + if (bSpent) + { + sleDst->clearFlag(lsfPasswordSpent); + + if (uSrcAccountID != uDstAccountID) + accounts.push_back(std::make_pair(taaMODIFY, sleDst)); + } + std::cerr << "doPasswordFund<" << std::endl; + + return terSUCCESS; +} + +TransactionEngineResult TransactionEngine::doPasswordSet(const SerializedTransaction& txn, std::vector& accounts) +{ + std::cerr << "doPasswordSet>" << std::endl; + + TransactionEngineResult result = setAuthorized(txn, accounts, false); + + std::cerr << "doPasswordSet<" << std::endl; + + return result; +} + TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn, std::vector& accounts, const uint160& srcAccountID) diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index aa1b23247e..ea576982b6 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -20,9 +20,12 @@ enum TransactionEngineResult tenDST_IS_SRC, // Destination may not be source. tenBAD_GEN_AUTH, // Not authorized to claim generator. tenBAD_ADD_AUTH, // Not authorized to add account. + tenBAD_CLAIM_ID, // Malformed. + tenBAD_SET_ID, // Malformed. // Invalid: Ledger won't allow. tenUNCLAIMED = -200, // Can not use an unclaimed account. + tenCLAIMED, // Can not claim a previously claimed account. tenBAD_AUTH, // Transaction's public key is not authorized. tenCREATED, // Can't add an already created account. tenMSG_SET, // Can't change a message key. @@ -40,7 +43,6 @@ enum TransactionEngineResult // Might succeed if not conflict is not caused by transaction ordering. terALREADY, // The transaction was already in the ledger terBAD_SEQ, // This sequence number should be zero for prepaid transactions. - terCLAIMED, // Can not claim a previously claimed account. terCREATED, // Can not create a previously created account. terDIR_FULL, // Can not add entry to full dir. terINSUF_FEE_B, // Account balance can't pay fee @@ -56,6 +58,7 @@ enum TransactionEngineResult terPRE_SEQ, // Missing/inapplicable prior transaction terUNFUNDED, // Source account had insufficient balance for transaction. terNO_LINE_NO_ZERO, // Can't zero non-existant line, destination might make it. + terSET_MISSING_DST, // Can't set password, destination missing. }; enum TransactionEngineParams @@ -91,18 +94,23 @@ private: const uint256& uBase, // Key of item. const uint256& uLedgerIndex); // Item being deleted + TransactionEngineResult setAuthorized(const SerializedTransaction& txn, std::vector& accounts, bool bSet); + protected: Ledger::pointer mLedger; TransactionEngineResult doAccountSet(const SerializedTransaction& txn, std::vector& accounts); TransactionEngineResult doClaim(const SerializedTransaction& txn, std::vector& accounts); TransactionEngineResult doCreditSet(const SerializedTransaction& txn, std::vector& accounts, - const uint160& srcAccountID); + const uint160& uSrcAccountID); TransactionEngineResult doDelete(const SerializedTransaction& txn, std::vector& accounts); TransactionEngineResult doInvoice(const SerializedTransaction& txn, std::vector& accounts); TransactionEngineResult doOffer(const SerializedTransaction& txn, std::vector& accounts); + TransactionEngineResult doPasswordFund(const SerializedTransaction& txn, std::vector& accounts, + const uint160& uSrcAccountID); + TransactionEngineResult doPasswordSet(const SerializedTransaction& txn, std::vector& accounts); TransactionEngineResult doPayment(const SerializedTransaction& txn, std::vector& accounts, - const uint160& srcAccountID); + const uint160& uSrcAccountID); TransactionEngineResult doStore(const SerializedTransaction& txn, std::vector& accounts); TransactionEngineResult doTake(const SerializedTransaction& txn, std::vector& accounts); TransactionEngineResult doTransitSet(const SerializedTransaction& txn, std::vector& accounts);