Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom fields validation fix #429

Merged
merged 6 commits into from Mar 14, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion qa/rpc-tests/sc_big_block.py
Expand Up @@ -177,7 +177,7 @@ def advance_sidechains_epoch(num_of_scs):
vCfe = ["ab000100"]
vCmt = [BIT_VECTOR_BUF]

fe1 = "00000000000000000000000000000000000000000000000000000000" + "ab000100"
fe1 = "ab000100" + "00000000000000000000000000000000000000000000000000000000"
fe2 = BIT_VECTOR_FE

proofCfeArray = [fe1, fe2]
Expand Down
20 changes: 10 additions & 10 deletions qa/rpc-tests/sc_cert_customfields.py
Expand Up @@ -346,7 +346,7 @@ def run_test(self):
vCmt = []

# serialized fe for the proof has 32 byte size
fe1 = "000000000000000000000000000000000000000000000000000000000000" + "0100"
fe1 = "0100" + "000000000000000000000000000000000000000000000000000000000000"

scProof3 = mcTest.create_test_proof(
'sc2', scid2_swapped, epoch_number_1, 10, MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash_1, constant2, [addr_node1], [bwt_amount],
Expand Down Expand Up @@ -426,9 +426,9 @@ def run_test(self):
# with the one declared during sidechain creation.
vCmt = [BIT_VECTOR_BUF_NOT_POW2]

fe1 = "00000000000000000000000000000000000000000000000000000000" + "ab000100"
fe2 = "0000000000000000000000000000000000000000000000000000" + "ccccdddd0000"
fe3 = "000000000000000000000000000000000000000000000000000000000000" + "0100"
fe1 = "ab000100" + "00000000000000000000000000000000000000000000000000000000"
fe2 = "ccccdddd0000" + "0000000000000000000000000000000000000000000000000000"
fe3 = "0100" + "000000000000000000000000000000000000000000000000000000000000"
fe4 = BIT_VECTOR_FE

scProof3 = mcTest.create_test_proof(
Expand Down Expand Up @@ -466,9 +466,9 @@ def run_test(self):
# Such a bit vector should be rejected from the node.
vCmt = [BIT_VECTOR_BUF_HUGE]

fe1 = "00000000000000000000000000000000000000000000000000000000" + "ab000100"
fe2 = "0000000000000000000000000000000000000000000000000000" + "ccccdddd0000"
fe3 = "000000000000000000000000000000000000000000000000000000000000" + "0100"
fe1 = "ab000100" + "00000000000000000000000000000000000000000000000000000000"
fe2 = "ccccdddd0000" + "0000000000000000000000000000000000000000000000000000"
fe3 = "0100" + "000000000000000000000000000000000000000000000000000000000000"
fe4 = BIT_VECTOR_FE

scProof3 = mcTest.create_test_proof(
Expand Down Expand Up @@ -505,9 +505,9 @@ def run_test(self):
# this is a compressed buffer which will yield a valid field element for the proof (see below)
vCmt = [BIT_VECTOR_BUF]

fe1 = "00000000000000000000000000000000000000000000000000000000" + "ab000100"
fe2 = "0000000000000000000000000000000000000000000000000000" + "ccccdddd0000"
fe3 = "000000000000000000000000000000000000000000000000000000000000" + "0100"
fe1 = "ab000100" + "00000000000000000000000000000000000000000000000000000000"
fe2 = "ccccdddd0000" + "0000000000000000000000000000000000000000000000000000"
fe3 = "0100" + "000000000000000000000000000000000000000000000000000000000000"
fe4 = BIT_VECTOR_FE

scProof3 = mcTest.create_test_proof(
Expand Down
8 changes: 4 additions & 4 deletions qa/rpc-tests/sc_rpc_cmds_json_output.py
Expand Up @@ -326,7 +326,7 @@ def dump_json_getblocktemplate(fileName, nodeid=0):
vCmt = []

# serialized fe for the proof has 32 byte size
fe1 = "000000000000000000000000000000000000000000000000000000000000" + "0100"
fe1 = "0100" + "000000000000000000000000000000000000000000000000000000000000"

quality = 72
scProof3 = certMcTest.create_test_proof(
Expand Down Expand Up @@ -370,9 +370,9 @@ def dump_json_getblocktemplate(fileName, nodeid=0):
# this is a compressed buffer which will yield a valid field element for the proof (see below)
vCmt = [BIT_VECTOR_BUF]

fe1 = "00000000000000000000000000000000000000000000000000000000" + "ab000100"
fe2 = "0000000000000000000000000000000000000000000000000000" + "ccccdddd0000"
fe3 = "000000000000000000000000000000000000000000000000000000000000" + "0100"
fe1 = "ab000100" + "00000000000000000000000000000000000000000000000000000000"
fe2 = "ccccdddd0000" + "0000000000000000000000000000000000000000000000000000"
fe3 = "0100" + "000000000000000000000000000000000000000000000000000000000000"
fe4 = BIT_VECTOR_FE

quality = 18
Expand Down
23 changes: 23 additions & 0 deletions src/gtest/test_libzendoo.cpp
Expand Up @@ -1973,4 +1973,27 @@ TEST(CctpLibrary, TestInvalidProofVkWhenOversized)
EXPECT_FALSE(vkInvalid.IsValid());

//TODO: Might be useful to test the same behaviour with bit vector
}

TEST(CctpLibrary, TestCustomFieldsValidation)
{
for (uint8_t i = 1; i < CHAR_BIT; i++)
i-Alex marked this conversation as resolved.
Show resolved Hide resolved
{
for (uint8_t j = 1; j > 0; j++)
{
std::vector<unsigned char> rawBytes = { j };
FieldElementCertificateField certField = FieldElementCertificateField(rawBytes);
FieldElementCertificateFieldConfig config = FieldElementCertificateFieldConfig(i);
CFieldElement fe = certField.GetFieldElement(config);

if (j < 1 << i)
{
EXPECT_TRUE(fe.IsValid());
}
else
{
EXPECT_FALSE(fe.IsValid());
}
}
}
}
4 changes: 2 additions & 2 deletions src/sc/sidechaintypes.cpp
Expand Up @@ -595,7 +595,7 @@ const CFieldElement& FieldElementCertificateField::GetFieldElement(const FieldEl
{
// check null bits in the last byte are as expected
unsigned char lastByte = vRawData.back();
int numbOfZeroBits = getTrailingZeroBitsInByte(lastByte);
int numbOfZeroBits = getLeadingZeroBitsInByte(lastByte);
if (numbOfZeroBits < (CHAR_BIT - rem))
{
LogPrint("sc", "%s():%d - ERROR: wrong number of null bits in last byte[0x%x]: %d vs %d\n",
Expand All @@ -605,7 +605,7 @@ const CFieldElement& FieldElementCertificateField::GetFieldElement(const FieldEl
}

std::vector<unsigned char> extendedRawData = vRawData;
extendedRawData.insert(extendedRawData.begin(), CFieldElement::ByteSize()-vRawData.size(), 0x0);
extendedRawData.insert(extendedRawData.end(), CFieldElement::ByteSize() - vRawData.size(), 0x0);

fieldElement.SetByteArray(extendedRawData);
if (fieldElement.IsValid())
Expand Down
21 changes: 8 additions & 13 deletions src/util.cpp
Expand Up @@ -17,6 +17,7 @@
#include "utiltime.h"

#include <stdarg.h>
#include <stdio.h>

#if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
#include <pthread.h>
Expand Down Expand Up @@ -934,21 +935,15 @@ int GetNumCores()
return boost::thread::physical_concurrency();
}

int getTrailingZeroBitsInByte(unsigned char inputByte)
int getLeadingZeroBitsInByte(unsigned char inputByte)
{
// output: c will count inputByte's trailing zero bits,
// so if inputByte is 1101000 (base 2), then c will be 3
int c = CHAR_BIT;
// Behavior of __builtin_clz() is undefined for zero input, so we need to handle this case explicitly.
if (inputByte == 0)
return 8;

if (inputByte)
{
inputByte = (inputByte ^ (inputByte - 1)) >> 1; // Set inputByte's trailing 0s to 1s and zero rest
for (c = 0; inputByte; c++)
{
inputByte >>= 1;
}
}
return c;
// __builtin_clz() returns the number of leading zeros for an unsigned int, so we need to perform a
// conversion to use it for an unsigned char.
return __builtin_clz(inputByte) % (sizeof(unsigned int) * 8 - CHAR_BIT);
i-Alex marked this conversation as resolved.
Show resolved Hide resolved
}

int getBytesFromBits(int nbits, int& reminder)
Expand Down
2 changes: 1 addition & 1 deletion src/util.h
Expand Up @@ -296,7 +296,7 @@ std::string dbg_blk_unlinked();
std::string dbg_blk_candidates();
std::string dbg_blk_global_tips();

int getTrailingZeroBitsInByte(unsigned char inputByte);
int getLeadingZeroBitsInByte(unsigned char inputByte);
int getBytesFromBits(int nbits, int& reminder);

#endif // BITCOIN_UTIL_H