KeyPair generateKeysFromSeed (KeyType type, RippleAddress const& seed) { KeyPair result; if (! seed.isSet()) { return result; } if (type == KeyType::secp256k1) { RippleAddress generator = RippleAddress::createGeneratorPublic (seed); result.secretKey.setAccountPrivate (generator, seed, 0); result.publicKey.setAccountPublic (generator, 0); } else if (type == KeyType::ed25519) { uint256 secretkey = keyFromSeed (seed.getSeed()); Blob ed25519_key (33); ed25519_key[0] = 0xED; assert (secretkey.size() + 1 == ed25519_key.size()); memcpy (&ed25519_key[1], secretkey.data(), secretkey.size()); result.secretKey.setAccountPrivate (ed25519_key); ed25519_publickey (secretkey.data(), &ed25519_key[1]); result.publicKey.setAccountPublic (ed25519_key); secretkey.zero(); // security erase } else { assert (false); // not reached } return result; }
TER AccountSetTransactor::doApply () { std::uint32_t const uTxFlags = mTxn.getFlags (); std::uint32_t const uFlagsIn = mTxnAccount->getFieldU32 (sfFlags); std::uint32_t uFlagsOut = uFlagsIn; std::uint32_t const uSetFlag = mTxn.getFieldU32 (sfSetFlag); std::uint32_t const uClearFlag = mTxn.getFieldU32 (sfClearFlag); // legacy AccountSet flags bool bSetRequireDest = (uTxFlags & TxFlag::requireDestTag) || (uSetFlag == asfRequireDest); bool bClearRequireDest = (uTxFlags & tfOptionalDestTag) || (uClearFlag == asfRequireDest); bool bSetRequireAuth = (uTxFlags & tfRequireAuth) || (uSetFlag == asfRequireAuth); bool bClearRequireAuth = (uTxFlags & tfOptionalAuth) || (uClearFlag == asfRequireAuth); if (uTxFlags & tfAccountSetMask) { m_journal.trace << "Malformed transaction: Invalid flags set."; return temINVALID_FLAG; } // // RequireAuth (if this issuer needs to allow others to hold its IOUs) // if (bSetRequireAuth && bClearRequireAuth) { m_journal.trace << "Malformed transaction: Contradictory flags set."; return temINVALID_FLAG; } if (bSetRequireAuth && !is_bit_set (uFlagsIn, lsfRequireAuth)) { if (!mEngine->view().dirIsEmpty (Ledger::getOwnerDirIndex (mTxnAccountID))) { m_journal.trace << "Retry: Owner directory not empty."; return is_bit_set(mParams, tapRETRY) ? terOWNERS : tecOWNERS; } m_journal.trace << "Set RequireAuth."; uFlagsOut |= lsfRequireAuth; } if (bClearRequireAuth && is_bit_set (uFlagsIn, lsfRequireAuth)) { m_journal.trace << "Clear RequireAuth."; uFlagsOut &= ~lsfRequireAuth; } // // RequireDestTag // if (bSetRequireDest && bClearRequireDest) { m_journal.trace << "Malformed transaction: Contradictory flags set."; return temINVALID_FLAG; } if (bSetRequireDest && !is_bit_set (uFlagsIn, lsfRequireDestTag)) { m_journal.trace << "Set lsfRequireDestTag."; uFlagsOut |= lsfRequireDestTag; } if (bClearRequireDest && is_bit_set (uFlagsIn, lsfRequireDestTag)) { m_journal.trace << "Clear lsfRequireDestTag."; uFlagsOut &= ~lsfRequireDestTag; } // // InflationDest // if ( mTxn.isFieldPresent(sfInflationDest) ) { RippleAddress aInflationDest = mTxn.getFieldAccount(sfInflationDest); if ( !aInflationDest.isSet() ){ m_journal.debug << "AccountSet: Removing inflation destination."; mTxnAccount->makeFieldAbsent(sfInflationDest); } else { if (!mEngine->getLedger()->hasAccount(aInflationDest)) { m_journal.debug << "AccountSet: Inflation destination account doesn't exist."; return temDST_NEEDED; } m_journal.debug << "AccountSet: Set inflation destination account."; mTxnAccount->setFieldAccount(sfInflationDest, aInflationDest); } } // // TransferRate // if (mTxn.isFieldPresent (sfTransferRate)) { std::uint32_t uRate = mTxn.getFieldU32 (sfTransferRate); if (!uRate || uRate == QUALITY_ONE) { m_journal.trace << "unset transfer rate"; mTxnAccount->makeFieldAbsent (sfTransferRate); } else if (uRate > QUALITY_ONE) { m_journal.trace << "set transfer rate"; mTxnAccount->setFieldU32 (sfTransferRate, uRate); } else { m_journal.trace << "bad transfer rate"; return temBAD_TRANSFER_RATE; } } if (uFlagsIn != uFlagsOut) mTxnAccount->setFieldU32 (sfFlags, uFlagsOut); return tesSUCCESS; }
Json::Value walletPropose (Json::Value const& params) { RippleAddress naSeed; RippleAddress naAccount; KeyType type = KeyType::secp256k1; bool const has_key_type = params.isMember (jss::key_type); bool const has_passphrase = params.isMember (jss::passphrase); if (has_key_type) { // `key_type` must be valid if present. type = keyTypeFromString (params[jss::key_type].asString()); if (type == KeyType::invalid) { return rpcError (rpcBAD_SEED); } naSeed = getSeedFromRPC (params); } else if (has_passphrase) { naSeed.setSeedGeneric (params[jss::passphrase].asString()); } else { naSeed.setSeedRandom(); } if (!naSeed.isSet()) { return rpcError(rpcBAD_SEED); } if (type == KeyType::secp256k1) { RippleAddress naGenerator = RippleAddress::createGeneratorPublic (naSeed); naAccount.setAccountPublic (naGenerator, 0); } else if (type == KeyType::ed25519) { uint256 secretkey = keyFromSeed (naSeed.getSeed()); Blob publickey (33); publickey[0] = 0xED; ed25519_publickey (secretkey.data(), &publickey[1]); secretkey.zero(); // security erase naAccount.setAccountPublic (publickey); } else { assert (false); // not reached } Json::Value obj (Json::objectValue); obj[jss::master_seed] = naSeed.humanSeed (); obj[jss::master_seed_hex] = to_string (naSeed.getSeed ()); obj[jss::master_key] = naSeed.humanSeed1751(); obj[jss::account_id] = naAccount.humanAccountID (); obj[jss::public_key] = naAccount.humanAccountPublic(); obj[jss::key_type] = to_string (type); auto acct = naAccount.getAccountPublic(); obj[jss::public_key_hex] = strHex(acct.begin(), acct.size()); return obj; }