Пример #1
0
std::pair<bool, std::string> 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, "Empty SigningPubKey."};

    // We don't allow both an sfSigners and an sfTxnSignature.  Both fields
    // being present would indicate that the transaction is signed both ways.
    if (isFieldPresent (sfTxnSignature))
        return {false, "Cannot both single- and multi-sign."};

    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, "Invalid Signers array size."};

    // 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.
    bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig);

    // 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, "Invalid multisigner."};

        // No duplicate signers allowed.
        if (lastAccountID == accountID)
            return {false, "Duplicate Signers not allowed."};

        // Accounts must be in order by account ID.  No duplicates allowed.
        if (lastAccountID > accountID)
            return {false, "Unsorted Signers array."};

        // The next signature must be greater than this one.
        lastAccountID = accountID;

        // Verify the signature.
        bool validSig = false;
        try
        {
            Serializer s = dataStart;
            finishMultiSigningData (accountID, s);

            auto spk = signer.getFieldVL (sfSigningPubKey);

            if (publicKeyType (makeSlice(spk)))
            {
                Blob const signature =
                    signer.getFieldVL (sfTxnSignature);

                validSig = verify (
                    PublicKey (makeSlice(spk)),
                    s.slice(),
                    makeSlice(signature),
                    fullyCanonical);
            }
        }
        catch (std::exception const&)
        {
            // We assume any problem lies with the signature.
            validSig = false;
        }
        if (!validSig)
            return {false, std::string("Invalid signature on account ") +
                toBase58(accountID)  + "."};
    }

    // All signatures verified.
    return {true, ""};
}
Пример #2
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;
}