Skip to content

Commit

Permalink
Merge pull request bitcoin-core#100 from kallewoof/202112-tap-253
Browse files Browse the repository at this point in the history
bug-fix: prefix compact size function
  • Loading branch information
kallewoof authored Dec 17, 2021
2 parents c5f51a1 + ac02730 commit a43374e
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 9 deletions.
2 changes: 2 additions & 0 deletions functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ int _e_jacobi_sym(Value&& pv) { pv.do_jacobi_symbol(); pv.println(); return 0;
int _e_tagged_hash(Value&& pv) { pv.do_tagged_hash(); pv.println(); return 0; }
int _e_taproot_tweak_pubkey(Value&& pv) { pv.do_taproot_tweak_pubkey(); pv.println(); return 0; }
int _e_prefix_compact_size(Value&& pv) { pv.do_prefix_compact_size(); pv.println(); return 0; }
int _e_len(Value&& pv) { pv.do_len(); pv.println(); return 0; }
#ifdef ENABLE_DANGEROUS
int _e_taproot_tweak_seckey(Value&& pv) { pv.do_taproot_tweak_seckey(); pv.println(); return 0; }
int _e_encode_wif(Value&& pv) { kerl_set_sensitive(true); pv.do_encode_wif(); pv.println(); return 0; }
Expand Down Expand Up @@ -288,6 +289,7 @@ static const tf_t tfs[] = {
TF ("[message] perform HASH256 (SHA256(SHA256(message))", hash256),
TF ("[*] convert into a hex string", hex),
TF ("[arg] convert into an integer", int),
TF ("[*] show length of expression in bytes", len),
TFN("[n] ([k]) calculate the Jacobi symbol for n modulo k, where k defaults to the secp256k1 field size", "jacobi-symbol", jacobi_sym),
TFN("[value] prefix [value] with its compact size encoded byte length", "prefix-compact-size", prefix_compact_size),
TFN("[pubkey] convert the given pubkey into an x-only pubkey, as those used in taproot/tapscript", "pubkey-to-xpubkey", pubkey_to_xpubkey),
Expand Down
50 changes: 50 additions & 0 deletions test/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,56 @@ TEST_CASE("Single entry values are interpreted correctly", "[single-entry-values
}
}

TEST_CASE("Compact size encoder", "[compact-size]") {
SECTION("Fitting in 1 byte") {
std::string s = "0x";
for (uint8_t i = 1; i < 253; ++i) {
s += strprintf("%02x", i);
Value v(s.c_str());
v.do_prefix_compact_size();
REQUIRE(v.data[0] == i);
}
s += "fd"; // -> 253 bytes -> 0xfd (16 bit) + LE(253) == 0xfdfd00
{
Value v(s.c_str());
v.do_prefix_compact_size();
REQUIRE((uint32_t)v.data[0] == 0xfd); // 2 byte size
REQUIRE((uint32_t)v.data[1] == 0xfd); // 253 (lower byte)
REQUIRE((uint32_t)v.data[2] == 0x00); // 00 (higher byte)
}
s += "feff000102"; // -> 258 bytes -> 0xfd + LE(258) == 0xfd0201
{
Value v(s.c_str());
v.do_prefix_compact_size();
REQUIRE((uint32_t)v.data[0] == 0xfd); // 2 byte size
REQUIRE((uint32_t)v.data[1] == 0x02); // 02 (lower byte)
REQUIRE((uint32_t)v.data[2] == 0x01); // 01 (higher byte)
}
{
Value v("0x00");
v.data.resize(65537);
v.do_prefix_compact_size();
// 65537 = 0x010001 = 0xfe (32 bit) + LE(65537) = 0xfc01000100
REQUIRE((uint32_t)v.data[0] == 0xfe); // 4 byte size
REQUIRE((uint32_t)v.data[1] == 0x01); // 01 (lowest byte)
REQUIRE((uint32_t)v.data[2] == 0x00); // 00 (lower byte)
REQUIRE((uint32_t)v.data[3] == 0x01); // 01 (higher byte)
REQUIRE((uint32_t)v.data[4] == 0x00); // 01 (highest byte)
}
{
Value v("0x00");
v.data.resize(65538);
v.do_prefix_compact_size();
// 65538 = 0x010002 = 0xfe (32 bit) + LE(65538) = 0xfc02000100
REQUIRE((uint32_t)v.data[0] == 0xfe); // 4 byte size
REQUIRE((uint32_t)v.data[1] == 0x02); // 02 (lowest byte)
REQUIRE((uint32_t)v.data[2] == 0x00); // 00 (lower byte)
REQUIRE((uint32_t)v.data[3] == 0x01); // 01 (higher byte)
REQUIRE((uint32_t)v.data[4] == 0x00); // 01 (highest byte)
}
}
}

TEST_CASE("Script or not to script", "[script-notscript]") {
SECTION("515293 becomes the number, not the script") {
Value notascript("515293");
Expand Down
23 changes: 14 additions & 9 deletions value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,17 +251,22 @@ void Value::do_not_op() {

void Value::do_prefix_compact_size() {
data_value();
uint8_t sz8 = 0;
std::vector<uint8_t> prefix;
size_t data_len = data.size();
#define DLW(type) \
if (sz8) data.insert(data.begin(), &sz8, &sz8 + 1);\
type t = (type)data_len;\
data.insert(data.begin(), &t, &t + sizeof(type));\
#define DLW(sz) \
for (size_t i = 0; i < sz; ++i) { prefix.push_back(data_len & 0xff); data_len >>= 8; } \
data.insert(data.begin(), prefix.begin(), prefix.end()); \
return
if (data_len < 253) { DLW(uint8_t); }
if (data_len <= std::numeric_limits<unsigned short>::max()) { sz8 = 253; DLW(uint16_t); }
if (data_len <= std::numeric_limits<unsigned int>::max()) { sz8 = 254; DLW(uint32_t); }
sz8 = 255; DLW(uint64_t);
if (data_len < 253) { DLW(1); }
if (data_len <= std::numeric_limits<unsigned short>::max()) { prefix.push_back(253); DLW(2); }
if (data_len <= std::numeric_limits<unsigned int>::max()) { prefix.push_back(254); DLW(4); }
prefix.push_back(255); DLW(8);
}

void Value::do_len() {
data_value();
int64 = (int64_t)data.size();
type = T_INT;
}

std::vector<uint8_t> gen_taproot_tagged_hash(const std::string& tag, const std::vector<uint8_t>& msg) {
Expand Down
1 change: 1 addition & 0 deletions value.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ struct Value {
void do_taproot_tweak_pubkey();
void do_jacobi_symbol();
void do_prefix_compact_size();
void do_len();
#ifdef ENABLE_DANGEROUS
void do_taproot_tweak_seckey();
void do_combine_privkeys();
Expand Down

0 comments on commit a43374e

Please sign in to comment.