Merge branch 'pay'

This commit is contained in:
Arthur Britto
2012-06-01 18:04:27 -07:00
10 changed files with 355 additions and 57 deletions

View File

@@ -263,17 +263,21 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
return tenINVALID;
}
//
// Verify transaction is signed properly.
//
// Extract signing key
// Transactions contain a signing key. This allows us to trivially verify a transaction has at least been properly signed
// without going to disk. Each transaction also notes a source account id. This is used to verify that the signing key is
// associated with the account.
// XXX This could be a lot cleaner to prevent unnecessary copying.
NewcoinAddress naPubKey;
NewcoinAddress naSigningPubKey;
naPubKey.setAccountPublic(txn.peekSigningPubKey());
naSigningPubKey.setAccountPublic(txn.peekSigningPubKey());
// check signature
if (!txn.checkSign(naPubKey))
// Consistency: really signed.
if (!txn.checkSign(naSigningPubKey))
{
std::cerr << "applyTransaction: Invalid transaction: bad signature" << std::endl;
return tenINVALID;
@@ -299,6 +303,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
case ttOFFER:
case ttCREDIT_SET:
case ttTRANSIT_SET:
case ttWALLET_ADD:
result = terSUCCESS;
break;
@@ -349,15 +354,46 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
boost::recursive_mutex::scoped_lock sl(mLedger->mLock);
// find source account
// If we are only verifying some transactions, this would be probablistic.
// If are only forwarding, due to resource limitations, we might verifying only some transactions, this would be probablistic.
LedgerStateParms lspRoot = lepNONE;
SLE::pointer sleSrc = mLedger->getAccountRoot(lspRoot, srcAccountID);
if (!sleSrc)
{
std::cerr << str(boost::format("applyTransaction: Delay transaction: source account does not exisit: %s") % txn.getSourceAccount().humanAccountID()) << std::endl;
return terNO_ACCOUNT;
}
// Consistency: Check signature
switch (txn.getTxnType())
{
case ttCLAIM:
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 tenINVALID;
}
break;
default:
if (!sleSrc->getIFieldPresent(sfAuthorizedKey))
{
std::cerr << "applyTransaction: Can not use unclaimed account." << std::endl;
return tenUNCLAIMED;
}
else if (naSigningPubKey.getAccountID() != sleSrc->getIFieldH160(sfAuthorizedKey))
{
std::cerr << "applyTransaction: Not authorized to use account." << std::endl;
return tenBAD_AUTH;
}
break;
}
// deduct the fee, so it's not available during the transaction
// we only write the account back if the transaction succeeds
if (!saCost.isZero())
@@ -390,15 +426,18 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
if (a_seq < t_seq)
{
std::cerr << "applyTransaction: future sequence number" << std::endl;
return terPRE_SEQ;
}
if (mLedger->hasTransaction(txID))
{
std::cerr << "applyTransaction: duplicate sequence number" << std::endl;
return terALREADY;
}
std::cerr << "applyTransaction: past sequence number" << std::endl;
return terPAST_SEQ;
}
else sleSrc->setIFieldU32(sfSequence, t_seq);
@@ -408,6 +447,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
if (t_seq)
{
std::cerr << "applyTransaction: bad sequence for pre-paid transaction" << std::endl;
return terPAST_SEQ;
}
}
@@ -446,6 +486,10 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
result = doTransitSet(txn, accounts);
break;
case ttWALLET_ADD:
result = doWalletAdd(txn, accounts);
break;
default:
result = tenUNKNOWN;
break;
@@ -486,41 +530,23 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction&
std::vector<AffectedAccount>& accounts)
{
std::cerr << "doClaim>" << std::endl;
NewcoinAddress naSigningPubKey;
naSigningPubKey.setAccountPublic(txn.peekSigningPubKey());
uint160 sourceAccountID = naSigningPubKey.getAccountID();
if (sourceAccountID != txn.getSourceAccount().getAccountID())
{
// 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 tenINVALID;
}
LedgerStateParms qry = lepNONE;
SLE::pointer sleDst = accounts[0].second;
if (!sleDst)
{
// Source account does not exist. Could succeed if it was created first.
std::cerr << str(boost::format("doClaim: no such account: %s") % txn.getSourceAccount().humanAccountID()) << std::endl;
return terNO_ACCOUNT;
}
std::cerr << str(boost::format("doClaim: %s") % sleDst->getFullText()) << std::endl;
// Verify not already claimed.
if (sleDst->getIFieldPresent(sfAuthorizedKey))
{
// Source account already claimed.
std::cerr << "doClaim: source already claimed" << std::endl;
return terCLAIMED;
}
//
// Verify claim is authorized for public key.
// 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<unsigned char> vucCipher = txn.getITFieldVL(sfGenerator);
@@ -533,22 +559,24 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction&
if (!naAccountPublic.accountPublicVerify(Serializer::getSHA512Half(vucCipher), vucSignature))
{
std::cerr << "doClaim: bad signature unauthorized claim" << std::endl;
return tenINVALID;
std::cerr << "doClaim: bad signature unauthorized generator claim" << std::endl;
return tenBAD_GEN_AUTH;
}
//
// Verify generator not already in use.
//
uint160 hGeneratorID = naAccountPublic.getAccountID();
uint160 hGeneratorID = naAccountPublic.getAccountID();
qry = lepNONE;
SLE::pointer sleGen = mLedger->getGenerator(qry, hGeneratorID);
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;
}
@@ -588,6 +616,7 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti
std::cerr << "doCreditSet: Invalid transaction: Payment destination account not specifed." << std::endl;
return tenDST_NEEDED;
}
// XXX Might make sense for ripple.
else if (uSrcAccountID == uDstAccountID)
{
std::cerr << "doCreditSet: Invalid transaction: Source account is the same as destination." << std::endl;
@@ -882,6 +911,72 @@ TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransact
return tenINVALID;
}
TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts)
{
std::cerr << "WalletAdd>" << std::endl;
SLE::pointer sleDst = accounts[0].second;
std::cerr << str(boost::format("WalletAdd: %s") % sleDst->getFullText()) << std::endl;
// Verify not already claimed.
if (sleDst->getIFieldPresent(sfAuthorizedKey))
{
std::cerr << "WalletAdd: 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<unsigned char> vucCipher = txn.getITFieldVL(sfGenerator);
std::vector<unsigned char> vucPubKey = txn.getITFieldVL(sfPubKey);
std::vector<unsigned char> vucSignature = txn.getITFieldVL(sfSignature);
NewcoinAddress naAccountPublic;
naAccountPublic.setAccountPublic(vucPubKey);
if (!naAccountPublic.accountPublicVerify(Serializer::getSHA512Half(vucCipher), vucSignature))
{
std::cerr << "WalletAdd: 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 << "WalletAdd: generator already in use" << std::endl;
return tenGEN_IN_USE;
}
//
// Claim the account.
//
// Set the public key needed to use the account.
sleDst->setIFieldH160(sfAuthorizedKey, hGeneratorID);
std::cerr << "WalletAdd<" << std::endl;
return terSUCCESS;
}
TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts)
{
@@ -900,12 +995,6 @@ TransactionEngineResult TransactionEngine::doTake(const SerializedTransaction& t
return tenUNKNOWN;
}
TransactionEngineResult TransactionEngine::doCancel(const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts)
{
return tenUNKNOWN;
}
TransactionEngineResult TransactionEngine::doStore(const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts)
{