Skip to content

Commit

Permalink
fix(sc): fix incorrect emitting of numbers in ScriptBuilder (#913)
Browse files Browse the repository at this point in the history
  • Loading branch information
ixje authored Aug 30, 2023
1 parent b419005 commit 7ddb0e6
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 9 deletions.
1 change: 1 addition & 0 deletions docs/changelog/v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ sidebar_position: 1

# 5.5.1
- sc
- Fix incorrect emitting of numbers in `ScriptBuilder`.
- Add support for `Map` type in `emitContractParam` function.

# 5.5.0
Expand Down
7 changes: 7 additions & 0 deletions packages/neon-core/__tests__/sc/ScriptBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,13 @@ describe("emitNumber", () => {
["long min", "-9223372036854775808", "030000000000000080"],
["long max", "9223372036854775807", "03ffffffffffffff7f"],
["ulong max", "18446744073709551615", "04ffffffffffffffff0000000000000000"],
["pushint8", 0x1f, "001f"],
["pushint16", 0xff, "01ff00"],
["pushin32", 0xffff, "02ffff0000"],
["pushint64", 0xffffffff, "03ffffffff00000000"],
["issue #911 #1", -129, "017fff"],
["issue #911 #2", -150, "016aff"],
["issue #911 #3", -255, "0101ff"],
])("%s", (_msg: string, data: number | string, expected: string) => {
const result = new ScriptBuilder().emitNumber(data).build();
expect(result).toBe(expected);
Expand Down
28 changes: 19 additions & 9 deletions packages/neon-core/src/sc/ScriptBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import BN from "bn.js";
import {
ab2hexstring,
BigInteger,
HexString,
int2hex,
num2hexstring,
Expand Down Expand Up @@ -229,20 +229,17 @@ export class ScriptBuilder extends StringStream {
return this.emit(OpCode.PUSH0 + bn.toNumber());
}
const negative = bn.isNeg();
const msbSet = bn.testn(bn.byteLength() * 8 - 1);
const occupiedBytes = bn.byteLength();
const targetBytes = this.roundToBestIntSize(
!negative && msbSet ? occupiedBytes + 1 : occupiedBytes
);
const bigint = BigInteger.fromNumber(num);
const occupiedBytes = bigint.toReverseTwos().length / 2;
const targetBytes = this.roundToBestIntSize(occupiedBytes);

// Catch case 64
if (targetBytes > 32) {
throw new Error(`Number too long to be emitted: ${num.toString()}`);
}

const hex = ab2hexstring(
bn.toTwos(bn.byteLength() * 8).toArray("le", targetBytes)
);
let hex = bigint.toReverseTwos();
hex = this.padRight(hex, targetBytes, negative);

switch (targetBytes) {
case 1:
Expand Down Expand Up @@ -282,6 +279,19 @@ export class ScriptBuilder extends StringStream {
}
}

private padRight(
data: string,
targetLength: number,
isSigned: boolean
): string {
if (data.length / 2 >= targetLength) return data;
const pad = isSigned ? "ff" : "00";
while (data.length / 2 != targetLength) {
data = data + pad;
}
return data;
}

/**
* Private method to append a ContractParam
*/
Expand Down

0 comments on commit 7ddb0e6

Please sign in to comment.