Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13711436
D1074.id2827.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Subscribers
None
D1074.id2827.diff
View Options
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,12 +56,21 @@
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) {
::Unserialize(s, VARINT(nHeightAndIsCoinBase));
- ::Unserialize(s, REF(CTxOutCompressor(out)));
+ if (s.GetType() & SER_DISK) {
+ ::Unserialize(s, REF(CTxOutCompressor(out)));
+ } else {
+ ::Unserialize(s, REF(out));
+ }
}
size_t DynamicMemoryUsage() const {
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,124 @@
+// 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_multiset multiset;
+ secp256k1_multiset_init(context, &multiset);
+ secp256k1_multiset_add(context, &multiset, expected.data(),
+ expected.size());
+
+ std::vector<uint8_t> expectedhash(32);
+ secp256k1_multiset_finalize(context, expectedhash.data(), &multiset);
+
+ 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,80 @@
+// 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>
+
+secp256k1_context *context = nullptr;
+
+/* 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() { secp256k1_multiset_init(context, &multiset); }
+
+ // Construct by combining two other CUtxoCommits
+ CUtxoCommit(const CUtxoCommit &commit1, const CUtxoCommit &commit2)
+ : CUtxoCommit() {
+ secp256k1_multiset_combine(context, &this->multiset, &commit1.multiset);
+ secp256k1_multiset_combine(context, &this->multiset, &commit2.multiset);
+ }
+
+ // Adds a TXO from multiset
+ void Add(const COutPoint &out, const Coin &element) {
+
+ CDataStream txo(SER_NETWORK, PROTOCOL_VERSION);
+ txo << out << element;
+ secp256k1_multiset_add(context, &multiset, (const uint8_t *)&txo[0],
+ txo.size());
+ }
+
+ // Removes a TXO from multiset
+ void Remove(const COutPoint &out, const Coin &element) {
+
+ CDataStream txo(SER_NETWORK, PROTOCOL_VERSION);
+ txo << out << element;
+ secp256k1_multiset_remove(context, &multiset, (const uint8_t *)&txo[0],
+ txo.size());
+ }
+
+ uint256 GetHash() const {
+
+ std::vector<uint8_t> hash(32);
+ secp256k1_multiset_finalize(context, hash.data(), &multiset);
+ return uint256(hash);
+ }
+
+ // 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();
+ }
+};
+
+#endif // MULTISET_H
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 26, 12:04 (2 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5573496
Default Alt Text
D1074.id2827.diff (7 KB)
Attached To
D1074: Add Utxo Commitment wrapper around libsecp256k1
Event Timeline
Log In to Comment