shadowproject/shadow

View on GitHub
src/core.h

Summary

Maintainability
Test Coverage
// Copyright (c) 2014 The ShadowCoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.

#ifndef SDC_CORE_H
#define SDC_CORE_H

#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <inttypes.h>

#include "util.h"
#include "serialize.h"
#include "script.h"
#include "ringsig.h"

enum GetMinFee_mode
{
    GMF_BLOCK,
    GMF_RELAY,
    GMF_SEND,
    GMF_ANON,
};

class CTransaction;

/** An outpoint - a combination of a transaction hash and an index n into its vout */
class COutPoint
{
public:
    uint256 hash;
    unsigned int n;

    COutPoint() { SetNull(); }
    COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
    IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
    void SetNull() { hash = 0; n = (unsigned int) -1; }
    bool IsNull() const { return (hash == 0 && n == (unsigned int) -1); }

    friend bool operator<(const COutPoint& a, const COutPoint& b)
    {
        return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
    }

    friend bool operator==(const COutPoint& a, const COutPoint& b)
    {
        return (a.hash == b.hash && a.n == b.n);
    }

    friend bool operator!=(const COutPoint& a, const COutPoint& b)
    {
        return !(a == b);
    }

    std::string ToString() const
    {
        return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10).c_str(), n);
    }

    void print() const
    {
        LogPrintf("%s\n", ToString().c_str());
    }
};

/** An inpoint - a combination of a transaction and an index n into its vin */
class CInPoint
{
public:
    CTransaction* ptx;
    unsigned int n;

    CInPoint() { SetNull(); }
    CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
    void SetNull() { ptx = NULL; n = (unsigned int) -1; }
    bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); }
};



/** An input of a transaction.  It contains the location of the previous
 * transaction's output that it claims and a signature that matches the
 * output's public key.
 */
class CTxIn
{
public:
    COutPoint prevout;
    CScript scriptSig;
    unsigned int nSequence;

    CTxIn()
    {
        nSequence = std::numeric_limits<unsigned int>::max();
    }

    explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
    {
        prevout = prevoutIn;
        scriptSig = scriptSigIn;
        nSequence = nSequenceIn;
    }

    CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
    {
        prevout = COutPoint(hashPrevTx, nOut);
        scriptSig = scriptSigIn;
        nSequence = nSequenceIn;
    }

    IMPLEMENT_SERIALIZE
    (
        READWRITE(prevout);
        READWRITE(scriptSig);
        READWRITE(nSequence);
    )

    bool IsFinal() const
    {
        return (nSequence == std::numeric_limits<unsigned int>::max());
    }

    bool IsAnonInput() const
    {
        return (scriptSig.size() >= MIN_ANON_IN_SIZE
            && scriptSig[0] == OP_RETURN
            && scriptSig[1] == OP_ANON_MARKER);
    }

    friend bool operator==(const CTxIn& a, const CTxIn& b)
    {
        return (a.prevout   == b.prevout &&
                a.scriptSig == b.scriptSig &&
                a.nSequence == b.nSequence);
    }

    friend bool operator!=(const CTxIn& a, const CTxIn& b)
    {
        return !(a == b);
    }


    std::string ToString() const
    {
        std::string str;
        str += "CTxIn(";
        str += prevout.ToString();
        if (prevout.IsNull())
            str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
        else
            str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
        if (nSequence != std::numeric_limits<unsigned int>::max())
            str += strprintf(", nSequence=%u", nSequence);
        str += ")";
        return str;
    }

    void print() const
    {
        LogPrintf("%s\n", ToString().c_str());
    }

    void ExtractKeyImage(ec_point& kiOut) const
    {
        kiOut.resize(EC_COMPRESSED_SIZE);
        memcpy(&kiOut[0], prevout.hash.begin(), 32);
        kiOut[32] = prevout.n & 0xFF;
    };

    int ExtractRingSize() const
    {
        return (prevout.n >> 16) & 0xFFFF;
    };

};




/** An output of a transaction.  It contains the public key that the next input
 * must be able to sign with to claim it.
 */
class CTxOut
{
public:
    int64_t nValue;
    CScript scriptPubKey;

    CTxOut()
    {
        SetNull();
    }

    CTxOut(int64_t nValueIn, CScript scriptPubKeyIn)
    {
        nValue = nValueIn;
        scriptPubKey = scriptPubKeyIn;
    }

    IMPLEMENT_SERIALIZE
    (
        READWRITE(nValue);
        READWRITE(scriptPubKey);
    )

    void SetNull()
    {
        nValue = -1;
        scriptPubKey.clear();
    }

    bool IsNull()
    {
        return (nValue == -1);
    }

    void SetEmpty()
    {
        nValue = 0;
        scriptPubKey.clear();
    }

    bool IsEmpty() const
    {
        return (nValue == 0 && scriptPubKey.empty());
    }

    bool IsAnonOutput() const
    {
        return (scriptPubKey.size() >= MIN_ANON_OUT_SIZE
            && scriptPubKey[0] == OP_RETURN
            && scriptPubKey[1] == OP_ANON_MARKER);
    }


    uint256 GetHash() const
    {
        return SerializeHash(*this);
    }

    friend bool operator==(const CTxOut& a, const CTxOut& b)
    {
        return (a.nValue       == b.nValue &&
                a.scriptPubKey == b.scriptPubKey);
    }

    friend bool operator!=(const CTxOut& a, const CTxOut& b)
    {
        return !(a == b);
    }

    friend bool operator<(const CTxOut& a, const CTxOut& b)
    {
        return (a.nValue < b.nValue);
    }

    std::string ToString() const
    {
        if (IsEmpty()) return "CTxOut(empty)";
        return strprintf("CTxOut(nValue=%s, scriptPubKey=%s)", FormatMoney(nValue).c_str(), scriptPubKey.ToString().c_str());
    }

    void print() const
    {
        LogPrintf("%s\n", ToString().c_str());
    }

    CPubKey ExtractAnonPk() const
    {
        // always use IsAnonOutput to check length
        return CPubKey(&scriptPubKey[2+1], EC_COMPRESSED_SIZE);
    };
};




class CKeyImageSpent
{
// stored in txdb, key is keyimage
public:
    CKeyImageSpent() {};

    CKeyImageSpent(uint256& txnHash_, uint32_t inputNo_, int64_t nValue_)
    {
        txnHash = txnHash_;
        inputNo = inputNo_;
        nValue  = nValue_;
    };

    uint256 txnHash;    // hash of spending transaction
    uint32_t inputNo;   // keyimage is for inputNo of txnHash
    int64_t nValue;     // reporting only

    IMPLEMENT_SERIALIZE
    (
        READWRITE(txnHash);
        READWRITE(inputNo);
        READWRITE(nValue);
    )
};

class CAnonOutput
{
// stored in txdb, key is pubkey
public:

    CAnonOutput() {};

    CAnonOutput(COutPoint& outpoint_, int64_t nValue_, int nBlockHeight_, uint8_t nCompromised_)
    {
        outpoint = outpoint_;
        nValue = nValue_;
        nBlockHeight = nBlockHeight_;
        nCompromised = nCompromised_;
    };

    COutPoint outpoint;
    int64_t nValue;         // rather store 2 bytes, digit + power 10 ?
    int nBlockHeight;
    uint8_t nCompromised;   // TODO: mark if output can be identified (spent with ringsig 1)
    IMPLEMENT_SERIALIZE
    (
        READWRITE(outpoint);
        READWRITE(nValue);
        READWRITE(nBlockHeight);
        READWRITE(nCompromised);
    )
};

class CAnonOutputCount
{ // CountAllAnonOutputs
public:

    CAnonOutputCount()
    {
        nValue = 0;
        nExists = 0;
        nSpends = 0;
        nOwned = 0;
        nLeastDepth = 0;
        nCompromised = 0;
    }

    CAnonOutputCount(int64_t nValue_, int nExists_, int nSpends_, int nOwned_, int nLeastDepth_, int nCompromised_)
    {
        nValue = nValue_;
        nExists = nExists_;
        nSpends = nSpends_;
        nOwned = nOwned_;
        nLeastDepth = nLeastDepth_;
        nCompromised = nCompromised_;
    }

    void set(int64_t nValue_, int nExists_, int nSpends_, int nOwned_, int nLeastDepth_, int nCompromised_)
    {
        nValue = nValue_;
        nExists = nExists_;
        nSpends = nSpends_;
        nOwned = nOwned_;
        nLeastDepth = nLeastDepth_;
        nCompromised = nCompromised_;
    }

    void addCoin(int nCoinDepth, int64_t nCoinValue)
    {
        nExists++;
        nValue = nCoinValue;
        if (nCoinDepth < nLeastDepth)
            nLeastDepth = nCoinDepth;
    }

    void updateDepth(int nCoinDepth, int64_t nCoinValue)
    {
        nValue = nCoinValue;
        if (nLeastDepth == 0
            || nCoinDepth < nLeastDepth)
            nLeastDepth = nCoinDepth;
    }

    void incSpends(int64_t nCoinValue)
    {
        nSpends++;
        nValue = nCoinValue;
    }

    void decSpends(int64_t nCoinValue)
    {
        nSpends--;
        nValue = nCoinValue;
    }

    void incExists(int64_t nCoinValue)
    {
        nExists++;
        nValue = nCoinValue;
    }

    void decExists(int64_t nCoinValue)
    {
        nExists--;
        nValue = nCoinValue;
    }


    int64_t nValue;
    int nExists;
    int nSpends;
    int nOwned; // todo
    int nLeastDepth;
    int nCompromised;

};


class CStakeModifier
{
// for CheckKernel
public:
    CStakeModifier() {};
    CStakeModifier(uint64_t modifier, uint256 modifierv2, int height, int64_t time)
        : nModifier(modifier), bnModifierV2(modifierv2), nHeight(height), nTime(time)
    {};

    uint64_t nModifier;
    uint256 bnModifierV2;
    int nHeight;
    int64_t nTime;
};

#endif  // SDC_CORE_H