Files
thehub/hub/server/DoubleSpendProof.h
T

125 lines
4.2 KiB
C++
Raw Permalink Normal View History

2019-09-02 23:28:14 +02:00
/*
* This file is part of the Flowee project
2021-01-20 21:35:20 +01:00
* Copyright (C) 2019-2021 Tom Zander <tom@flowee.org>
2019-09-02 23:28:14 +02:00
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DOUBLESPENDPROOF_H
#define DOUBLESPENDPROOF_H
#include <uint256.h>
#include <primitives/Tx.h>
2020-09-29 17:01:52 +02:00
#include <primitives/script.h>
2019-09-02 23:28:14 +02:00
#include "serialize.h"
#include <deque>
class CTxMemPool;
class DoubleSpendProof
{
public:
2020-09-29 17:01:52 +02:00
//! limit for the size of a `pushData` vector below
static constexpr size_t MaxPushDataSize = MAX_SCRIPT_ELEMENT_SIZE;
/** Creates an empty, invalid object */
2019-09-02 23:28:14 +02:00
DoubleSpendProof();
2020-09-29 17:01:52 +02:00
/** Create a proof object, given two conflicting transactions */
2019-09-02 23:28:14 +02:00
static DoubleSpendProof create(const Tx &tx1, const Tx &tx2);
2021-01-20 21:35:20 +01:00
/** loads a DSProof from a serialized stream. */
static DoubleSpendProof load(const Streaming::ConstBuffer &buffer);
2020-09-29 17:01:52 +02:00
/** Returns true if this object is invalid, i.e. does not represent a double spend proof */
2019-09-02 23:28:14 +02:00
bool isEmpty() const;
2020-09-29 17:01:52 +02:00
/** Return codes for the 'validate' function */
2019-09-02 23:28:14 +02:00
enum Validity {
2020-09-29 17:01:52 +02:00
Valid, //< Double spend proof is valid
MissingTransaction, //< We cannot determine the validity of this proof because we don't have one of the spends
MissingUTXO, //< We cannot determine the validity of this proof because the prevout is not available
Invalid //< This object does not contain a valid doublespend proof
2019-09-02 23:28:14 +02:00
};
2020-09-29 17:01:52 +02:00
/**
* Returns whether this doublespend proof is valid, or why its
* validity cannot be determined.
*/
2020-01-08 16:22:14 +01:00
Validity validate(const CTxMemPool &mempool) const;
2019-09-02 23:28:14 +02:00
2020-09-29 17:01:52 +02:00
/** Returns the hash of the input transaction (UTXO) that is being doublespent */
2019-09-02 23:28:14 +02:00
uint256 prevTxId() const;
2020-09-29 17:01:52 +02:00
/** Returns the index of the output that is being doublespent */
2019-09-02 23:28:14 +02:00
int prevOutIndex() const;
2020-09-29 17:01:52 +02:00
/** This struction tracks information about each doublespend transaction */
2019-09-02 23:28:14 +02:00
struct Spender {
uint32_t txVersion = 0, outSequence = 0, lockTime = 0;
uint256 hashPrevOutputs, hashSequence, hashOutputs;
std::vector<std::vector<uint8_t>> pushData;
};
2020-09-29 17:01:52 +02:00
/// Return the first spender, sorted by hashOutputs
2019-09-02 23:28:14 +02:00
Spender firstSpender() const {
return m_spender1;
}
2020-09-29 17:01:52 +02:00
/// return the 2nd spender, sorted by hashOutputs
Spender secondSpender() const {
2019-09-02 23:28:14 +02:00
return m_spender2;
}
// old fashioned serialization.
ADD_SERIALIZE_METHODS
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(m_prevTxId);
READWRITE(m_prevOutIndex);
READWRITE(m_spender1.txVersion);
READWRITE(m_spender1.outSequence);
READWRITE(m_spender1.lockTime);
READWRITE(m_spender1.hashPrevOutputs);
READWRITE(m_spender1.hashSequence);
READWRITE(m_spender1.hashOutputs);
READWRITE(m_spender1.pushData);
READWRITE(m_spender2.txVersion);
READWRITE(m_spender2.outSequence);
READWRITE(m_spender2.lockTime);
READWRITE(m_spender2.hashPrevOutputs);
READWRITE(m_spender2.hashSequence);
READWRITE(m_spender2.hashOutputs);
READWRITE(m_spender2.pushData);
}
2020-09-29 17:01:52 +02:00
/** create the ID of this doublespend proof */
2019-09-02 23:28:14 +02:00
uint256 createHash() const;
private:
2020-09-29 17:01:52 +02:00
/// Throws std::runtime_error if the proof breaks the sanity of:
/// - isEmpty()
/// - does not have exactly 1 pushData per spender vector
/// - any pushData size >520 bytes
/// Called from: `create()` and `validate()` (`validate()` won't throw but will return Invalid)
void checkSanityOrThrow() const;
2019-09-02 23:28:14 +02:00
uint256 m_prevTxId;
int32_t m_prevOutIndex = -1;
Spender m_spender1, m_spender2;
};
#endif