Work on Create and Payment transactions.

This commit is contained in:
Arthur Britto
2012-05-16 17:17:35 -07:00
parent adf4883fa9
commit e4d5d1c725
6 changed files with 185 additions and 80 deletions

View File

@@ -57,8 +57,9 @@ Transaction::Transaction(
const NewcoinAddress& naSourceAccount, const NewcoinAddress& naSourceAccount,
uint32 uSeq, uint32 uSeq,
uint64 uFee, uint64 uFee,
uint32 uSourceTag) : uint32 uSourceTag,
mInLedger(0), mStatus(NEW) uint32 uLedger) :
mStatus(NEW)
{ {
mAccountFrom = naSourceAccount; mAccountFrom = naSourceAccount;
mFromPubKey = naPublicKey; mFromPubKey = naPublicKey;
@@ -78,6 +79,12 @@ Transaction::Transaction(
mTransaction->makeITFieldPresent(sfSourceTag); mTransaction->makeITFieldPresent(sfSourceTag);
mTransaction->setITFieldU32(sfSourceTag, uSourceTag); mTransaction->setITFieldU32(sfSourceTag, uSourceTag);
} }
if (uLedger)
{
mTransaction->makeITFieldPresent(sfTargetLedger);
mTransaction->setITFieldU32(sfTargetLedger, uLedger);
}
} }
bool Transaction::sign(const NewcoinAddress& naAccountPrivate) bool Transaction::sign(const NewcoinAddress& naAccountPrivate)
@@ -148,6 +155,41 @@ Transaction::pointer Transaction::sharedClaim(
return tResult->setClaim(naPrivateKey, vucGenerator, vucPubKey, vucSignature); return tResult->setClaim(naPrivateKey, vucGenerator, vucPubKey, vucSignature);
} }
//
// Create
//
Transaction::pointer Transaction::setCreate(
const NewcoinAddress& naPrivateKey,
const NewcoinAddress& naCreateAccountID,
uint64 uFund)
{
mTransaction->setITFieldU32(sfFlags, tfCreateAccount);
mTransaction->setITFieldAccount(sfDestination, naCreateAccountID);
mTransaction->setITFieldU64(sfAmount, uFund);
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedCreate(
const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey,
const NewcoinAddress& naSourceAccount,
uint32 uSeq,
uint64 uFee,
uint32 uSourceTag,
uint32 uLedger,
const NewcoinAddress& naCreateAccountID,
uint64 uFund)
{
pointer tResult = boost::make_shared<Transaction>(ttPAYMENT,
naPublicKey, naSourceAccount,
uSeq, uFee, uSourceTag, uLedger);
return tResult->setCreate(naPrivateKey, naCreateAccountID, uFund);
}
// //
// Payment // Payment
// //
@@ -155,18 +197,11 @@ Transaction::pointer Transaction::sharedClaim(
Transaction::pointer Transaction::setPayment( Transaction::pointer Transaction::setPayment(
const NewcoinAddress& naPrivateKey, const NewcoinAddress& naPrivateKey,
const NewcoinAddress& toAccount, const NewcoinAddress& toAccount,
uint64 uAmount, uint64 uAmount)
uint32 ledger)
{ {
mTransaction->setITFieldAccount(sfDestination, toAccount); mTransaction->setITFieldAccount(sfDestination, toAccount);
mTransaction->setITFieldU64(sfAmount, uAmount); mTransaction->setITFieldU64(sfAmount, uAmount);
if (ledger != 0)
{
mTransaction->makeITFieldPresent(sfTargetLedger);
mTransaction->setITFieldU32(sfTargetLedger, ledger);
}
sign(naPrivateKey); sign(naPrivateKey);
return shared_from_this(); return shared_from_this();
@@ -178,15 +213,15 @@ Transaction::pointer Transaction::sharedPayment(
uint32 uSeq, uint32 uSeq,
uint64 uFee, uint64 uFee,
uint32 uSourceTag, uint32 uSourceTag,
uint32 uLedger,
const NewcoinAddress& toAccount, const NewcoinAddress& toAccount,
uint64 uAmount, uint64 uAmount)
uint32 ledger)
{ {
pointer tResult = boost::make_shared<Transaction>(ttMAKE_PAYMENT, pointer tResult = boost::make_shared<Transaction>(ttPAYMENT,
naPublicKey, naSourceAccount, naPublicKey, naSourceAccount,
uSeq, uFee, uSourceTag); uSeq, uFee, uSourceTag, uLedger);
return tResult->setPayment(naPrivateKey, toAccount, uAmount, ledger); return tResult->setPayment(naPrivateKey, toAccount, uAmount);
} }
// //

View File

@@ -47,18 +47,22 @@ private:
SerializedTransaction::pointer mTransaction; SerializedTransaction::pointer mTransaction;
Transaction::pointer setPayment(
const NewcoinAddress& naPrivateKey,
const NewcoinAddress& toAccount,
uint64 uAmount,
uint32 ledger);
Transaction::pointer setClaim( Transaction::pointer setClaim(
const NewcoinAddress& naPrivateKey, const NewcoinAddress& naPrivateKey,
const std::vector<unsigned char>& vucGenerator, const std::vector<unsigned char>& vucGenerator,
const std::vector<unsigned char>& vucPubKey, const std::vector<unsigned char>& vucPubKey,
const std::vector<unsigned char>& vucSignature); const std::vector<unsigned char>& vucSignature);
Transaction::pointer setCreate(
const NewcoinAddress& naPrivateKey,
const NewcoinAddress& naCreateAccountID,
uint64 uFund);
Transaction::pointer setPayment(
const NewcoinAddress& naPrivateKey,
const NewcoinAddress& toAccount,
uint64 uAmount);
public: public:
Transaction(const SerializedTransaction::pointer st, bool bValidate); Transaction(const SerializedTransaction::pointer st, bool bValidate);
@@ -66,22 +70,14 @@ public:
Transaction( Transaction(
TransactionType ttKind, TransactionType ttKind,
const NewcoinAddress& naPublicKey, const NewcoinAddress& naPublicKey, // To prove transaction is consistent and authorized.
const NewcoinAddress& naSourceAccount, const NewcoinAddress& naSourceAccount, // To identify the paying account.
uint32 uSeq, uint32 uSeq, // To order transactions.
uint64 uFee, uint64 uFee, // Transaction fee.
uint32 uSourceTag); uint32 uSourceTag, // User call back value.
uint32 uLedger=0);
static Transaction::pointer sharedPayment(
const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey,
const NewcoinAddress& naSourceAccount,
uint32 uSeq,
uint64 uFee,
uint32 uSourceTag,
const NewcoinAddress& toAccount,
uint64 uAmount,
uint32 ledger);
// Claim a wallet.
static Transaction::pointer sharedClaim( static Transaction::pointer sharedClaim(
const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey,
const NewcoinAddress& naSourceAccount, const NewcoinAddress& naSourceAccount,
@@ -89,6 +85,29 @@ public:
const std::vector<unsigned char>& vucGenerator, const std::vector<unsigned char>& vucGenerator,
const std::vector<unsigned char>& vucPubKey, const std::vector<unsigned char>& vucPubKey,
const std::vector<unsigned char>& vucSignature); const std::vector<unsigned char>& vucSignature);
// Create an account.
static Transaction::pointer sharedCreate(
const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey,
const NewcoinAddress& naSourceAccount,
uint32 uSeq,
uint64 uFee,
uint32 uSourceTag,
uint32 uLedger,
const NewcoinAddress& naCreateAccountID, // Account to create.
uint64 uFund); // Initial funds in XNC.
// Make a payment.
static Transaction::pointer sharedPayment(
const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey,
const NewcoinAddress& naSourceAccount,
uint32 uSeq,
uint64 uFee,
uint32 uSourceTag,
uint32 uLedger,
const NewcoinAddress& toAccount,
uint64 uAmount);
#if 0 #if 0
Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toID, Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toID,
CKey::pointer pubKey, uint64 uAmount, uint64 fee, uint32 fromSeq, uint32 fromLedger, CKey::pointer pubKey, uint64 uAmount, uint64 fee, uint32 fromSeq, uint32 fromLedger,

View File

@@ -29,7 +29,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
// check signature // check signature
if (!txn.checkSign(naPubKey)) if (!txn.checkSign(naPubKey))
{ {
std::cerr << "applyTransaction: invalid signature" << std::endl; std::cerr << "applyTransaction: Invalid transaction: bad signature" << std::endl;
return tenINVALID; return tenINVALID;
} }
@@ -42,19 +42,19 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
bPrepaid = true; bPrepaid = true;
break; break;
case ttMAKE_PAYMENT: case ttPAYMENT:
case ttINVOICE: case ttINVOICE:
case ttEXCHANGE_OFFER: case ttEXCHANGE_OFFER:
result = terSUCCESS; result = terSUCCESS;
break; break;
case ttINVALID: case ttINVALID:
std::cerr << "applyTransaction: ttINVALID transaction type" << std::endl; std::cerr << "applyTransaction: Invalid transaction: ttINVALID transaction type" << std::endl;
result = tenINVALID; result = tenINVALID;
break; break;
default: default:
std::cerr << "applyTransaction: unknown transaction type" << std::endl; std::cerr << "applyTransaction: Invalid transaction: unknown transaction type" << std::endl;
result = tenUNKNOWN; result = tenUNKNOWN;
break; break;
} }
@@ -85,9 +85,9 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
} }
} }
// get source account ID // Get source account ID.
uint160 srcAccount = txn.getSourceAccount().getAccountID(); uint160 srcAccountID = txn.getSourceAccount().getAccountID();
if (!srcAccount) if (!srcAccountID)
{ {
std::cerr << "applyTransaction: bad source id" << std::endl; std::cerr << "applyTransaction: bad source id" << std::endl;
return tenINVALID; return tenINVALID;
@@ -98,10 +98,10 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
// find source account // find source account
// If we are only verifying some transactions, this would be probablistic. // If we are only verifying some transactions, this would be probablistic.
LedgerStateParms qry = lepNONE; LedgerStateParms qry = lepNONE;
SerializedLedgerEntry::pointer src = mLedger->getAccountRoot(qry, srcAccount); SerializedLedgerEntry::pointer src = mLedger->getAccountRoot(qry, srcAccountID);
if (!src) if (!src)
{ {
std::cerr << str(boost::format("applyTransaction: no such account: %s") % txn.getSourceAccount().humanAccountID()) << std::endl; std::cerr << str(boost::format("applyTransaction: Delay transaction: source account does not exisit: %s") % txn.getSourceAccount().humanAccountID()) << std::endl;
return terNO_ACCOUNT; return terNO_ACCOUNT;
} }
@@ -109,15 +109,15 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
// we only write the account back if the transaction succeeds // we only write the account back if the transaction succeeds
if (txnFee) if (txnFee)
{ {
uint64 balance = src->getIFieldU64(sfBalance); uint64 uSrcBalance = src->getIFieldU64(sfBalance);
if (balance < txnFee) if (uSrcBalance < txnFee)
{ {
std::cerr << "applyTransaction: insufficent balance" << std::endl; std::cerr << "applyTransaction: Delay transaction: insufficent balance" << std::endl;
return terINSUF_FEE_B; return terINSUF_FEE_B;
} }
src->setIFieldU64(sfBalance, balance - txnFee); src->setIFieldU64(sfBalance, uSrcBalance - txnFee);
} }
// Validate sequence // Validate sequence
@@ -169,8 +169,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
result = doClaim(txn, accounts); result = doClaim(txn, accounts);
break; break;
case ttMAKE_PAYMENT: case ttPAYMENT:
result = doPayment(txn, accounts); result = doPayment(txn, accounts, srcAccountID);
break; break;
case ttINVOICE: case ttINVOICE:
@@ -308,43 +308,82 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction&
} }
TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn, TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts) std::vector<AffectedAccount>& accounts,
uint160 srcAccountID)
{ {
uint32 txFlags = txn.getFlags(); uint32 txFlags = txn.getFlags();
uint160 destAccount = txn.getITFieldAccount(sfDestination); uint160 dstAccountID = txn.getITFieldAccount(sfDestination);
// Does the destination account exist? // Does the destination account exist?
if (!destAccount) return tenINVALID; if (!dstAccountID)
{
std::cerr << "doPayment: Invalid transaction: Payment destination account not specifed." << std::endl;
return tenINVALID;
}
else if (srcAccountID == dstAccountID)
{
std::cerr << "doPayment: Invalid transaction: Source account is the same as destination." << std::endl;
return tenINVALID;
}
bool bCreate = !(txFlags & tfCreateAccount);
uint160 currency;
if (txn.getITFieldPresent(sfCurrency))
currency = txn.getITFieldH160(sfCurrency);
// XXX No XNC don't allow currency.
LedgerStateParms qry = lepNONE; LedgerStateParms qry = lepNONE;
// FIXME: If this transfer is to the same account, bad things will happen SerializedLedgerEntry::pointer dest = mLedger->getAccountRoot(qry, dstAccountID);
SerializedLedgerEntry::pointer dest = mLedger->getAccountRoot(qry, destAccount);
if (!dest) if (!dest)
{ // can this transaction create an account {
if ((txFlags & 0x00010000) == 0) // no // Destination account does not exist.
if (bCreate && !!currency)
{
std::cerr << "doPayment: Invalid transaction: Create account may only fund XBC." << std::endl;
return tenCREATEXNC;
}
else if (!bCreate)
{
std::cerr << "doPayment: Delay transaction: Destination account does not exist." << std::endl;
return terNO_TARGET; return terNO_TARGET;
}
// Create the account.
dest = boost::make_shared<SerializedLedgerEntry>(ltACCOUNT_ROOT); dest = boost::make_shared<SerializedLedgerEntry>(ltACCOUNT_ROOT);
dest->setIndex(Ledger::getAccountRootIndex(destAccount));
dest->setIFieldAccount(sfAccount, destAccount); dest->setIndex(Ledger::getAccountRootIndex(dstAccountID));
dest->setIFieldAccount(sfAccount, dstAccountID);
dest->setIFieldU32(sfSequence, 1); dest->setIFieldU32(sfSequence, 1);
accounts.push_back(std::make_pair(taaCREATE, dest)); accounts.push_back(std::make_pair(taaCREATE, dest));
} }
else accounts.push_back(std::make_pair(taaMODIFY, dest)); // Destination exists.
else if (bCreate)
uint64 amount = txn.getITFieldU64(sfAmount);
uint160 currency;
if(txn.getITFieldPresent(sfCurrency))
currency = txn.getITFieldH160(sfCurrency);
bool native = !!currency;
if (native)
{ {
uint64 balance = accounts[0].second->getIFieldU64(sfBalance); std::cerr << "doPayment: Invalid transaction: Account already created." << std::endl;
if (balance < amount) return terUNFUNDED; return tenCREATED;
accounts[0].second->setIFieldU64(sfBalance, balance - amount); }
accounts[1].second->setIFieldU64(sfBalance, accounts[1].second->getIFieldU64(sfBalance) + amount); else
{
accounts.push_back(std::make_pair(taaMODIFY, dest));
}
uint64 uAmount = txn.getITFieldU64(sfAmount);
if (!currency)
{
uint64 uSrcBalance = accounts[0].second->getIFieldU64(sfBalance);
if (uSrcBalance < uAmount)
{
std::cerr << "doPayment: Delay transaction: Insufficent funds." << std::endl;
return terUNFUNDED;
}
accounts[0].second->setIFieldU64(sfBalance, uSrcBalance - uAmount);
accounts[1].second->setIFieldU64(sfBalance, accounts[1].second->getIFieldU64(sfBalance) + uAmount);
} }
else else
{ {

View File

@@ -13,9 +13,17 @@
enum TransactionEngineResult enum TransactionEngineResult
{ {
// tenCAN_NEVER_SUCCEED = <0 // tenCAN_NEVER_SUCCEED = <0
tenGEN_IN_USE = -100, // Generator already in use.
// Malformed
tenGEN_IN_USE = -300, // Generator already in use.
tenCREATEXNC, // Can not specify non XNC for Create.
// Not possible due to ledger database.
tenCREATED = -200, // Can not create a previously created account.
tenCLAIMED, // Can not claim a previously claimed account. tenCLAIMED, // Can not claim a previously claimed account.
tenFAILED, // Something broke horribly
// Other
tenFAILED = -100, // Something broke horribly
tenUNKNOWN, // The transactions requires logic not implemented yet tenUNKNOWN, // The transactions requires logic not implemented yet
tenINSUF_FEE_P, // fee totally insufficient tenINSUF_FEE_P, // fee totally insufficient
tenINVALID, // The transaction is ill-formed tenINVALID, // The transaction is ill-formed
@@ -63,7 +71,8 @@ protected:
TransactionEngineResult doDelete(const SerializedTransaction&, std::vector<AffectedAccount>&); TransactionEngineResult doDelete(const SerializedTransaction&, std::vector<AffectedAccount>&);
TransactionEngineResult doInvoice(const SerializedTransaction&, std::vector<AffectedAccount>&); TransactionEngineResult doInvoice(const SerializedTransaction&, std::vector<AffectedAccount>&);
TransactionEngineResult doOffer(const SerializedTransaction&, std::vector<AffectedAccount>&); TransactionEngineResult doOffer(const SerializedTransaction&, std::vector<AffectedAccount>&);
TransactionEngineResult doPayment(const SerializedTransaction&, std::vector<AffectedAccount>&); TransactionEngineResult doPayment(const SerializedTransaction&, std::vector<AffectedAccount>&,
uint160 srcAccountID);
TransactionEngineResult doStore(const SerializedTransaction&, std::vector<AffectedAccount>&); TransactionEngineResult doStore(const SerializedTransaction&, std::vector<AffectedAccount>&);
TransactionEngineResult doTake(const SerializedTransaction&, std::vector<AffectedAccount>&); TransactionEngineResult doTake(const SerializedTransaction&, std::vector<AffectedAccount>&);

View File

@@ -5,7 +5,7 @@
TransactionFormat InnerTxnFormats[]= TransactionFormat InnerTxnFormats[]=
{ {
{ "MakePayment", ttMAKE_PAYMENT, { { "Payment", ttPAYMENT, {
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
{ S_FIELD(Destination), STI_ACCOUNT, SOE_REQUIRED, 0 }, { S_FIELD(Destination), STI_ACCOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Amount), STI_AMOUNT, SOE_REQUIRED, 0 }, { S_FIELD(Amount), STI_AMOUNT, SOE_REQUIRED, 0 },

View File

@@ -6,7 +6,7 @@
enum TransactionType enum TransactionType
{ {
ttINVALID = -1, ttINVALID = -1,
ttMAKE_PAYMENT = 0, ttPAYMENT = 0,
ttCLAIM = 1, ttCLAIM = 1,
ttINVOICE = 2, ttINVOICE = 2,
ttEXCHANGE_OFFER = 3 ttEXCHANGE_OFFER = 3
@@ -31,6 +31,9 @@ const int TransactionIFee = 5;
const int TransactionMinLen=32; const int TransactionMinLen=32;
const int TransactionMaxLen=1048576; const int TransactionMaxLen=1048576;
// Transaction flags.
const uint32 tfCreateAccount = 0x00010000;
extern TransactionFormat InnerTxnFormats[]; extern TransactionFormat InnerTxnFormats[];
extern TransactionFormat* getTxnFormat(TransactionType t); extern TransactionFormat* getTxnFormat(TransactionType t);
#endif #endif