Example #1
0
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_);
}
Example #2
0
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;
}
Example #3
0
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;
}