Exemple #1
0
bool Base58::raw_decode (char const* first, char const* last, void* dest,
    std::size_t size, bool checked, Alphabet const& alphabet)
{
    CAutoBN_CTX pctx;
    CBigNum bn58 = 58;
    CBigNum bn = 0;
    CBigNum bnChar;

    // Convert big endian string to bignum
    for (char const* p = first; p != last; ++p)
    {
        int i (alphabet.from_char (*p));
        if (i == -1)
            return false;
        bnChar.setuint ((unsigned int) i);

        int const success (BN_mul (&bn, &bn, &bn58, pctx));

        assert (success);
        (void) success;

        bn += bnChar;
    }

    // Get bignum as little endian data
    Blob vchTmp = bn.getvch ();

    // Trim off sign byte if present
    if (vchTmp.size () >= 2 && vchTmp.end ()[-1] == 0 && vchTmp.end ()[-2] >= 0x80)
        vchTmp.erase (vchTmp.end () - 1);

    char* const out (static_cast <char*> (dest));

    // Count leading zeros
    int nLeadingZeros = 0;
    for (char const* p = first; p!=last && *p==alphabet[0]; p++)
        nLeadingZeros++;

    // Verify that the size is correct
    if (vchTmp.size() + nLeadingZeros != size)
        return false;

    // Fill the leading zeros
    memset (out, 0, nLeadingZeros);

    // Copy little endian data to big endian
    std::reverse_copy (vchTmp.begin (), vchTmp.end (),
        out + nLeadingZeros);

    if (checked)
    {
        char hash4 [4];
        fourbyte_hash256 (hash4, out, size - 4);
        if (memcmp (hash4, out + size - 4, 4) != 0)
            return false;
    }

    return true;
}
Exemple #2
0
bool Base58::decode (const char* psz, Blob& vchRet, Alphabet const& alphabet)
{
    CAutoBN_CTX pctx;
    vchRet.clear ();
    CBigNum bn58 = 58;
    CBigNum bn = 0;
    CBigNum bnChar;

    while (isspace (*psz))
        psz++;

    // Convert big endian string to bignum
    for (const char* p = psz; *p; p++)
    {
        // VFALCO TODO Make this use the inverse table!
        //             Or better yet ditch this and call raw_decode
        //
        const char* p1 = strchr (alphabet.chars(), *p);

        if (p1 == nullptr)
        {
            while (isspace (*p))
                p++;

            if (*p != '\0')
                return false;

            break;
        }

        bnChar.setuint (p1 - alphabet.chars());

        if (!BN_mul (&bn, &bn, &bn58, pctx))
            throw bignum_error ("DecodeBase58 : BN_mul failed");

        bn += bnChar;
    }

    // Get bignum as little endian data
    Blob vchTmp = bn.getvch ();

    // Trim off sign byte if present
    if (vchTmp.size () >= 2 && vchTmp.end ()[-1] == 0 && vchTmp.end ()[-2] >= 0x80)
        vchTmp.erase (vchTmp.end () - 1);

    // Restore leading zeros
    int nLeadingZeros = 0;

    for (const char* p = psz; *p == alphabet.chars()[0]; p++)
        nLeadingZeros++;

    vchRet.assign (nLeadingZeros + vchTmp.size (), 0);

    // Convert little endian data to big endian
    std::reverse_copy (vchTmp.begin (), vchTmp.end (), vchRet.end () - vchTmp.size ());
    return true;
}
Exemple #3
0
inline bool DecodeBase58(const char* psz, vector<unsigned char>& vchRet)
{
    CAutoBN_CTX pctx;
    vchRet.clear();
    CBigNum bn58 = 58;
    CBigNum bn = 0;
    CBigNum bnChar;
    while (isspace(*psz))
        psz++;
    
    // Convert big endian string to bignum
    for (const char* p = psz; *p; p++)
        {
        const char* p1 = strchr(pszBase58, *p);
        if (p1 == NULL)
            {
            while (isspace(*p))
                p++;
            if (*p != '\0')
                return false;
            break;
            }
        bnChar.setulong(p1 - pszBase58);
        if (!BN_mul(&bn, &bn, &bn58, pctx))
            throw bignum_error("DecodeBase58 : BN_mul failed");
        bn += bnChar;
        }
    
    // Get bignum as little endian data
    vector<unsigned char> vchTmp = bn.getvch();
    
    // Trim off sign byte if present
    if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)
        vchTmp.erase(vchTmp.end()-1);
    
    // Restore leading zeros
    int nLeadingZeros = 0;
    for (const char* p = psz; *p == pszBase58[0]; p++)
        nLeadingZeros++;
    vchRet.assign(nLeadingZeros + vchTmp.size(), 0);
    
    // Convert little endian data to big endian
    reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());
    return true;
}
static bool verify(const CBigNum& bignum, const CScriptNum& scriptnum)
{
    return bignum.getvch() == scriptnum.getvch() && bignum.getint() == scriptnum.getint();
}
Exemple #5
0
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
    CAutoBN_CTX pctx;
    CScript::const_iterator pc = script.begin();
    CScript::const_iterator pend = script.end();
    CScript::const_iterator pbegincodehash = script.begin();
    opcodetype opcode;
    valtype vchPushValue;
    vector<bool> vfExec;
    vector<valtype> altstack;
    if (script.size() > 10000)
        return false;
    int nOpCount = 0;


    try
    {
        while (pc < pend)
        {
            bool fExec = !count(vfExec.begin(), vfExec.end(), false);

            //
            // Read instruction
            //
            if (!script.GetOp(pc, opcode, vchPushValue))
                return false;
            if (vchPushValue.size() > 520)
                return false;
            if (opcode > OP_16 && ++nOpCount > 201)
                return false;

            if (opcode == OP_CAT ||
                opcode == OP_SUBSTR ||
                opcode == OP_LEFT ||
                opcode == OP_RIGHT ||
                opcode == OP_INVERT ||
                opcode == OP_AND ||
                opcode == OP_OR ||
                opcode == OP_XOR ||
                opcode == OP_2MUL ||
                opcode == OP_2DIV ||
                opcode == OP_MUL ||
                opcode == OP_DIV ||
                opcode == OP_MOD ||
                opcode == OP_LSHIFT ||
                opcode == OP_RSHIFT)
                return false;

            if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4)
                stack.push_back(vchPushValue);
            else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
            switch (opcode)
            {
                //
                // Push value
                //
                case OP_1NEGATE:
                case OP_1:
                case OP_2:
                case OP_3:
                case OP_4:
                case OP_5:
                case OP_6:
                case OP_7:
                case OP_8:
                case OP_9:
                case OP_10:
                case OP_11:
                case OP_12:
                case OP_13:
                case OP_14:
                case OP_15:
                case OP_16:
                {
                    // ( -- value)
                    CBigNum bn((int)opcode - (int)(OP_1 - 1));
                    stack.push_back(bn.getvch());
                }
                break;


                //
                // Control
                //
                case OP_NOP:
                case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5:
                case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
                break;

                case OP_IF:
                case OP_NOTIF:
                {
                    // <expression> if [statements] [else [statements]] endif
                    bool fValue = false;
                    if (fExec)
                    {
                        if (stack.size() < 1)
                            return false;
                        valtype& vch = stacktop(-1);
                        fValue = CastToBool(vch);
                        if (opcode == OP_NOTIF)
                            fValue = !fValue;
                        popstack(stack);
                    }
                    vfExec.push_back(fValue);
                }
                break;

                case OP_ELSE:
                {
                    if (vfExec.empty())
                        return false;
                    vfExec.back() = !vfExec.back();
                }
                break;

                case OP_ENDIF:
                {
                    if (vfExec.empty())
                        return false;
                    vfExec.pop_back();
                }
                break;

                case OP_VERIFY:
                {
                    // (true -- ) or
                    // (false -- false) and return
                    if (stack.size() < 1)
                        return false;
                    bool fValue = CastToBool(stacktop(-1));
                    if (fValue)
                        popstack(stack);
                    else
                        return false;
                }
                break;

                case OP_RETURN:
                {
                    return false;
                }
                break;


                //
                // Stack ops
                //
                case OP_TOALTSTACK:
                {
                    if (stack.size() < 1)
                        return false;
                    altstack.push_back(stacktop(-1));
                    popstack(stack);
                }
                break;

                case OP_FROMALTSTACK:
                {
                    if (altstack.size() < 1)
                        return false;
                    stack.push_back(altstacktop(-1));
                    popstack(altstack);
                }
                break;

                case OP_2DROP:
                {
                    // (x1 x2 -- )
                    if (stack.size() < 2)
                        return false;
                    popstack(stack);
                    popstack(stack);
                }
                break;

                case OP_2DUP:
                {
                    // (x1 x2 -- x1 x2 x1 x2)
                    if (stack.size() < 2)
                        return false;
                    valtype vch1 = stacktop(-2);
                    valtype vch2 = stacktop(-1);
                    stack.push_back(vch1);
                    stack.push_back(vch2);
                }
                break;

                case OP_3DUP:
                {
                    // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
                    if (stack.size() < 3)
                        return false;
                    valtype vch1 = stacktop(-3);
                    valtype vch2 = stacktop(-2);
                    valtype vch3 = stacktop(-1);
                    stack.push_back(vch1);
                    stack.push_back(vch2);
                    stack.push_back(vch3);
                }
                break;

                case OP_2OVER:
                {
                    // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
                    if (stack.size() < 4)
                        return false;
                    valtype vch1 = stacktop(-4);
                    valtype vch2 = stacktop(-3);
                    stack.push_back(vch1);
                    stack.push_back(vch2);
                }
                break;

                case OP_2ROT:
                {
                    // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
                    if (stack.size() < 6)
                        return false;
                    valtype vch1 = stacktop(-6);
                    valtype vch2 = stacktop(-5);
                    stack.erase(stack.end()-6, stack.end()-4);
                    stack.push_back(vch1);
                    stack.push_back(vch2);
                }
                break;

                case OP_2SWAP:
                {
                    // (x1 x2 x3 x4 -- x3 x4 x1 x2)
                    if (stack.size() < 4)
                        return false;
                    swap(stacktop(-4), stacktop(-2));
                    swap(stacktop(-3), stacktop(-1));
                }
                break;

                case OP_IFDUP:
                {
                    // (x - 0 | x x)
                    if (stack.size() < 1)
                        return false;
                    valtype vch = stacktop(-1);
                    if (CastToBool(vch))
                        stack.push_back(vch);
                }
                break;

                case OP_DEPTH:
                {
                    // -- stacksize
                    CBigNum bn(stack.size());
                    stack.push_back(bn.getvch());
                }
                break;

                case OP_DROP:
                {
                    // (x -- )
                    if (stack.size() < 1)
                        return false;
                    popstack(stack);
                }
                break;

                case OP_DUP:
                {
                    // (x -- x x)
                    if (stack.size() < 1)
                        return false;
                    valtype vch = stacktop(-1);
                    stack.push_back(vch);
                }
                break;

                case OP_NIP:
                {
                    // (x1 x2 -- x2)
                    if (stack.size() < 2)
                        return false;
                    stack.erase(stack.end() - 2);
                }
                break;

                case OP_OVER:
                {
                    // (x1 x2 -- x1 x2 x1)
                    if (stack.size() < 2)
                        return false;
                    valtype vch = stacktop(-2);
                    stack.push_back(vch);
                }
                break;

                case OP_PICK:
                case OP_ROLL:
                {
                    // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
                    // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
                    if (stack.size() < 2)
                        return false;
                    int n = CastToBigNum(stacktop(-1)).getint();
                    popstack(stack);
                    if (n < 0 || n >= stack.size())
                        return false;
                    valtype vch = stacktop(-n-1);
                    if (opcode == OP_ROLL)
                        stack.erase(stack.end()-n-1);
                    stack.push_back(vch);
                }
                break;

                case OP_ROT:
                {
                    // (x1 x2 x3 -- x2 x3 x1)
                    //  x2 x1 x3  after first swap
                    //  x2 x3 x1  after second swap
                    if (stack.size() < 3)
                        return false;
                    swap(stacktop(-3), stacktop(-2));
                    swap(stacktop(-2), stacktop(-1));
                }
                break;

                case OP_SWAP:
                {
                    // (x1 x2 -- x2 x1)
                    if (stack.size() < 2)
                        return false;
                    swap(stacktop(-2), stacktop(-1));
                }
                break;

                case OP_TUCK:
                {
                    // (x1 x2 -- x2 x1 x2)
                    if (stack.size() < 2)
                        return false;
                    valtype vch = stacktop(-1);
                    stack.insert(stack.end()-2, vch);
                }
                break;


                //
                // Splice ops
                //
                case OP_CAT:
                {
                    // (x1 x2 -- out)
                    if (stack.size() < 2)
                        return false;
                    valtype& vch1 = stacktop(-2);
                    valtype& vch2 = stacktop(-1);
                    vch1.insert(vch1.end(), vch2.begin(), vch2.end());
                    popstack(stack);
                    if (stacktop(-1).size() > 520)
                        return false;
                }
                break;

                case OP_SUBSTR:
                {
                    // (in begin size -- out)
                    if (stack.size() < 3)
                        return false;
                    valtype& vch = stacktop(-3);
                    int nBegin = CastToBigNum(stacktop(-2)).getint();
                    int nEnd = nBegin + CastToBigNum(stacktop(-1)).getint();
                    if (nBegin < 0 || nEnd < nBegin)
                        return false;
                    if (nBegin > vch.size())
                        nBegin = vch.size();
                    if (nEnd > vch.size())
                        nEnd = vch.size();
                    vch.erase(vch.begin() + nEnd, vch.end());
                    vch.erase(vch.begin(), vch.begin() + nBegin);
                    popstack(stack);
                    popstack(stack);
                }
                break;

                case OP_LEFT:
                case OP_RIGHT:
                {
                    // (in size -- out)
                    if (stack.size() < 2)
                        return false;
                    valtype& vch = stacktop(-2);
                    int nSize = CastToBigNum(stacktop(-1)).getint();
                    if (nSize < 0)
                        return false;
                    if (nSize > vch.size())
                        nSize = vch.size();
                    if (opcode == OP_LEFT)
                        vch.erase(vch.begin() + nSize, vch.end());
                    else
                        vch.erase(vch.begin(), vch.end() - nSize);
                    popstack(stack);
                }
                break;

                case OP_SIZE:
                {
                    // (in -- in size)
                    if (stack.size() < 1)
                        return false;
                    CBigNum bn(stacktop(-1).size());
                    stack.push_back(bn.getvch());
                }
                break;


                //
                // Bitwise logic
                //
                case OP_INVERT:
                {
                    // (in - out)
                    if (stack.size() < 1)
                        return false;
                    valtype& vch = stacktop(-1);
                    for (int i = 0; i < vch.size(); i++)
                        vch[i] = ~vch[i];
                }
                break;

                case OP_AND:
                case OP_OR:
                case OP_XOR:
                {
                    // (x1 x2 - out)
                    if (stack.size() < 2)
                        return false;
                    valtype& vch1 = stacktop(-2);
                    valtype& vch2 = stacktop(-1);
                    MakeSameSize(vch1, vch2);
                    if (opcode == OP_AND)
                    {
                        for (int i = 0; i < vch1.size(); i++)
                            vch1[i] &= vch2[i];
                    }
                    else if (opcode == OP_OR)
                    {
                        for (int i = 0; i < vch1.size(); i++)
                            vch1[i] |= vch2[i];
                    }
                    else if (opcode == OP_XOR)
                    {
                        for (int i = 0; i < vch1.size(); i++)
                            vch1[i] ^= vch2[i];
                    }
                    popstack(stack);
                }
                break;

                case OP_EQUAL:
                case OP_EQUALVERIFY:
                //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL
                {
                    // (x1 x2 - bool)
                    if (stack.size() < 2)
                        return false;
                    valtype& vch1 = stacktop(-2);
                    valtype& vch2 = stacktop(-1);
                    bool fEqual = (vch1 == vch2);
                    // OP_NOTEQUAL is disabled because it would be too easy to say
                    // something like n != 1 and have some wiseguy pass in 1 with extra
                    // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
                    //if (opcode == OP_NOTEQUAL)
                    //    fEqual = !fEqual;
                    popstack(stack);
                    popstack(stack);
                    stack.push_back(fEqual ? vchTrue : vchFalse);
                    if (opcode == OP_EQUALVERIFY)
                    {
                        if (fEqual)
                            popstack(stack);
                        else
                            return false;
                    }
                }
                break;


                //
                // Numeric
                //
                case OP_1ADD:
                case OP_1SUB:
                case OP_2MUL:
                case OP_2DIV:
                case OP_NEGATE:
                case OP_ABS:
                case OP_NOT:
                case OP_0NOTEQUAL:
                {
                    // (in -- out)
                    if (stack.size() < 1)
                        return false;
                    CBigNum bn = CastToBigNum(stacktop(-1));
                    switch (opcode)
                    {
                    case OP_1ADD:       bn += bnOne; break;
                    case OP_1SUB:       bn -= bnOne; break;
                    case OP_2MUL:       bn <<= 1; break;
                    case OP_2DIV:       bn >>= 1; break;
                    case OP_NEGATE:     bn = -bn; break;
                    case OP_ABS:        if (bn < bnZero) bn = -bn; break;
                    case OP_NOT:        bn = (bn == bnZero); break;
                    case OP_0NOTEQUAL:  bn = (bn != bnZero); break;
                    default:            assert(!"invalid opcode"); break;
                    }
                    popstack(stack);
                    stack.push_back(bn.getvch());
                }
                break;

                case OP_ADD:
                case OP_SUB:
                case OP_MUL:
                case OP_DIV:
                case OP_MOD:
                case OP_LSHIFT:
                case OP_RSHIFT:
                case OP_BOOLAND:
                case OP_BOOLOR:
                case OP_NUMEQUAL:
                case OP_NUMEQUALVERIFY:
                case OP_NUMNOTEQUAL:
                case OP_LESSTHAN:
                case OP_GREATERTHAN:
                case OP_LESSTHANOREQUAL:
                case OP_GREATERTHANOREQUAL:
                case OP_MIN:
                case OP_MAX:
                {
                    // (x1 x2 -- out)
                    if (stack.size() < 2)
                        return false;
                    CBigNum bn1 = CastToBigNum(stacktop(-2));
                    CBigNum bn2 = CastToBigNum(stacktop(-1));
                    CBigNum bn;
                    switch (opcode)
                    {
                    case OP_ADD:
                        bn = bn1 + bn2;
                        break;

                    case OP_SUB:
                        bn = bn1 - bn2;
                        break;

                    case OP_MUL:
                        if (!BN_mul(&bn, &bn1, &bn2, pctx))
                            return false;
                        break;

                    case OP_DIV:
                        if (!BN_div(&bn, NULL, &bn1, &bn2, pctx))
                            return false;
                        break;

                    case OP_MOD:
                        if (!BN_mod(&bn, &bn1, &bn2, pctx))
                            return false;
                        break;

                    case OP_LSHIFT:
                        if (bn2 < bnZero || bn2 > CBigNum(2048))
                            return false;
                        bn = bn1 << bn2.getulong();
                        break;

                    case OP_RSHIFT:
                        if (bn2 < bnZero || bn2 > CBigNum(2048))
                            return false;
                        bn = bn1 >> bn2.getulong();
                        break;

                    case OP_BOOLAND:             bn = (bn1 != bnZero && bn2 != bnZero); break;
                    case OP_BOOLOR:              bn = (bn1 != bnZero || bn2 != bnZero); break;
                    case OP_NUMEQUAL:            bn = (bn1 == bn2); break;
                    case OP_NUMEQUALVERIFY:      bn = (bn1 == bn2); break;
                    case OP_NUMNOTEQUAL:         bn = (bn1 != bn2); break;
                    case OP_LESSTHAN:            bn = (bn1 < bn2); break;
                    case OP_GREATERTHAN:         bn = (bn1 > bn2); break;
                    case OP_LESSTHANOREQUAL:     bn = (bn1 <= bn2); break;
                    case OP_GREATERTHANOREQUAL:  bn = (bn1 >= bn2); break;
                    case OP_MIN:                 bn = (bn1 < bn2 ? bn1 : bn2); break;
                    case OP_MAX:                 bn = (bn1 > bn2 ? bn1 : bn2); break;
                    default:                     assert(!"invalid opcode"); break;
                    }
                    popstack(stack);
                    popstack(stack);
                    stack.push_back(bn.getvch());

                    if (opcode == OP_NUMEQUALVERIFY)
                    {
                        if (CastToBool(stacktop(-1)))
                            popstack(stack);
                        else
                            return false;
                    }
                }
                break;

                case OP_WITHIN:
                {
                    // (x min max -- out)
                    if (stack.size() < 3)
                        return false;
                    CBigNum bn1 = CastToBigNum(stacktop(-3));
                    CBigNum bn2 = CastToBigNum(stacktop(-2));
                    CBigNum bn3 = CastToBigNum(stacktop(-1));
                    bool fValue = (bn2 <= bn1 && bn1 < bn3);
                    popstack(stack);
                    popstack(stack);
                    popstack(stack);
                    stack.push_back(fValue ? vchTrue : vchFalse);
                }
                break;


                //
                // Crypto
                //
                case OP_RIPEMD160:
                case OP_SHA1:
                case OP_SHA256:
                case OP_HASH160:
                case OP_HASH256:
                {
                    // (in -- hash)
                    if (stack.size() < 1)
                        return false;
                    valtype& vch = stacktop(-1);
                    valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32);
                    if (opcode == OP_RIPEMD160)
                        RIPEMD160(&vch[0], vch.size(), &vchHash[0]);
                    else if (opcode == OP_SHA1)
                        SHA1(&vch[0], vch.size(), &vchHash[0]);
                    else if (opcode == OP_SHA256)
                        SHA256(&vch[0], vch.size(), &vchHash[0]);
                    else if (opcode == OP_HASH160)
                    {
                        uint160 hash160 = Hash160(vch);
                        memcpy(&vchHash[0], &hash160, sizeof(hash160));
                    }
                    else if (opcode == OP_HASH256)
                    {
                        uint256 hash = Hash(vch.begin(), vch.end());
                        memcpy(&vchHash[0], &hash, sizeof(hash));
                    }
                    popstack(stack);
                    stack.push_back(vchHash);
                }
                break;

                case OP_CODESEPARATOR:
                {
                    // Hash starts after the code separator
                    pbegincodehash = pc;
                }
                break;

                case OP_CHECKSIG:
                case OP_CHECKSIGVERIFY:
                {
                    // (sig pubkey -- bool)
                    if (stack.size() < 2)
                        return false;

                    valtype& vchSig    = stacktop(-2);
                    valtype& vchPubKey = stacktop(-1);

                    ////// debug print
                    //PrintHex(vchSig.begin(), vchSig.end(), "sig: %s\n");
                    //PrintHex(vchPubKey.begin(), vchPubKey.end(), "pubkey: %s\n");

                    // Subset of script starting at the most recent codeseparator
                    CScript scriptCode(pbegincodehash, pend);

                    // Drop the signature, since there's no way for a signature to sign itself
                    scriptCode.FindAndDelete(CScript(vchSig));

                    bool fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);

                    popstack(stack);
                    popstack(stack);
                    stack.push_back(fSuccess ? vchTrue : vchFalse);
                    if (opcode == OP_CHECKSIGVERIFY)
                    {
                        if (fSuccess)
                            popstack(stack);
                        else
                            return false;
                    }
                }
                break;

                case OP_CHECKMULTISIG:
                case OP_CHECKMULTISIGVERIFY:
                {
                    // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)

                    int i = 1;
                    if (stack.size() < i)
                        return false;

                    int nKeysCount = CastToBigNum(stacktop(-i)).getint();
                    if (nKeysCount < 0 || nKeysCount > 20)
                        return false;
                    nOpCount += nKeysCount;
                    if (nOpCount > 201)
                        return false;
                    int ikey = ++i;
                    i += nKeysCount;
                    if (stack.size() < i)
                        return false;

                    int nSigsCount = CastToBigNum(stacktop(-i)).getint();
                    if (nSigsCount < 0 || nSigsCount > nKeysCount)
                        return false;
                    int isig = ++i;
                    i += nSigsCount;
                    if (stack.size() < i)
                        return false;

                    // Subset of script starting at the most recent codeseparator
                    CScript scriptCode(pbegincodehash, pend);

                    // Drop the signatures, since there's no way for a signature to sign itself
                    for (int k = 0; k < nSigsCount; k++)
                    {
                        valtype& vchSig = stacktop(-isig-k);
                        scriptCode.FindAndDelete(CScript(vchSig));
                    }

                    bool fSuccess = true;
                    while (fSuccess && nSigsCount > 0)
                    {
                        valtype& vchSig    = stacktop(-isig);
                        valtype& vchPubKey = stacktop(-ikey);

                        // Check signature
                        if (CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType))
                        {
                            isig++;
                            nSigsCount--;
                        }
                        ikey++;
                        nKeysCount--;

                        // If there are more signatures left than keys left,
                        // then too many signatures have failed
                        if (nSigsCount > nKeysCount)
                            fSuccess = false;
                    }

                    while (i-- > 0)
                        popstack(stack);
                    stack.push_back(fSuccess ? vchTrue : vchFalse);

                    if (opcode == OP_CHECKMULTISIGVERIFY)
                    {
                        if (fSuccess)
                            popstack(stack);
                        else
                            return false;
                    }
                }
                break;

                default:
                    return false;
            }

            // Size limits
            if (stack.size() + altstack.size() > 1000)
                return false;
        }
    }
    catch (...)
    {
        return false;
    }


    if (!vfExec.empty())
        return false;

    return true;
}
Exemple #6
0
bool BitcoinMiner2_mineProbableChain(primecoinBlock_t* block, mpz_class& mpzFixedMultiplier, bool& fNewBlock, unsigned int& nTriedMultiplier, unsigned int& nProbableChainLength, 
										 unsigned int& nTests, unsigned int& nPrimesHit, sint32 threadIndex, mpz_class& mpzHash, unsigned int nPrimorialMultiplier)
{
	mpz_class mpzChainOrigin;
	mpz_class mpzFinalFixedMultiplier = mpzFixedMultiplier * mpzHash;
	mpz_class mpzTemp;
	uint32 nTime = GetTickCount();
	cSieve_prepare(mpzFinalFixedMultiplier, block->nBits>>24);
	nTime = GetTickCount()-nTime;
	//printf("cSieve prep time: %d\n", nTime);

	unsigned int nPrimorialSeq = 0;
	while (vPrimes[nPrimorialSeq + 1] <= nPrimorialMultiplier)
		nPrimorialSeq++;
	// Allocate GMP variables for primality tests
	CPrimalityTestParams testParams(block->nBits, nPrimorialSeq);
	{
		unsigned long lDivisor = 1;
		unsigned int i;
		testParams.vFastDivSeq.push_back(nPrimorialSeq);
		for (i = 1; i <= nFastDivPrimes; i++)
		{
			// Multiply primes together until the result won't fit an unsigned long
			if (lDivisor < ULONG_MAX / vPrimes[nPrimorialSeq + i])
				lDivisor *= vPrimes[nPrimorialSeq + i];
			else
			{
				testParams.vFastDivisors.push_back(lDivisor);
				testParams.vFastDivSeq.push_back(nPrimorialSeq + i);
				lDivisor = 1;
			}
		}

		// Finish off by multiplying as many primes as possible
		while (lDivisor < ULONG_MAX / vPrimes[nPrimorialSeq + i])
		{
			lDivisor *= vPrimes[nPrimorialSeq + i];
			i++;
		}
		testParams.vFastDivisors.push_back(lDivisor);
		testParams.vFastDivSeq.push_back(nPrimorialSeq + i);
		testParams.nFastDivisorsSize = testParams.vFastDivisors.size();
	}
	// References to counters;
	unsigned int& nChainLengthCunningham1 = testParams.nChainLengthCunningham1;
	unsigned int& nChainLengthCunningham2 = testParams.nChainLengthCunningham2;
	unsigned int& nChainLengthBiTwin = testParams.nChainLengthBiTwin;

	uint32 debugStats_primes = 0;
	uint32 debugStats_multipliersTested = 0;
	
	while( block->serverData.blockHeight == jhMiner_getCurrentWorkBlockHeight(block->threadIndex) )
	{
		uint32 sieveFlags;
		uint32 multiplier = cSieve_findNextMultiplier(&sieveFlags);
		if( multiplier == 0 )
		{
			// mix in next layer
			//printf("Layer finished [%d]\n", cSieve->currentSieveLayerIdx);
			if( cSieve_sieveNextLayer() == false )
				break;
			mpzFinalFixedMultiplier = cSieve->mpzFixedMultiplier;
			//printf("[%02d] debugStats_multipliersTested: %d\n", cSieve->currentSieveLayerIdx, debugStats_multipliersTested);
			//printf("[%02d] debugStats_primes: %d\n", cSieve->currentSieveLayerIdx, debugStats_primes);
			//double primality = (double)debugStats_primes / (double)debugStats_multipliersTested;
			//printf("[%02d] debugStats_primality: %lf\n", cSieve->currentSieveLayerIdx, primality);
			debugStats_primes = 0;
			debugStats_multipliersTested = 0;
			continue;
		}
		 
		//// test for sieve bugs C1
		//if( (sieveFlags&SIEVE_FLAG_C1_COMPOSITE)==0 && (rand()%10)==0 )
		//{
		//	// test c1
		//	for(uint32 lt=0; lt<cSieve->chainLength; lt++)
		//	{
		//		uint32 aMult = 1<<lt;
		//		mpzChainOrigin = mpzFinalFixedMultiplier * multiplier * aMult - 1;	
		//		for(uint32 f=0; f<cSieve->numPrimeFactors; f++)
		//		{
		//			uint32 mod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzChainOrigin.get_mpz_t(), vPrimes[f]);
		//			if( mod == 0 )
		//				printf("c1 div by %d possible\n", vPrimes[f]);//__debugbreak();
		//		}
		//	}
		//}
		//// test for sieve bugs C2
		//if( (sieveFlags&SIEVE_FLAG_C2_COMPOSITE)==0 && (rand()%10)==0 )
		//{
		//	// test c1
		//	for(uint32 lt=0; lt<cSieve->chainLength; lt++)
		//	{
		//		uint32 aMult = 1<<lt;
		//		mpzChainOrigin = mpzFinalFixedMultiplier * multiplier * aMult + 1;	
		//		for(uint32 f=0; f<cSieve->numPrimeFactors; f++)
		//		{
		//			uint32 mod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzChainOrigin.get_mpz_t(), vPrimes[f]);
		//			if( mod == 0 )
		//				printf("c2 div by %d possible\n", vPrimes[f]);//__debugbreak();
		//		}
		//	}
		//}
		// test for sieve bugs BT
		//if( (sieveFlags&SIEVE_FLAG_BT_COMPOSITE)==0 )
		//{
		//	// test c1
		//	mpzChainOrigin = mpzFinalFixedMultiplier * multiplier + 1;	
		//	for(uint32 f=0; f<cSieve->numPrimeFactors; f++)
		//	{
		//		uint32 mod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzChainOrigin.get_mpz_t(), vPrimes[f]);
		//		if( mod == 0 )
		//			printf("bt-c2 div by %d possible\n", vPrimes[f]);
		//	}
		//	// test c2
		//	mpzChainOrigin = mpzFinalFixedMultiplier * multiplier - 1;	
		//	for(uint32 f=0; f<cSieve->numPrimeFactors; f++)
		//	{
		//		uint32 mod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzChainOrigin.get_mpz_t(), vPrimes[f]);
		//		if( mod == 0 )
		//			printf("bt-c2 div by %d possible\n", vPrimes[f]);
		//	}
		//}

		//mpzChainOrigin = mpzFinalFixedMultiplier * multiplier;		
		mpz_mul_ui(mpzChainOrigin.get_mpz_t(), mpzFinalFixedMultiplier.get_mpz_t(), multiplier);
		nChainLengthCunningham1 = 0;
		nChainLengthCunningham2 = 0;
		nChainLengthBiTwin = 0;

		bool canSubmitAsShare = ProbablePrimeChainTestFast2(mpzChainOrigin, testParams, sieveFlags, multiplier);
		nProbableChainLength = max(max(nChainLengthCunningham1, nChainLengthCunningham2), nChainLengthBiTwin);

		if( nProbableChainLength >= 0x01000000 )
			debugStats_primes++;
		debugStats_multipliersTested++;
		//bool canSubmitAsShare = ProbablePrimeChainTestFast(mpzChainOrigin, testParams);
		//CBigNum bnChainOrigin;
		//bnChainOrigin.SetHex(mpzChainOrigin.get_str(16));
		//bool canSubmitAsShare = ProbablePrimeChainTestBN(bnChainOrigin, block->serverData.nBitsForShare, false, nChainLengthCunningham1, nChainLengthCunningham2, nChainLengthBiTwin);
		


		if( nProbableChainLength >= 0x04000000 )
		{
			sint32 chainDif = (nProbableChainLength>>24) - 7;
			primeStats.nChainHit += pow(8, (float)chainDif);
			//primeStats.nChainHit += pow(8, ((float)((double)nProbableChainLength  / (double)0x1000000))-7.0);
			//primeStats.nChainHit += pow(8, floor((float)((double)nProbableChainLength  / (double)0x1000000)) - 7);
			nTests = 0;
			primeStats.fourChainCount ++;
			if (nProbableChainLength >= 0x5000000)
			{
				primeStats.fiveChainCount ++;
				if (nProbableChainLength >= 0x6000000)
				{
					primeStats.sixChainCount ++;
					if (nProbableChainLength >= 0x7000000)
						primeStats.sevenChainCount ++;
				}
			}
		}
		//if( nBitsGen >= 0x03000000 )
		//	printf("%08X\n", nBitsGen);
		primeStats.primeChainsFound++;
		//if( nProbableChainLength > 0x03000000 )
		//	primeStats.qualityPrimesFound++;
		if( nProbableChainLength > primeStats.bestPrimeChainDifficulty )
			primeStats.bestPrimeChainDifficulty = nProbableChainLength;
		
		if(nProbableChainLength >= block->serverData.nBitsForShare)
		{
			// note: mpzPrimeChainMultiplier does not include the blockHash multiplier
			mpz_div(block->mpzPrimeChainMultiplier.get_mpz_t(), mpzChainOrigin.get_mpz_t(), mpzHash.get_mpz_t());
			//mpz_lsh(block->mpzPrimeChainMultiplier.get_mpz_t(), mpzFixedMultiplier.get_mpz_t(), multiplier);
			// update server data
			block->serverData.client_shareBits = nProbableChainLength;
			// generate block raw data
			uint8 blockRawData[256] = {0};
			memcpy(blockRawData, block, 80);
			uint32 writeIndex = 80;
			sint32 lengthBN = 0;
			CBigNum bnPrimeChainMultiplier;
			bnPrimeChainMultiplier.SetHex(block->mpzPrimeChainMultiplier.get_str(16));
			std::vector<unsigned char> bnSerializeData = bnPrimeChainMultiplier.getvch();
			lengthBN = bnSerializeData.size();
			*(uint8*)(blockRawData+writeIndex) = (uint8)lengthBN; // varInt (we assume it always has a size low enough for 1 byte)
			writeIndex += 1;
			memcpy(blockRawData+writeIndex, &bnSerializeData[0], lengthBN);
			writeIndex += lengthBN;	
			// switch endianness
			for(uint32 f=0; f<256/4; f++)
			{
				*(uint32*)(blockRawData+f*4) = _swapEndianessU32(*(uint32*)(blockRawData+f*4));
			}
			time_t now = time(0);
			struct tm * timeinfo;
			timeinfo = localtime (&now);
			char sNow [80];
			strftime (sNow, 80, "%x - %X",timeinfo);

			printf("%s - SHARE FOUND !!! (Th#: %u Multiplier: %d Layer: %d) ---  DIFF: %f    %s    %s\n", 
				sNow, threadIndex, multiplier, cSieve->currentSieveLayerIdx, (float)((double)nProbableChainLength  / (double)0x1000000), 
				nProbableChainLength >= 0x6000000 ? ">6":"", nProbableChainLength >= 0x7000000 ? ">7":"");

			// submit this share
			if (jhMiner_pushShare_primecoin(blockRawData, block))
				primeStats.foundShareCount ++;
			//printf("Probable prime chain found for block=%s!!\n  Target: %s\n  Length: (%s %s %s)\n", block.GetHash().GetHex().c_str(),TargetToString(block.nBits).c_str(), TargetToString(nChainLengthCunningham1).c_str(), TargetToString(nChainLengthCunningham2).c_str(), TargetToString(nChainLengthBiTwin).c_str());
			//nProbableChainLength = max(max(nChainLengthCunningham1, nChainLengthCunningham2), nChainLengthBiTwin);
			// since we are using C structs here we have to make sure the memory for the CBigNum in the block is freed again
			//delete *psieve;
			//*psieve = NULL;
			//block->bnPrimeChainMultiplier = NULL;
			RtlZeroMemory(blockRawData, 256);
			//delete *psieve;
			//*psieve = NULL;
			// dont quit if we find a share, there could be other shares in the remaining prime candidates
			nTests = 0;   // tehere is a good chance to find more shares so search a litle more.
			//block->nonce++;
			//return true;
			//break;
			//if (multipleShare)
		}
	}
Exemple #7
0
/*
bool Evaluator::operator()(const Script& script, const Script& tmpl) {
    _begin = script.begin();
    _current = script.begin();
    _end = script.end();
    Script::const_iterator current = tmpl.begin();

    // step through the script and template -
}
*/
boost::tribool Evaluator::eval(opcodetype opcode) {
    switch (opcode) {
            // Push value
        case OP_1NEGATE:
        case OP_1:
        case OP_2:
        case OP_3:
        case OP_4:
        case OP_5:
        case OP_6:
        case OP_7:
        case OP_8:
        case OP_9:
        case OP_10:
        case OP_11:
        case OP_12:
        case OP_13:
        case OP_14:
        case OP_15:
        case OP_16: {
            // ( -- value)
            CBigNum bn((int)opcode - (int)(OP_1 - 1));
            _stack.push_back(bn.getvch());
            break;
        }
            
            // Control
        case OP_NOP:
        case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5:
        case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
            break;
            
        case OP_IF:
        case OP_NOTIF: {
            // <expression> if [statements] [else [statements]] endif
            bool fValue = false;
            if (_exec) {
                if (_stack.size() < 1)
                    return false;
                Value& vch = top(-1);
                fValue = CastToBool(vch);
                if (opcode == OP_NOTIF)
                    fValue = !fValue;
                pop(_stack);
            }
            _exec_stack.push_back(fValue);
            break;
        }
            
        case OP_ELSE: {
            if (_exec_stack.empty())
                return false;
            _exec_stack.back() = !_exec_stack.back();
            break;
        }
            
        case OP_ENDIF: {
            if (_exec_stack.empty())
                return false;
            _exec_stack.pop_back();
            break;
        }
            
        case OP_VERIFY: {
            // (true -- ) or
            // (false -- false) and return
            if (_stack.size() < 1)
                return false;
            bool fValue = CastToBool(top(-1));
            if (fValue)
                pop(_stack);
            else
                return false;
            break;
        }
            
        case OP_RETURN: {
            return false;
            break;
        }
            
            
            // Stack ops
        case OP_TOALTSTACK: {
            if (_stack.size() < 1)
                return false;
            _alt_stack.push_back(top(-1));
            pop(_stack);
            break;
        }
            
        case OP_FROMALTSTACK: {
            if (_alt_stack.size() < 1)
                return false;
            _stack.push_back(alttop(-1));
            pop(_alt_stack);
            break;
        }
            
        case OP_2DROP: {
            // (x1 x2 -- )
            if (_stack.size() < 2)
                return false;
            pop(_stack);
            pop(_stack);
            break;
        }
            
        case OP_2DUP: {
            // (x1 x2 -- x1 x2 x1 x2)
            if (_stack.size() < 2)
                return false;
            Value vch1 = top(-2);
            Value vch2 = top(-1);
            _stack.push_back(vch1);
            _stack.push_back(vch2);
            break;
        }
            
        case OP_3DUP: {
            // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
            if (_stack.size() < 3)
                return false;
            Value vch1 = top(-3);
            Value vch2 = top(-2);
            Value vch3 = top(-1);
            _stack.push_back(vch1);
            _stack.push_back(vch2);
            _stack.push_back(vch3);
            break;
        }
            
        case OP_2OVER: {
            // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
            if (_stack.size() < 4)
                return false;
            Value vch1 = top(-4);
            Value vch2 = top(-3);
            _stack.push_back(vch1);
            _stack.push_back(vch2);
            break;
        }
            
        case OP_2ROT: {
            // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
            if (_stack.size() < 6)
                return false;
            Value vch1 = top(-6);
            Value vch2 = top(-5);
            _stack.erase(_stack.end()-6, _stack.end()-4);
            _stack.push_back(vch1);
            _stack.push_back(vch2);
            break;
        }
            
        case OP_2SWAP: {
            // (x1 x2 x3 x4 -- x3 x4 x1 x2)
            if (_stack.size() < 4)
                return false;
            swap(top(-4), top(-2));
            swap(top(-3), top(-1));
            break;
        }
            
        case OP_IFDUP: {
            // (x - 0 | x x)
            if (_stack.size() < 1)
                return false;
            Value vch = top(-1);
            if (CastToBool(vch))
                _stack.push_back(vch);
            break;
        }
            
        case OP_DEPTH: {
            // -- stacksize
            CBigNum bn((uint64_t)_stack.size());
            _stack.push_back(bn.getvch());
            break;
        }
            
        case OP_DROP: {
            // (x -- )
            if (_stack.size() < 1)
                return false;
            pop(_stack);
            break;
        }
            
        case OP_DUP: {
            // (x -- x x)
            if (_stack.size() < 1)
                return false;
            Value vch = top(-1);
            _stack.push_back(vch);
            break;
        }
            
        case OP_NIP: {
            // (x1 x2 -- x2)
            if (_stack.size() < 2)
                return false;
            _stack.erase(_stack.end() - 2);
            break;
        }
            
        case OP_OVER: {
            // (x1 x2 -- x1 x2 x1)
            if (_stack.size() < 2)
                return false;
            Value vch = top(-2);
            _stack.push_back(vch);
            break;
        }
            
        case OP_PICK:
        case OP_ROLL: {
            // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
            // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
            if (_stack.size() < 2)
                return false;
            int n = CastToBigNum(top(-1)).getint();
            pop(_stack);
            if (n < 0 || (unsigned int)n >= _stack.size())
                return false;
            Value vch = top(-n-1);
            if (opcode == OP_ROLL)
                _stack.erase(_stack.end()-n-1);
            _stack.push_back(vch);
            break;
        }
            
        case OP_ROT: {
            // (x1 x2 x3 -- x2 x3 x1)
            //  x2 x1 x3  after first swap
            //  x2 x3 x1  after second swap
            if (_stack.size() < 3)
                return false;
            swap(top(-3), top(-2));
            swap(top(-2), top(-1));
            break;
        }
            
        case OP_SWAP: {
            // (x1 x2 -- x2 x1)
            if (_stack.size() < 2)
                return false;
            swap(top(-2), top(-1));
            break;
        }
            
        case OP_TUCK: {
            // (x1 x2 -- x2 x1 x2)
            if (_stack.size() < 2)
                return false;
            Value vch = top(-1);
            _stack.insert(_stack.end()-2, vch);
            break;
        }
            
            
            //
            // Splice ops
            //
        case OP_CAT: {
            // (x1 x2 -- out)
            if (_stack.size() < 2)
                return false;
            Value& vch1 = top(-2);
            Value& vch2 = top(-1);
            vch1.insert(vch1.end(), vch2.begin(), vch2.end());
            pop(_stack);
            if (top(-1).size() > MAX_SCRIPT_ELEMENT_SIZE)
                return false;
            break;
        }
            
        case OP_SUBSTR: {
            // (in begin size -- out)
            if (_stack.size() < 3)
                return false;
            Value& vch = top(-3);
            int nBegin = CastToBigNum(top(-2)).getint();
            int nEnd = nBegin + CastToBigNum(top(-1)).getint();
            if (nBegin < 0 || nEnd < nBegin)
                return false;
            if ((unsigned int)nBegin > vch.size())
                nBegin = vch.size();
            if ((unsigned int)nEnd > vch.size())
                nEnd = vch.size();
            vch.erase(vch.begin() + nEnd, vch.end());
            vch.erase(vch.begin(), vch.begin() + nBegin);
            pop(_stack);
            pop(_stack);
            break;
        }
            
        case OP_LEFT:
        case OP_RIGHT: {
            // (in size -- out)
            if (_stack.size() < 2)
                return false;
            Value& vch = top(-2);
            int nSize = CastToBigNum(top(-1)).getint();
            if (nSize < 0)
                return false;
            if ((unsigned int)nSize > vch.size())
                nSize = vch.size();
            if (opcode == OP_LEFT)
                vch.erase(vch.begin() + nSize, vch.end());
            else
                vch.erase(vch.begin(), vch.end() - nSize);
            pop(_stack);
            break;
        }
            
        case OP_SIZE: {
            // (in -- in size)
            if (_stack.size() < 1)
                return false;
            CBigNum bn((uint64_t)top(-1).size());
            _stack.push_back(bn.getvch());
            break;
        }
            
            
            // Bitwise logic
        case OP_INVERT: {
            // (in - out)
            if (_stack.size() < 1)
                return false;
            Value& vch = top(-1);
            for (unsigned int i = 0; i < vch.size(); i++)
                vch[i] = ~vch[i];
            break;
        }
            
        case OP_AND:
        case OP_OR:
        case OP_XOR: {
            // (x1 x2 - out)
            if (_stack.size() < 2)
                return false;
            Value& vch1 = top(-2);
            Value& vch2 = top(-1);
            MakeSameSize(vch1, vch2);
            if (opcode == OP_AND) {
                for (unsigned int i = 0; i < vch1.size(); i++)
                    vch1[i] &= vch2[i];
            }
            else if (opcode == OP_OR) {
                for (unsigned int i = 0; i < vch1.size(); i++)
                    vch1[i] |= vch2[i];
            }
            else if (opcode == OP_XOR) {
                for (unsigned int i = 0; i < vch1.size(); i++)
                    vch1[i] ^= vch2[i];
            }
            pop(_stack);
            break;
        }
            
        case OP_EQUAL:
            //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL
        case OP_EQUALVERIFY: {
            // (x1 x2 - bool)
            if (_stack.size() < 2)
                return false;
            Value& vch1 = top(-2);
            Value& vch2 = top(-1);
            bool fEqual = (vch1 == vch2);
            // OP_NOTEQUAL is disabled because it would be too easy to say
            // something like n != 1 and have some wiseguy pass in 1 with extra
            // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
            //if (opcode == OP_NOTEQUAL)
            //    fEqual = !fEqual;
            pop(_stack);
            pop(_stack);
            _stack.push_back(fEqual ? vchTrue : vchFalse);
            if (opcode == OP_EQUALVERIFY) {
                if (fEqual)
                    pop(_stack);
                else
                    return false;
            }
            break;
        }
            
            
            // Numeric
        case OP_1ADD:
        case OP_1SUB:
        case OP_2MUL:
        case OP_2DIV:
        case OP_NEGATE:
        case OP_ABS:
        case OP_NOT:
        case OP_0NOTEQUAL: {
            // (in -- out)
            if (_stack.size() < 1)
                return false;
            CBigNum bn = CastToBigNum(top(-1));
            switch (opcode) {
                case OP_1ADD:       bn += bnOne; break;
                case OP_1SUB:       bn -= bnOne; break;
                case OP_2MUL:       bn <<= 1; break;
                case OP_2DIV:       bn >>= 1; break;
                case OP_NEGATE:     bn = -bn; break;
                case OP_ABS:        if (bn < bnZero) bn = -bn; break;
                case OP_NOT:        bn = (bn == bnZero); break;
                case OP_0NOTEQUAL:  bn = (bn != bnZero); break;
                default:            assert(!"invalid opcode"); break;
            }
            pop(_stack);
            _stack.push_back(bn.getvch());
            break;
        }
            
        case OP_ADD:
        case OP_SUB:
        case OP_MUL:
        case OP_DIV:
        case OP_MOD:
        case OP_LSHIFT:
        case OP_RSHIFT:
        case OP_BOOLAND:
        case OP_BOOLOR:
        case OP_NUMEQUAL:
        case OP_NUMEQUALVERIFY:
        case OP_NUMNOTEQUAL:
        case OP_LESSTHAN:
        case OP_GREATERTHAN:
        case OP_LESSTHANOREQUAL:
        case OP_GREATERTHANOREQUAL:
        case OP_MIN:
        case OP_MAX: {
            // (x1 x2 -- out)
            CAutoBN_CTX pctx;
            if (_stack.size() < 2)
                return false;
            CBigNum bn1 = CastToBigNum(top(-2));
            CBigNum bn2 = CastToBigNum(top(-1));
            CBigNum bn;
            switch (opcode) {
                case OP_ADD:
                    bn = bn1 + bn2;
                    break;
                    
                case OP_SUB:
                    bn = bn1 - bn2;
                    break;
                    
                case OP_MUL:
                    if (!BN_mul(&bn, &bn1, &bn2, pctx))
                        return false;
                    break;
                    
                case OP_DIV:
                    if (!BN_div(&bn, NULL, &bn1, &bn2, pctx))
                        return false;
                    break;
                    
                case OP_MOD:
                    if (!BN_mod(&bn, &bn1, &bn2, pctx))
                        return false;
                    break;
                    
                case OP_LSHIFT:
                    if (bn2 < bnZero || bn2 > CBigNum(2048))
                        return false;
                    bn = bn1 << bn2.getulong();
                    break;
                    
                case OP_RSHIFT:
                    if (bn2 < bnZero || bn2 > CBigNum(2048))
                        return false;
                    bn = bn1 >> bn2.getulong();
                    break;
                    
                case OP_BOOLAND:             bn = (bn1 != bnZero && bn2 != bnZero); break;
                case OP_BOOLOR:              bn = (bn1 != bnZero || bn2 != bnZero); break;
                case OP_NUMEQUAL:            bn = (bn1 == bn2); break;
                case OP_NUMEQUALVERIFY:      bn = (bn1 == bn2); break;
                case OP_NUMNOTEQUAL:         bn = (bn1 != bn2); break;
                case OP_LESSTHAN:            bn = (bn1 < bn2); break;
                case OP_GREATERTHAN:         bn = (bn1 > bn2); break;
                case OP_LESSTHANOREQUAL:     bn = (bn1 <= bn2); break;
                case OP_GREATERTHANOREQUAL:  bn = (bn1 >= bn2); break;
                case OP_MIN:                 bn = (bn1 < bn2 ? bn1 : bn2); break;
                case OP_MAX:                 bn = (bn1 > bn2 ? bn1 : bn2); break;
                default:                     assert(!"invalid opcode"); break;
            }
            pop(_stack);
            pop(_stack);
            _stack.push_back(bn.getvch());
            
            if (opcode == OP_NUMEQUALVERIFY) {
                if (CastToBool(top(-1)))
                    pop(_stack);
                else
                    return false;
            }
            break;
        }
            
        case OP_WITHIN: {
            // (x min max -- out)
            if (_stack.size() < 3)
                return false;
            CBigNum bn1 = CastToBigNum(top(-3));
            CBigNum bn2 = CastToBigNum(top(-2));
            CBigNum bn3 = CastToBigNum(top(-1));
            bool fValue = (bn2 <= bn1 && bn1 < bn3);
            pop(_stack);
            pop(_stack);
            pop(_stack);
            _stack.push_back(fValue ? vchTrue : vchFalse);
            break;
        }
            
            
            // Crypto
        case OP_RIPEMD160:
        case OP_SHA1:
        case OP_SHA256:
        case OP_HASH160:
        case OP_HASH256: {
            // (in -- hash)
            if (_stack.size() < 1)
                return false;
            Value& vch = top(-1);
            Value vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32);
            if (opcode == OP_RIPEMD160)
                RIPEMD160(&vch[0], vch.size(), &vchHash[0]);
            else if (opcode == OP_SHA1)
                SHA1(&vch[0], vch.size(), &vchHash[0]);
            else if (opcode == OP_SHA256)
                SHA256(&vch[0], vch.size(), &vchHash[0]);
            else if (opcode == OP_HASH160) {
                uint160 hash160 = toPubKeyHash(vch);
                memcpy(&vchHash[0], &hash160, sizeof(hash160));
            }
            else if (opcode == OP_HASH256) {
                uint256 hash = Hash(vch.begin(), vch.end());
                memcpy(&vchHash[0], &hash, sizeof(hash));
            }
            pop(_stack);
            _stack.push_back(vchHash);
            break;
        }
            
        default:
            break;
    }
    return indeterminate;
}
Exemple #8
0
bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet) {
    CAutoBN_CTX pctx;
    vchRet.clear();
    CBigNum bn58 = 58;
    CBigNum bn = 0;
    CBigNum bnChar;
    // Skip leading spaces.
    while (*psz && isspace(*psz))
        psz++;
    // Skip and count leading '1's.
    int zeroes = 0;
    while (*psz == '1') {
        zeroes++;
        psz++;
    }
    // Convert big endian string to bignum
    for (const char* p = psz; *p; p++)
    {
        const char* p1 = strchr(pszBase58, *p);
        if (p1 == NULL)
        {
            while (isspace(*p))
                p++;
            if (*p != '\0')
                return false;
            break;
        }
        bnChar.setulong(p1 - pszBase58);
        if (!BN_mul(&bn, &bn, &bn58, pctx))
            throw bignum_error("DecodeBase58 : BN_mul failed");
        bn += bnChar;
    }

     // Get bignum as little endian data
    std::vector<unsigned char> vchTmp = bn.getvch();

    // Trim off sign byte if present
    if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)
        vchTmp.erase(vchTmp.end()-1);

    // Restore leading zeros
    int nLeadingZeros = 0;
    for (const char* p = psz; *p == pszBase58[0]; p++)
        nLeadingZeros++;
    vchRet.assign(nLeadingZeros + vchTmp.size(), 0);

    // Convert little endian data to big endian
    reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());
    return true;
    // Allocate enough space in big-endian base256 representation.
    std::vector<unsigned char> b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
    // Process the characters.
    while (*psz && !isspace(*psz)) {
        // Decode base58 character
        const char *ch = strchr(pszBase58, *psz);
        if (ch == NULL)
            return false;
        // Apply "b256 = b256 * 58 + ch".
        int carry = ch - pszBase58;
        for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) {
            carry += 58 * (*it);
            *it = carry % 256;
            carry /= 256;
        }
        assert(carry == 0);
        psz++;
    }
    // Skip trailing spaces.
    while (isspace(*psz))
        psz++;
    if (*psz != 0)
        return false;
    // Skip leading zeroes in b256.
    std::vector<unsigned char>::iterator it = b256.begin();
    while (it != b256.end() && *it == 0)
        it++;
    // Copy result into output vector.
    vchRet.reserve(zeroes + (b256.end() - it));
    vchRet.assign(zeroes, 0x00);
    while (it != b256.end())
      vchRet.push_back(*(it++));
    return true;
}