Page MenuHomePhabricator

Add function to trim leading array zeros maintaining MSB.
ClosedPublic

Authored by jasonbcox on Mar 18 2018, 09:35.

Details

Summary

Add a function MinimalizeBigEndianArray to trim a byte array
of leading zeros, while maintaining any MSB for negation. This
will get used in BIN2NUM in a later patch.

Co-authored-by: Shammah Chancellor <shammah.chancellor@gmail.com>

Test Plan

make check

Diff Detail

Repository
rABC Bitcoin ABC
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

schancel retitled this revision from Add function to trim leading array zeros maitaining MSB. to Add function to trim leading array zeros maintaining MSB..Mar 18 2018, 10:11
src/test/script_tests.cpp
431 ↗(On Diff #3287)

Some additional tests to ensure behavior is an inverse match for IsMinimalArray (apologies for redeclaring all the variables each time, not sure of correct C++ syntax)

	//case: 0x00 00 80 -> 0x 00 80
	//case: 0x80 00 80 -> 0x80 80
	
	std::vector<uint8_t> input({{0x00, 0x00, 0x80}});
    std::vector<uint8_t> negInput({{0x80, 0x00, 0x80}});

    std::vector<uint8_t> check({0x00, 0x80});
    std::vector<uint8_t> negCheck({0x80, 0x80});

    std::vector<uint8_t> out = MinimalizeBigEndianArray(input);
    std::vector<uint8_t> negOut = MinimalizeBigEndianArray(negInput);

    BOOST_CHECK(out == check);
    BOOST_CHECK(negOut == negCheck);
	
	//case: 0x00 80 -> 0x00 80
	//case: 0x80 80 -> 0x80 80
	
	std::vector<uint8_t> input({{0x00, 0x80}});
    std::vector<uint8_t> negInput({{0x80, 0x80}});

    std::vector<uint8_t> check({0x00, 0x80});
    std::vector<uint8_t> negCheck({0x80, 0x80});

    std::vector<uint8_t> out = MinimalizeBigEndianArray(input);
    std::vector<uint8_t> negOut = MinimalizeBigEndianArray(negInput);

    BOOST_CHECK(out == check);
    BOOST_CHECK(negOut == negCheck);
	

	//case: 0x00 00 0f -> 0x0f
	//case: 0x80 00 0f -> 0x8f
	
	std::vector<uint8_t> input({{0x00, 0x00, 0x0f}});
    std::vector<uint8_t> negInput({{0x80, 0x00, 0x0f}});

    std::vector<uint8_t> check({0x0f});
    std::vector<uint8_t> negCheck({0x8f});

    std::vector<uint8_t> out = MinimalizeBigEndianArray(input);
    std::vector<uint8_t> negOut = MinimalizeBigEndianArray(negInput);

    BOOST_CHECK(out == check);
    BOOST_CHECK(negOut == negCheck);


	//case: 0x00 0f -> 0x0f
	//case: 0x80 0f -> 0x8f
	
	std::vector<uint8_t> input({{0x00, 0x0f}});
    std::vector<uint8_t> negInput({{0x80, 0x0f}});

    std::vector<uint8_t> check({0x0f});
    std::vector<uint8_t> negCheck({0x8f});

    std::vector<uint8_t> out = MinimalizeBigEndianArray(input);
    std::vector<uint8_t> negOut = MinimalizeBigEndianArray(negInput);

    BOOST_CHECK(out == check);
    BOOST_CHECK(negOut == negCheck);
src/test/script_tests.cpp
431 ↗(On Diff #3287)

One more:

//case: 0x00 00 8f 00 00 01 -> 0x 00 8f 00 00 01
jasonbcox requested changes to this revision.Mar 18 2018, 15:43
jasonbcox added inline comments.
src/script/script.cpp
277 ↗(On Diff #3287)

msb -> neg since this is no longer the msb

278 ↗(On Diff #3287)

This can be interpreted as "isStart" in which case init as false is confusing. Please rename to something like pushedRes or hasPushedResult.

src/test/script_tests.cpp
431 ↗(On Diff #3287)

Need to check these cases:
Empty array,
0x00 -> 0x00,
0x00 0x00 0x00 0x00 -> 0x00,
0xff 0xff 0xff 0xff -> 0xff 0xff 0xff 0xff

This revision now requires changes to proceed.Mar 18 2018, 15:43
src/test/script_tests.cpp
431 ↗(On Diff #3287)

Scratch the last case. Should be 0x7f 0xff 0xff 0xff -> 0x7f 0xff 0xff 0xff

src/script/script.cpp
284 ↗(On Diff #3287)

Found a bug while writing tests: This line skips all instances of {0x00 ... 0x00} and returns empty list.

jasonbcox edited reviewers, added: schancel; removed: jasonbcox.
jasonbcox added a reviewer: deadalnix.
This revision is now accepted and ready to land.Mar 18 2018, 20:08
This revision was automatically updated to reflect the committed changes.
src/script/script.cpp
310
for (uint8_t x : data) {
    // ...
}
src/test/script_tests.cpp
456

A few test case made of a test input + expected result is necessary. They ensure that you did not have the same bug in the test and the implementation - which you both did, so that's actually very likely. They also constitute reusable material from someone wanting to build a compatible system.