mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -83,3 +83,4 @@ public:
|
||||
|
||||
extern Config theConfig;
|
||||
#endif
|
||||
// vim:ts=4
|
||||
|
||||
@@ -205,7 +205,8 @@ Json::Value RPCServer::getGenerator(const uint256& uLedger, const NewcoinAddress
|
||||
Json::Value RPCServer::authorize(const uint256& uLedger,
|
||||
const NewcoinAddress& naSeed, const NewcoinAddress& naSrcAccountID,
|
||||
NewcoinAddress& naAccountPublic, NewcoinAddress& naAccountPrivate,
|
||||
AccountState::pointer& asSrc)
|
||||
AccountState::pointer& asSrc,
|
||||
const NewcoinAddress& naVerifyGenerator)
|
||||
{
|
||||
asSrc = mNetOps->getAccountState(uLedger, naSrcAccountID);
|
||||
if (!asSrc)
|
||||
@@ -225,6 +226,13 @@ Json::Value RPCServer::authorize(const uint256& uLedger,
|
||||
if (!obj.empty())
|
||||
return obj;
|
||||
|
||||
if (naVerifyGenerator.isValid() && naMasterGenerator != naVerifyGenerator)
|
||||
{
|
||||
std::cerr << "naAccountPublic: wrong seed" << std::endl;
|
||||
|
||||
return JSONRPCError(500, "wrong seed");
|
||||
}
|
||||
|
||||
//
|
||||
// Find the index of the account from the master generator, so we can generate the public and private keys.
|
||||
//
|
||||
@@ -322,7 +330,8 @@ Json::Value RPCServer::doAccountInfo(Json::Value ¶ms)
|
||||
{
|
||||
return "invalid params";
|
||||
}
|
||||
else if (!mNetOps->available()) {
|
||||
else if (!mNetOps->available())
|
||||
{
|
||||
return JSONRPCError(503, "network not available");
|
||||
}
|
||||
else
|
||||
@@ -368,7 +377,8 @@ Json::Value RPCServer::doAccountLines(Json::Value ¶ms)
|
||||
{
|
||||
return "invalid params";
|
||||
}
|
||||
else if (!mNetOps->available()) {
|
||||
else if (!mNetOps->available())
|
||||
{
|
||||
return JSONRPCError(503, "network not available");
|
||||
}
|
||||
else
|
||||
@@ -525,16 +535,18 @@ Json::Value RPCServer::doCreditSet(Json::Value& params)
|
||||
{
|
||||
return JSONRPCError(500, "bad src amount/currency");
|
||||
}
|
||||
else if (!mNetOps->available()) {
|
||||
else if (!mNetOps->available())
|
||||
{
|
||||
return JSONRPCError(503, "network not available");
|
||||
}
|
||||
else
|
||||
{
|
||||
NewcoinAddress naMasterGenerator;
|
||||
NewcoinAddress naAccountPublic;
|
||||
NewcoinAddress naAccountPrivate;
|
||||
AccountState::pointer asSrc;
|
||||
uint256 uLedger = mNetOps->getClosedLedger();
|
||||
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, asSrc);
|
||||
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, asSrc, naMasterGenerator);
|
||||
|
||||
if (!obj.empty())
|
||||
return obj;
|
||||
@@ -613,16 +625,18 @@ Json::Value RPCServer::doSend(Json::Value& params)
|
||||
{
|
||||
return JSONRPCError(500, "bad src amount/currency");
|
||||
}
|
||||
else if (!mNetOps->available()) {
|
||||
else if (!mNetOps->available())
|
||||
{
|
||||
return JSONRPCError(503, "network not available");
|
||||
}
|
||||
else
|
||||
{
|
||||
NewcoinAddress naMasterGenerator;
|
||||
NewcoinAddress naAccountPublic;
|
||||
NewcoinAddress naAccountPrivate;
|
||||
AccountState::pointer asSrc;
|
||||
uint256 uLedger = mNetOps->getClosedLedger();
|
||||
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, asSrc);
|
||||
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, asSrc, naMasterGenerator);
|
||||
|
||||
if (!obj.empty())
|
||||
{
|
||||
@@ -704,16 +718,18 @@ Json::Value RPCServer::doTransitSet(Json::Value& params)
|
||||
{
|
||||
return JSONRPCError(500, "source account id needed");
|
||||
}
|
||||
else if (!mNetOps->available()) {
|
||||
else if (!mNetOps->available())
|
||||
{
|
||||
return JSONRPCError(503, "network not available");
|
||||
}
|
||||
else
|
||||
{
|
||||
NewcoinAddress naMasterGenerator;
|
||||
NewcoinAddress naAccountPublic;
|
||||
NewcoinAddress naAccountPrivate;
|
||||
AccountState::pointer asSrc;
|
||||
uint256 uLedger = mNetOps->getClosedLedger();
|
||||
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, asSrc);
|
||||
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, asSrc, naMasterGenerator);
|
||||
|
||||
if (!obj.empty())
|
||||
{
|
||||
@@ -917,7 +933,8 @@ Json::Value RPCServer::doWalletAccounts(Json::Value& params)
|
||||
{
|
||||
return "seed expected";
|
||||
}
|
||||
else if (!mNetOps->available()) {
|
||||
else if (!mNetOps->available())
|
||||
{
|
||||
return JSONRPCError(503, "network not available");
|
||||
}
|
||||
else if ((uLedger = mNetOps->getClosedLedger()).isZero())
|
||||
@@ -955,9 +972,122 @@ Json::Value RPCServer::doWalletAccounts(Json::Value& params)
|
||||
}
|
||||
}
|
||||
|
||||
// wallet_add <regular_seed> <paying_account> <master_seed> [<initial_funds>] [<account_annotation>]
|
||||
Json::Value RPCServer::doWalletAdd(Json::Value& params)
|
||||
{
|
||||
return "not implemented";
|
||||
NewcoinAddress naMasterSeed;
|
||||
NewcoinAddress naRegularSeed;
|
||||
NewcoinAddress naSrcAccountID;
|
||||
STAmount saAmount;
|
||||
std::string sDstCurrency;
|
||||
|
||||
if (params.size() < 3 || params.size() > 5)
|
||||
{
|
||||
return "invalid params";
|
||||
}
|
||||
else if (!naRegularSeed.setFamilySeedGeneric(params[0u].asString()))
|
||||
{
|
||||
return "regular seed expected";
|
||||
}
|
||||
else if (!naSrcAccountID.setAccountID(params[1u].asString()))
|
||||
{
|
||||
return JSONRPCError(500, "source account id needed");
|
||||
}
|
||||
else if (!naMasterSeed.setFamilySeedGeneric(params[2u].asString()))
|
||||
{
|
||||
return "master seed expected";
|
||||
}
|
||||
else if (params.size() >= 4 && !saAmount.setValue(params[3u].asString(), sDstCurrency))
|
||||
{
|
||||
return JSONRPCError(500, "bad dst amount/currency");
|
||||
}
|
||||
else if (!mNetOps->available())
|
||||
{
|
||||
return JSONRPCError(503, "network not available");
|
||||
}
|
||||
else
|
||||
{
|
||||
NewcoinAddress naMasterGenerator;
|
||||
NewcoinAddress naRegularGenerator;
|
||||
|
||||
naMasterGenerator.setFamilyGenerator(naMasterSeed);
|
||||
naRegularGenerator.setFamilyGenerator(naRegularSeed);
|
||||
|
||||
NewcoinAddress naAccountPublic;
|
||||
NewcoinAddress naAccountPrivate;
|
||||
AccountState::pointer asSrc;
|
||||
uint256 uLedger = mNetOps->getClosedLedger();
|
||||
Json::Value obj = authorize(uLedger, naRegularSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, asSrc, naMasterGenerator);
|
||||
|
||||
if (!obj.empty())
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
// XXX Confirm total funds.
|
||||
|
||||
STAmount saSrcBalance = asSrc->getBalance();
|
||||
|
||||
if (saSrcBalance < theConfig.FEE_CREATE)
|
||||
{
|
||||
return JSONRPCError(500, "insufficent funds");
|
||||
}
|
||||
else
|
||||
{
|
||||
NewcoinAddress naNewAccountPublic;
|
||||
NewcoinAddress naNewAccountPrivate;
|
||||
NewcoinAddress naAuthKeyID;
|
||||
uint160 uAuthKeyID;
|
||||
AccountState::pointer asNew;
|
||||
std::vector<unsigned char> vucSignature;
|
||||
bool bAgain = true;
|
||||
int iIndex = -1;
|
||||
|
||||
// Find an unmade account.
|
||||
do {
|
||||
++iIndex;
|
||||
naNewAccountPublic.setAccountPublic(naMasterGenerator, iIndex);
|
||||
|
||||
asNew = mNetOps->getAccountState(uLedger, naNewAccountPublic);
|
||||
if (!asNew)
|
||||
bAgain = false;
|
||||
} while (bAgain);
|
||||
|
||||
// XXX Have a maximum number of accounts per wallet?
|
||||
|
||||
// Determine corrisponding master private key.
|
||||
naNewAccountPrivate.setAccountPrivate(naMasterGenerator, naMasterSeed, iIndex);
|
||||
|
||||
// Determine new accounts authorized regular key.
|
||||
naAuthKeyID.setAccountPublic(naRegularGenerator, iIndex);
|
||||
|
||||
uAuthKeyID = naAuthKeyID.getAccountID();
|
||||
|
||||
// Sign anything (naAuthKeyID) to prove we know new master private key.
|
||||
naNewAccountPrivate.accountPrivateSign(Serializer::getSHA512Half(uAuthKeyID.begin(), uAuthKeyID.size()), vucSignature);
|
||||
|
||||
Transaction::pointer trans = Transaction::sharedWalletAdd(
|
||||
naAccountPublic, naAccountPrivate,
|
||||
naSrcAccountID,
|
||||
asSrc->getSeq(),
|
||||
theConfig.FEE_CREATE,
|
||||
0, // YYY No source tag
|
||||
saAmount,
|
||||
naAuthKeyID,
|
||||
naNewAccountPublic,
|
||||
vucSignature);
|
||||
|
||||
(void) mNetOps->processTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
obj["srcAccountID"] = naSrcAccountID.humanAccountID();
|
||||
obj["newAccountID"] = naNewAccountPublic.humanAccountID();
|
||||
obj["amount"] = saAmount.getText();
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wallet_claim <master_seed> <regular_seed> [<source_tag>] [<account_annotation>]
|
||||
@@ -1013,12 +1143,13 @@ Json::Value RPCServer::doWalletClaim(Json::Value& params)
|
||||
naRegular0Public.setAccountPublic(naRegularGenerator, 0);
|
||||
naRegular0Private.setAccountPrivate(naRegularGenerator, naRegularSeed, 0);
|
||||
|
||||
// hash of regular account #reserved public key.
|
||||
// Hash of regular account #0 public key.
|
||||
uint160 uGeneratorID = naRegular0Public.getAccountID();
|
||||
std::vector<unsigned char> vucGeneratorCipher = naRegular0Private.accountPrivateEncrypt(naRegular0Public, naMasterGenerator.getFamilyGenerator());
|
||||
std::vector<unsigned char> vucGeneratorSig;
|
||||
|
||||
// XXX Check result.
|
||||
// Prove that we have the corrisponding private key to the generator id. So, we can get the generator id.
|
||||
naRegular0Private.accountPrivateSign(Serializer::getSHA512Half(vucGeneratorCipher), vucGeneratorSig);
|
||||
|
||||
Transaction::pointer trns = Transaction::sharedClaim(
|
||||
@@ -1078,7 +1209,8 @@ Json::Value RPCServer::doWalletCreate(Json::Value& params)
|
||||
{
|
||||
return "create account id needed";
|
||||
}
|
||||
else if (!mNetOps->available()) {
|
||||
else if (!mNetOps->available())
|
||||
{
|
||||
// We require access to the paying account's sequence number and key information.
|
||||
return JSONRPCError(503, "network not available");
|
||||
}
|
||||
@@ -1095,11 +1227,12 @@ Json::Value RPCServer::doWalletCreate(Json::Value& params)
|
||||
// Trying to build:
|
||||
// peer_wallet_create <paying_account> <paying_signature> <account_id> [<initial_funds>] [<annotation>]
|
||||
|
||||
NewcoinAddress naMasterGenerator;
|
||||
NewcoinAddress naAccountPublic;
|
||||
NewcoinAddress naAccountPrivate;
|
||||
AccountState::pointer asSrc;
|
||||
uint256 uLedger = mNetOps->getClosedLedger();
|
||||
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, asSrc);
|
||||
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, asSrc, naMasterGenerator);
|
||||
|
||||
STAmount saSrcBalance = asSrc->getBalance();
|
||||
STAmount saInitialFunds = (params.size() < 4) ? 0 : boost::lexical_cast<uint64>(params[3u].asString());
|
||||
|
||||
@@ -42,7 +42,8 @@ private:
|
||||
Json::Value getGenerator(const uint256& uLedger, const NewcoinAddress& naSeed, NewcoinAddress& naMasterGenerator);
|
||||
Json::Value authorize(const uint256& uLedger, const NewcoinAddress& naSeed, const NewcoinAddress& naSrcAccountID,
|
||||
NewcoinAddress& naAccountPublic, NewcoinAddress& naAccountPrivate,
|
||||
AccountState::pointer& asSrc);
|
||||
AccountState::pointer& asSrc,
|
||||
const NewcoinAddress& naVerifyGenerator);
|
||||
Json::Value accounts(const uint256& uLedger, const NewcoinAddress& naMasterGenerator);
|
||||
|
||||
Json::Value accountFromString(const uint256& uLedger, NewcoinAddress& naAccount, bool& bIndex, const std::string& strIdent, const int iIndex);
|
||||
|
||||
@@ -305,6 +305,45 @@ Transaction::pointer Transaction::sharedTransitSet(
|
||||
return tResult->setTransitSet(naPrivateKey, uTransitRate, uTransitStart, uTransitExpire);
|
||||
}
|
||||
|
||||
//
|
||||
// WalletAdd
|
||||
//
|
||||
|
||||
Transaction::pointer Transaction::setWalletAdd(
|
||||
const NewcoinAddress& naPrivateKey,
|
||||
const STAmount& saAmount,
|
||||
const NewcoinAddress& naAuthKeyID,
|
||||
const NewcoinAddress& naNewPubKey,
|
||||
const std::vector<unsigned char>& vucSignature)
|
||||
{
|
||||
mTransaction->setITFieldAmount(sfAmount, saAmount);
|
||||
mTransaction->setITFieldAccount(sfAuthorizedKey, naAuthKeyID);
|
||||
mTransaction->setITFieldVL(sfPubKey, naNewPubKey.getAccountPublic());
|
||||
mTransaction->setITFieldVL(sfSignature, vucSignature);
|
||||
|
||||
sign(naPrivateKey);
|
||||
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
Transaction::pointer Transaction::sharedWalletAdd(
|
||||
const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey,
|
||||
const NewcoinAddress& naSourceAccount,
|
||||
uint32 uSeq,
|
||||
const STAmount& saFee,
|
||||
uint32 uSourceTag,
|
||||
const STAmount& saAmount,
|
||||
const NewcoinAddress& naAuthKeyID,
|
||||
const NewcoinAddress& naNewPubKey,
|
||||
const std::vector<unsigned char>& vucSignature)
|
||||
{
|
||||
pointer tResult = boost::make_shared<Transaction>(ttWALLET_ADD,
|
||||
naPublicKey, naSourceAccount,
|
||||
uSeq, saFee, uSourceTag);
|
||||
|
||||
return tResult->setWalletAdd(naPrivateKey, saAmount, naAuthKeyID, naNewPubKey, vucSignature);
|
||||
}
|
||||
|
||||
//
|
||||
// Misc.
|
||||
//
|
||||
|
||||
@@ -76,6 +76,13 @@ private:
|
||||
uint32 uTransitStart,
|
||||
uint32 uTransitExpire);
|
||||
|
||||
Transaction::pointer setWalletAdd(
|
||||
const NewcoinAddress& naPrivateKey,
|
||||
const STAmount& saAmount,
|
||||
const NewcoinAddress& naAuthKeyID,
|
||||
const NewcoinAddress& naNewPubKey,
|
||||
const std::vector<unsigned char>& vucSignature);
|
||||
|
||||
public:
|
||||
Transaction(const SerializedTransaction::pointer st, bool bValidate);
|
||||
|
||||
@@ -142,6 +149,18 @@ public:
|
||||
uint32 uTransitStart,
|
||||
uint32 uTransitExpire);
|
||||
|
||||
// Add an account to a wallet.
|
||||
static Transaction::pointer sharedWalletAdd(
|
||||
const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey,
|
||||
const NewcoinAddress& naSourceAccount,
|
||||
uint32 uSeq,
|
||||
const STAmount& saFee,
|
||||
uint32 uSourceTag,
|
||||
const STAmount& saAmount, // Initial funds in XNC.
|
||||
const NewcoinAddress& naAuthKeyID, // ID of regular public to auth.
|
||||
const NewcoinAddress& naNewPubKey, // Public key of new account
|
||||
const std::vector<unsigned char>& vucSignature); // Proof know new account's private key.
|
||||
|
||||
bool sign(const NewcoinAddress& naAccountPrivate);
|
||||
bool checkSign() const;
|
||||
void updateID() { mTransactionID=mTransaction->getTransactionID(); }
|
||||
|
||||
@@ -90,6 +90,7 @@ TransactionEngineResult TransactionEngine::dirAdd(
|
||||
std::cerr << "dirAdd: last: " << strHex(uNodeDir) << std::endl;
|
||||
|
||||
sleRoot->setIFieldU64(sfLastNode, uNodeDir);
|
||||
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleRoot));
|
||||
}
|
||||
}
|
||||
@@ -262,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;
|
||||
@@ -298,6 +303,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
||||
case ttOFFER:
|
||||
case ttCREDIT_SET:
|
||||
case ttTRANSIT_SET:
|
||||
case ttWALLET_ADD:
|
||||
result = terSUCCESS;
|
||||
break;
|
||||
|
||||
@@ -348,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())
|
||||
@@ -389,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);
|
||||
@@ -407,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;
|
||||
}
|
||||
}
|
||||
@@ -445,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;
|
||||
@@ -485,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);
|
||||
@@ -532,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;
|
||||
}
|
||||
|
||||
@@ -587,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;
|
||||
@@ -613,16 +643,16 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti
|
||||
SLE::pointer sleRippleState = mLedger->getRippleState(qry, uSrcAccountID, uDstAccountID, uCurrency);
|
||||
if (sleRippleState)
|
||||
{
|
||||
std::cerr << "doCreditSet: Modifying ripple line." << std::endl;
|
||||
|
||||
bAddIndex = !(sleRippleState->getFlags() & uFlags);
|
||||
|
||||
std::cerr << "doCreditSet: Modifying ripple line: bAddIndex=" << bAddIndex << std::endl;
|
||||
|
||||
sleRippleState->setIFieldAmount(bSltD ? sfLowLimit : sfHighLimit, saLimitAmount);
|
||||
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleRippleState));
|
||||
|
||||
if (bAddIndex)
|
||||
sleRippleState->setFlag(uFlags);
|
||||
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleRippleState));
|
||||
}
|
||||
// Line does not exist.
|
||||
else if (saLimitAmount.isZero())
|
||||
@@ -881,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)
|
||||
{
|
||||
@@ -899,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)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,11 @@ enum TransactionEngineResult
|
||||
tenEXPLICITXNC, // XNC is used by default, don't specify it.
|
||||
tenDST_NEEDED, // Destination not specified.
|
||||
tenDST_IS_SRC, // Destination may not be source.
|
||||
tenBAD_GEN_AUTH, // Not authorized to claim generator.
|
||||
|
||||
// Invalid: Ledger won't allow.
|
||||
tenUNCLAIMED = -200, // Can not use an unclaimed account.
|
||||
tenBAD_AUTH, // Transaction's public key is not authorized.
|
||||
|
||||
// Other
|
||||
tenFAILED = -100, // Something broke horribly
|
||||
@@ -86,7 +90,6 @@ private:
|
||||
protected:
|
||||
Ledger::pointer mLedger;
|
||||
|
||||
TransactionEngineResult doCancel(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doClaim(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doCreditSet(const SerializedTransaction&, std::vector<AffectedAccount>&,
|
||||
const uint160& srcAccountID);
|
||||
@@ -98,6 +101,7 @@ protected:
|
||||
TransactionEngineResult doStore(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doTake(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doTransitSet(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doWalletAdd(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
|
||||
public:
|
||||
TransactionEngine() { ; }
|
||||
|
||||
@@ -69,6 +69,16 @@ TransactionFormat InnerTxnFormats[]=
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
},
|
||||
{ "WalletAdd", ttWALLET_ADD, {
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(Amount), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(AuthorizedKey), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(PubKey), STI_VL, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Signature), STI_VL, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
},
|
||||
{ NULL, ttINVALID }
|
||||
};
|
||||
|
||||
|
||||
@@ -8,8 +8,9 @@ enum TransactionType
|
||||
ttINVALID = -1,
|
||||
ttPAYMENT = 0,
|
||||
ttCLAIM = 1,
|
||||
ttINVOICE = 2,
|
||||
ttOFFER = 3,
|
||||
ttWALLET_ADD = 2,
|
||||
ttINVOICE = 3,
|
||||
ttOFFER = 4,
|
||||
ttCREDIT_SET = 20,
|
||||
ttTRANSIT_SET = 21,
|
||||
};
|
||||
|
||||
@@ -53,6 +53,7 @@ void printHelp(const po::options_description& desc)
|
||||
cout << " unl_list" << endl;
|
||||
cout << " unl_reset" << endl;
|
||||
cout << " validation_create [<seed>|<pass_phrase>|<key>]" << endl;
|
||||
cout << " wallet_add <regular_seed> <paying_account> <master_seed> [<initial_funds>] [<account_annotation>]" << endl;
|
||||
cout << " wallet_accounts <seed>" << endl;
|
||||
cout << " wallet_claim <master_seed> <regular_seed> [<source_tag>] [<account_annotation>]" << endl;
|
||||
cout << " wallet_seed [<seed>|<passphrase>|<passkey>]" << endl;
|
||||
|
||||
Reference in New Issue
Block a user