Skip to content

Commit

Permalink
feat: add bytes abi decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
as-iotex committed Apr 4, 2022
1 parent df8af01 commit 10b61f5
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
53 changes: 52 additions & 1 deletion src/abi/abiDecode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,55 @@ bool iotex::abi::decode::decodeBool(const char data[64])
{
// Bool is encoded as uint8. With the value of 1 for true and the value of 0 for false.
return data[63] == '1';
}
}

iotex::ResultCode iotex::abi::decode::decodeStaticBytes(const char* pData, size_t bytesSize, uint8_t out[])
{
// Bytes are left aliged and padded to the right with 0.
ResultCode res = signer.str2hex(pData, out, bytesSize, bytesSize*2);
return res;
}

iotex::ResultCode iotex::abi::decode::decodeDynamicBytes(const char* pData, std::vector<uint8_t>& out, bool includesHeader)
{
// Cheack size is enough to contain at least the header/size.
if (strlen(pData) < wordStrLen) { return ResultCode::ERROR_BAD_PARAMETER; }

const char* pBytesSize = pData;
if (includesHeader)
{
// Cheack size is enough to contain at least the header + offset
if (strlen(pData) < wordStrLen * 2) { return ResultCode::ERROR_BAD_PARAMETER; }

uint64_t offset = decodeUint64(pData);
pBytesSize += (offset*2);
}
size_t bytesCount = getDynamicArraySize(pBytesSize);

// Validate the size is enought to contain all the bytes.
size_t minimumSize = wordStrLen; // 1st word - Number of bytes
minimumSize += (bytesCount / 32) * wordStrLen; // Full words
minimumSize += (bytesCount % 32) * 2;
if (strlen(pBytesSize) < minimumSize) { return ResultCode::SUCCESS; }

// Move the pointer to the data.
const char* pByte = pBytesSize + wordStrLen;

out.reserve(bytesCount);
for (size_t i=0; i<bytesCount; i++)
{
uint8_t byte;
ResultCode res = signer.str2hex(pByte, &byte, 1, 2);
if (res != ResultCode::SUCCESS) { return res; }
out.push_back(byte);
// Move the pointer to the next byte.
pByte += 2;
}

return ResultCode::SUCCESS;
}

size_t iotex::abi::decode::getDynamicArraySize(const char* pData)
{
return decodeUint64(pData);
}
20 changes: 20 additions & 0 deletions src/abi/abiDecode.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,26 @@ iotex::ResultCode decodeString(const char* pData, size_t size, IotexString& out)
iotex::ResultCode decodeAddress(const char data[64], char out[ETH_ADDRESS_C_STRING_SIZE]);
bool decodeBool(const char data[64]);

/**
* @brief Decodes an ABI encoded static bytes value.
*
* @param pData The ABI encoded data.
* @param pData The nuber of bytes encoded.
* @param[out] out A pointer to a byte array where to store the decoded value. Must be able to hold at least bytesSize bytes.
*/
iotex::ResultCode decodeStaticBytes(const char* pData, size_t bytesSize, uint8_t out[]);

/**
* @brief Decodes an ABI encoded static bytes value.
*
* @param pData The ABI encoded data.
* @param pData The nuber of bytes encoded.
* @param[out] out A pointer to a byte array where to store the decoded value. Must be able to hold at least bytesSize bytes.
*/
iotex::ResultCode decodeDynamicBytes(const char* pData, std::vector<uint8_t>& out, bool includesHeader = true);


size_t getDynamicArraySize(const char* pData);

iotex::ResultCode decodeUintGeneric(const char* pData, size_t uintSize, uint64_t* out);
iotex::ResultCode decodeIntGeneric(const char* pData, size_t uintSize, int64_t* out);
Expand Down

0 comments on commit 10b61f5

Please sign in to comment.