Skip to content

Commit

Permalink
contracts: minor feedback on CBOR library docs
Browse files Browse the repository at this point in the history
  • Loading branch information
CedarMist committed Oct 28, 2024
1 parent d09a36d commit 7498c4e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 33 deletions.
46 changes: 30 additions & 16 deletions contracts/contracts/CBOR.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,35 @@
pragma solidity ^0.8.0;

/// While parsing CBOR map, unexpected key
error CBOR_Error_InvalidKey();
error CBOR_InvalidKey();

/// While parsing CBOR map, length is invalid, or other parse error
error CBOR_Error_InvalidMap();
error CBOR_InvalidMap();

/// While parsing CBOR structure, data length was unexpected
error CBOR_Error_InvalidLength(uint256);
error CBOR_InvalidLength(uint256);

/// Value cannot be parsed as a uint
error CBOR_Error_InvalidUintPrefix(uint8);
error CBOR_InvalidUintPrefix(uint8);

/// Unsigned integer of unknown size
error CBOR_Error_InvalidUintSize(uint8);
/// CBOR spec supports, 1, 2, 4 & 8 byte uints. Caused by parse error.
error CBOR_InvalidUintSize(uint8);

/// CBOR parsed value is out of expected range
error CBOR_Error_ValueOutOfRange();
error CBOR_Error_ValueOutOfRange(uint256 value, uint256 maxValue);

/// Buffer too short to parse expected value
error CBOR_Error_BufferOverrun(uint256 len, uint256 offset, uint256 need);

/// @notice Byte array is too long
/// @dev Solidity has 256bit length prefixes for byte arrays. We decided for
/// a reasonable cutoff point (64kb), so at most a 2-byte uint describing
/// the array length.
error CBOR_Error_BytesTooLong(uint256 byteLength);

/// @dev we don't follow bignum tagged encoding
/// See: https://www.rfc-editor.org/rfc/rfc8949.html#section-3.4.3
function encodeUint(uint256 value) pure returns (bytes memory) {
// NOTE: we don't follow bignum tagged encoding
// See: https://www.rfc-editor.org/rfc/rfc8949.html#section-3.4.3
if (value < 24) {
return abi.encodePacked(uint8(value));
} else if (value <= type(uint8).max) {
Expand Down Expand Up @@ -71,7 +78,7 @@ function parseMapStart(bytes memory in_data, uint256 in_offset)
{
uint256 b = uint256(uint8(in_data[in_offset]));
if (b < 0xa0 || b > 0xb7) {
revert CBOR_Error_InvalidMap();
revert CBOR_InvalidMap();
}

n_entries = b - 0xa0;
Expand Down Expand Up @@ -108,16 +115,21 @@ function parseUint(bytes memory result, uint256 offset)
} else if (prefix == 0x1b) {
len = 8;
} else {
revert CBOR_Error_InvalidUintSize(prefix);
// Falls outside of the CBOR spec, tagged as uint, but unsupported
revert CBOR_InvalidUintSize(prefix);
}
offset += 1;
}
// Unknown...
else {
revert CBOR_Error_InvalidUintPrefix(prefix);
revert CBOR_InvalidUintPrefix(prefix);
}

if (len > 0x20) revert CBOR_Error_InvalidLength(len);
// Exceeds what can be represented by a 256bit word
if (len > 0x20) revert CBOR_InvalidLength(len);

if (offset + len > result.length)
revert CBOR_Error_BufferOverrun(result.length, offset, len);

// Load 32 bytes from the buffer at the given offset
assembly {
Expand All @@ -138,7 +150,8 @@ function parseUint64(bytes memory result, uint256 offset)

(newOffset, tmp) = parseUint(result, offset);

if (tmp > type(uint64).max) revert CBOR_Error_ValueOutOfRange();
if (tmp > type(uint64).max)
revert CBOR_Error_ValueOutOfRange(tmp, type(uint64).max);

value = uint64(tmp);
}
Expand All @@ -151,7 +164,8 @@ function parseUint128(bytes memory result, uint256 offset)

(newOffset, tmp) = parseUint(result, offset);

if (tmp > type(uint128).max) revert CBOR_Error_ValueOutOfRange();
if (tmp > type(uint128).max)
revert CBOR_Error_ValueOutOfRange(tmp, type(uint128).max);

value = uint128(tmp);
}
Expand All @@ -160,7 +174,7 @@ function parseKey(bytes memory result, uint256 offset)
pure
returns (uint256 newOffset, bytes32 keyDigest)
{
if (result[offset] & 0x60 != 0x60) revert CBOR_Error_InvalidKey();
if (result[offset] & 0x60 != 0x60) revert CBOR_InvalidKey();

uint8 len = uint8(result[offset++]) ^ 0x60;

Expand Down
41 changes: 24 additions & 17 deletions contracts/contracts/Subcall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ library Subcall {

error AccountsTransferError(uint64 status, string data);

/// Expected map of different size!
error WrongMapSizeError();

/// Unknown type of receipt!
error TakeReceiptKindOutOfRange(uint receiptKind);

/// The origin is not authorized for the given ROFL app
error RoflOriginNotAuthorizedForApp();

Expand All @@ -63,6 +69,9 @@ library Subcall {
/// CBOR parser expected a key, but it was not found in the map!
error MissingKey();

/// We expected to have parsed everything, but there are excess bytes!
error IncompleteParse();

/// Error while trying to retrieve current epoch
error CoreCurrentEpochError(uint64);

Expand Down Expand Up @@ -176,7 +185,7 @@ library Subcall {
if (receiptId == 0) revert InvalidReceiptId();

if (uint256(kind) == 0 || uint256(kind) > 23)
revert CBOR.CBOR_Error_ValueOutOfRange();
revert TakeReceiptKindOutOfRange(uint256(kind));

(bool success, bytes memory data) = SUBCALL.call( // solhint-disable-line
abi.encode(
Expand Down Expand Up @@ -224,7 +233,8 @@ library Subcall {

bool hasReceipt = false;

if (result[0] != 0xA2) revert CBOR.CBOR_Error_InvalidMap();
// Expects map with 2 pairs
if (result[0] != 0xA2) revert WrongMapSizeError();

while (offset < result.length) {
bytes32 keyDigest;
Expand Down Expand Up @@ -254,7 +264,8 @@ library Subcall {

bool hasAmount = false;

if (result[0] != 0xA1) revert CBOR.CBOR_Error_InvalidMap();
// Expects map with 1 pair
if (result[0] != 0xA1) revert WrongMapSizeError();

while (offset < result.length) {
bytes32 keyDigest;
Expand All @@ -281,19 +292,15 @@ library Subcall {
pure
returns (uint128 shares)
{
if (result[0] != 0xA1) revert CBOR.CBOR_Error_InvalidMap();
// Expects map with 1 pair
if (result[0] != 0xA1) revert WrongMapSizeError();

if (result[0] == 0xA1 && result[1] == 0x66 && result[2] == "s") {
// Delegation succeeded, decode number of shares.
uint8 sharesLen = uint8(result[8]) & 0x1f; // Assume shares field is never greater than 16 bytes.

if (9 + sharesLen != result.length)
revert CBOR.CBOR_Error_InvalidLength(sharesLen);

for (uint256 offset = 0; offset < sharesLen; offset++) {
uint8 v = uint8(result[9 + offset]);

shares += uint128(v) << (8 * uint128(sharesLen - offset - 1));
uint newOffset;
(newOffset,shares) = CBOR.parseUint128(result, 8);
if( newOffset != result.length ) {
revert IncompleteParse();
}
} else {
revert ParseReceiptError(receiptId);
Expand Down Expand Up @@ -566,12 +573,12 @@ library Subcall {
);
} else if (keyDigest == keccak256("signature")) {
if (in_data[offset++] != 0x58) {
revert CBOR.CBOR_Error_InvalidUintPrefix(
revert CBOR.CBOR_InvalidUintPrefix(
uint8(in_data[offset - 1])
);
}
if (in_data[offset++] != 0x40) {
revert CBOR.CBOR_Error_InvalidUintSize(
revert CBOR.CBOR_InvalidUintSize(
uint8(in_data[offset - 1])
);
}
Expand All @@ -587,7 +594,7 @@ library Subcall {

offset += 0x40;
} else {
revert CBOR.CBOR_Error_InvalidKey();
revert CBOR.CBOR_InvalidKey();
}
}
}
Expand All @@ -614,7 +621,7 @@ library Subcall {
offset
);
} else {
revert CBOR.CBOR_Error_InvalidKey();
revert CBOR.CBOR_InvalidKey();
}
}
}
Expand Down

0 comments on commit 7498c4e

Please sign in to comment.