bool STTx::checkSign () const { if (boost::indeterminate (sig_state_)) { try { ECDSA const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ? ECDSA::strict : ECDSA::not_strict; RippleAddress n; n.setAccountPublic (getFieldVL (sfSigningPubKey)); sig_state_ = n.accountPublicVerify (getSigningData (*this), getFieldVL (sfTxnSignature), fullyCanonical); } catch (...) { sig_state_ = false; } } assert (!boost::indeterminate (sig_state_)); return static_cast<bool> (sig_state_); }
bool STTx::checkSingleSign () const { // We don't allow both a non-empty sfSigningPubKey and an sfSigners. // That would allow the transaction to be signed two ways. So if both // fields are present the signature is invalid. if (isFieldPresent (sfSigners)) return false; bool ret = false; try { ECDSA const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ? ECDSA::strict : ECDSA::not_strict; RippleAddress n; n.setAccountPublic (getFieldVL (sfSigningPubKey)); ret = n.accountPublicVerify (getSigningData (*this), getFieldVL (sfTxnSignature), fullyCanonical); } catch (...) { // Assume it was a signature failure. ret = false; } return ret; }
bool STTx::checkMultiSign () const { // Make sure the MultiSigners are present. Otherwise they are not // attempting multi-signing and we just have a bad SigningPubKey. if (!isFieldPresent (sfSigners)) return false; STArray const& signers {getFieldArray (sfSigners)}; // There are well known bounds that the number of signers must be within. if (signers.size() < minMultiSigners || signers.size() > maxMultiSigners) return false; // We can ease the computational load inside the loop a bit by // pre-constructing part of the data that we hash. Fill a Serializer // with the stuff that stays constant from signature to signature. Serializer const dataStart {startMultiSigningData (*this)}; // We also use the sfAccount field inside the loop. Get it once. auto const txnAccountID = getAccountID (sfAccount); // Determine whether signatures must be full canonical. ECDSA const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ? ECDSA::strict : ECDSA::not_strict; // Signers must be in sorted order by AccountID. AccountID lastAccountID (beast::zero); for (auto const& signer : signers) { auto const accountID = signer.getAccountID (sfAccount); // The account owner may not multisign for themselves. if (accountID == txnAccountID) return false; // Accounts must be in order by account ID. No duplicates allowed. if (lastAccountID >= accountID) return false; // The next signature must be greater than this one. lastAccountID = accountID; // Verify the signature. bool validSig = false; try { Serializer s = dataStart; finishMultiSigningData (accountID, s); RippleAddress const pubKey = RippleAddress::createAccountPublic ( signer.getFieldVL (sfSigningPubKey)); Blob const signature = signer.getFieldVL (sfTxnSignature); validSig = pubKey.accountPublicVerify ( s.getData(), signature, fullyCanonical); } catch (...) { // We assume any problem lies with the signature. validSig = false; } if (!validSig) return false; } // All signatures verified. return true; }