Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13711437
D1074.id3011.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Subscribers
None
D1074.id3011.diff
View Options
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
Details
Attached
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)
Attached To
D1074: Add Utxo Commitment wrapper around libsecp256k1
Event Timeline
Log In to Comment