Page MenuHomePhabricator

D1074.id3011.diff
No OneTemporary

D1074.id3011.diff

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -133,6 +133,7 @@
scheduler.cpp
script/sign.cpp
script/standard.cpp
+ utxocommit.cpp
warnings.cpp
)
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -169,6 +169,7 @@
util.h \
utilmoneystr.h \
utiltime.h \
+ utxocommit.cpp \
validation.h \
validationinterface.h \
versionbits.h \
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -98,6 +98,7 @@
test/undo_tests.cpp \
test/univalue_tests.cpp \
test/util_tests.cpp \
+ test/utxocommit_tests.cpp \
test/validation_tests.cpp
if ENABLE_WALLET
diff --git a/src/coins.h b/src/coins.h
--- a/src/coins.h
+++ b/src/coins.h
@@ -56,10 +56,16 @@
template <typename Stream> void Serialize(Stream &s) const {
assert(!IsSpent());
::Serialize(s, VARINT(nHeightAndIsCoinBase));
- ::Serialize(s, CTxOutCompressor(REF(out)));
+ // only compress for disk format
+ if (s.GetType() & SER_DISK) {
+ ::Serialize(s, CTxOutCompressor(REF(out)));
+ } else {
+ ::Serialize(s, REF(out));
+ }
}
template <typename Stream> void Unserialize(Stream &s) {
+ assert(s.GetType() & SER_DISK);
::Unserialize(s, VARINT(nHeightAndIsCoinBase));
::Unserialize(s, REF(CTxOutCompressor(out)));
}
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -71,6 +71,7 @@
undo_tests.cpp
univalue_tests.cpp
util_tests.cpp
+ utxocommit_tests.cpp
validation_tests.cpp
)
diff --git a/src/test/utxocommit_tests.cpp b/src/test/utxocommit_tests.cpp
new file mode 100644
--- /dev/null
+++ b/src/test/utxocommit_tests.cpp
@@ -0,0 +1,126 @@
+// Copyright (c) 2014-2016 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+// Tests for CUtxoCommit wrapper.
+// Mostly redundant with libsecp256k1_multiset tests
+
+#include "coins.h"
+#include "test/test_bitcoin.h"
+#include "util.h"
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+#include "secp256k1/include/secp256k1_multiset.h"
+#include "utxocommit.h"
+
+static COutPoint RandomOutpoint() {
+ const COutPoint op(InsecureRand256(), insecure_rand());
+ return op;
+}
+
+static Coin RandomCoin() {
+ const Coin c(CTxOut(Amount(InsecureRandRange(1000)),
+ CScript(InsecureRandBytes(insecure_rand() % 0x3f))),
+ insecure_rand(), InsecureRandBool());
+ return c;
+}
+
+BOOST_FIXTURE_TEST_SUITE(utxocommit_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(utxo_commit_order) {
+
+ // Test order independence
+
+ const COutPoint op1 = RandomOutpoint();
+ const COutPoint op2 = RandomOutpoint();
+ const COutPoint op3 = RandomOutpoint();
+ const Coin c1 = RandomCoin();
+ const Coin c2 = RandomCoin();
+ const Coin c3 = RandomCoin();
+
+ CUtxoCommit uc1, uc2, uc3;
+ BOOST_CHECK(uc1 == uc2);
+ uc1.Add(op1, c1);
+ uc1.Add(op2, c2);
+ uc1.Add(op3, c3);
+
+ uc2.Add(op2, c2);
+ BOOST_CHECK(uc1 != uc2);
+ uc2.Add(op3, c3);
+ uc2.Add(op1, c1);
+ BOOST_CHECK(uc1 == uc2);
+
+ // remove ordering
+ uc2.Remove(op2, c2);
+ uc2.Remove(op3, c3);
+
+ uc1.Remove(op2, c2);
+ uc1.Remove(op3, c3);
+
+ BOOST_CHECK(uc1 == uc2);
+
+ // odd but allowed
+ uc3.Remove(op2, c2);
+ uc3.Add(op2, c2);
+ uc3.Add(op1, c1);
+ BOOST_CHECK(uc1 == uc3);
+}
+
+BOOST_AUTO_TEST_CASE(utxo_commit_serialize) {
+
+ // Test whether the serialization is as expected
+
+ // some coin & output
+ const std::vector<uint8_t> txid = ParseHex(
+ "38115d014104c6ec27cffce0823c3fecb162dbd576c88dd7cda0b7b32b096118");
+ const uint32_t output = 2;
+ const uint32_t height = 7;
+ const uint64_t amount = 100;
+
+ const auto script =
+ CScript(ParseHex("76A9148ABCDEFABBAABBAABBAABBAABBAABBAABBAABBA88AC"));
+
+ const COutPoint op(uint256(txid), output);
+ const Coin coin = Coin(CTxOut(Amount(amount), script), height, false);
+ CScript s;
+
+ // find commit
+ CUtxoCommit commit;
+ commit.Add(op, coin);
+ uint256 hash = commit.GetHash();
+
+ // try the same manually
+ std::vector<uint8_t> expected;
+
+ // txid
+ expected.insert(expected.end(), txid.begin(), txid.end());
+
+ // output
+ auto outputbytes = ParseHex("02000000");
+ expected.insert(expected.end(), outputbytes.begin(), outputbytes.end());
+
+ // height and coinbase => height * 2
+ expected.push_back(14);
+
+ // amount & script
+ auto amountbytes = ParseHex("6400000000000000");
+ expected.insert(expected.end(), amountbytes.begin(), amountbytes.end());
+ expected.push_back(uint8_t(script.size()));
+ expected.insert(expected.end(), script.begin(), script.end());
+
+ secp256k1_context *ctx;
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+ secp256k1_multiset multiset;
+ secp256k1_multiset_init(ctx, &multiset);
+ secp256k1_multiset_add(ctx, &multiset, expected.data(), expected.size());
+
+ std::vector<uint8_t> expectedhash(32);
+ secp256k1_multiset_finalize(ctx, expectedhash.data(), &multiset);
+
+ secp256k1_context_destroy(ctx);
+ BOOST_ASSERT(uint256(expectedhash) == hash);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/utxocommit.h b/src/utxocommit.h
new file mode 100644
--- /dev/null
+++ b/src/utxocommit.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2017 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTXOCOMMIT_H
+#define BITCOIN_UTXOCOMMIT_H
+
+#include "coins.h"
+#include "hash.h"
+#include "secp256k1/include/secp256k1_multiset.h"
+#include "streams.h"
+#include <vector>
+
+class Coin;
+
+/* A Utxo Commitment
+ *
+ * This is maintained as 96-byte multiset value that uniquely defines a UTXO set
+ *
+ * It wraps the secp256k1 multiset
+ *
+ * Note that a CUtxoCommit allows "negative sets". That is
+ *
+ * CUtxoCommit set; // set is an empty set
+ * set.Remove(X); // set is empty set "minus" X
+ * set.Add(X); // set is an empty set
+ *
+ * This means a CUtxoCommit can both represent the total UTXO set, or a delta to
+ * the UTXO set
+*/
+class CUtxoCommit {
+private:
+ secp256k1_multiset multiset;
+
+public:
+ // Constructs empty CUtxoCommit
+ CUtxoCommit();
+
+ // Construct by combining two other CUtxoCommits
+ CUtxoCommit(const CUtxoCommit &commit1, const CUtxoCommit &commit2);
+
+ // Adds a TXO from multiset
+ void Add(const COutPoint &out, const Coin &element);
+
+ // Removes a TXO from multiset
+ void Remove(const COutPoint &out, const Coin &element);
+
+ void Clear();
+
+ uint256 GetHash() const;
+
+ // Comparison
+ friend bool operator==(const CUtxoCommit &a, const CUtxoCommit &b) {
+ return a.GetHash() == b.GetHash();
+ }
+ friend bool operator!=(const CUtxoCommit &a, const CUtxoCommit &b) {
+ return a.GetHash() != b.GetHash();
+ }
+
+ // Serialization
+ template <typename Stream> void Serialize(Stream &s) const {
+ s.write((char *)multiset, sizeof(multiset));
+ }
+ template <typename Stream> void Unserialize(Stream &s) {
+ s.read((char *)multiset, sizeof(multiset));
+ }
+
+ ~CUtxoCommit();
+};
+
+#endif // MULTISET_H
diff --git a/src/utxocommit.cpp b/src/utxocommit.cpp
new file mode 100644
--- /dev/null
+++ b/src/utxocommit.cpp
@@ -0,0 +1,66 @@
+// Copyright (c) 2017 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "utxocommit.h"
+
+namespace {
+secp256k1_context *secp256k1_context_multiset;
+int secp256k1_context_refcount = 0;
+}
+
+// Constructs empty CUtxoCommit
+CUtxoCommit::CUtxoCommit() {
+ if (secp256k1_context_refcount == 0) {
+ secp256k1_context_multiset =
+ secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+ }
+ secp256k1_context_refcount++;
+ secp256k1_multiset_init(secp256k1_context_multiset, &multiset);
+}
+
+CUtxoCommit::~CUtxoCommit() {
+ secp256k1_context_refcount--;
+ if (secp256k1_context_refcount == 0) {
+ secp256k1_context_destroy(secp256k1_context_multiset);
+ }
+}
+
+// Construct by combining two other CUtxoCommits
+CUtxoCommit::CUtxoCommit(const CUtxoCommit &commit1, const CUtxoCommit &commit2)
+ : CUtxoCommit() {
+ secp256k1_multiset_combine(secp256k1_context_multiset, &this->multiset,
+ &commit1.multiset);
+ secp256k1_multiset_combine(secp256k1_context_multiset, &this->multiset,
+ &commit2.multiset);
+}
+
+// Adds a TXO from multiset
+void CUtxoCommit::Add(const COutPoint &out, const Coin &element) {
+
+ CDataStream txo(SER_NETWORK, PROTOCOL_VERSION);
+ txo << out << element;
+ secp256k1_multiset_add(secp256k1_context_multiset, &multiset,
+ (const uint8_t *)&txo[0], txo.size());
+}
+
+// Removes a TXO from multiset
+void CUtxoCommit::Remove(const COutPoint &out, const Coin &element) {
+
+ CDataStream txo(SER_NETWORK, PROTOCOL_VERSION);
+ txo << out << element;
+ secp256k1_multiset_remove(secp256k1_context_multiset, &multiset,
+ (const uint8_t *)&txo[0], txo.size());
+}
+
+void CUtxoCommit::Clear() {
+ secp256k1_multiset_init(secp256k1_context_multiset, &multiset);
+}
+
+uint256 CUtxoCommit::GetHash() const {
+
+ std::vector<uint8_t> hash(32);
+ secp256k1_multiset_finalize(secp256k1_context_multiset, hash.data(),
+ &multiset);
+ return uint256(hash);
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 26, 12:04 (2 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5573497
Default Alt Text
D1074.id3011.diff (9 KB)

Event Timeline