Skip to content

Commit

Permalink
chore: cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
antoncoding committed Dec 29, 2023
1 parent daefd00 commit 220ce5d
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 17 deletions.
72 changes: 58 additions & 14 deletions src/periphery/CompressedSubmitter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import "openzeppelin/access/Ownable2Step.sol";
import "../interfaces/IBaseManager.sol";
import "../interfaces/IDataReceiver.sol";

import "../interfaces/IBaseLyraFeed.sol";

import "forge-std/console2.sol";

contract CompressedSubmitter is IDataReceiver, Ownable2Step {
Expand All @@ -22,7 +24,7 @@ contract CompressedSubmitter is IDataReceiver, Ownable2Step {
* @dev submit compressed data directly (not through the manager)
*/
function submitCompressedData(bytes calldata data) external {
IBaseManager.ManagerData[] memory feedDatas = _parseFeedDataArray(data);
IBaseManager.ManagerData[] memory feedDatas = _parseCompressedToFeedDatas(data);

for (uint i; i < feedDatas.length; i++) {
IDataReceiver(feedDatas[i].receiver).acceptData(feedDatas[i].data);
Expand All @@ -34,7 +36,7 @@ contract CompressedSubmitter is IDataReceiver, Ownable2Step {
* Data is compressed into bytes
*/
function acceptData(bytes calldata data) external {
IBaseManager.ManagerData[] memory feedDatas = _parseFeedDataArray(data);
IBaseManager.ManagerData[] memory feedDatas = _parseCompressedToFeedDatas(data);

Check warning on line 39 in src/periphery/CompressedSubmitter.sol

View check run for this annotation

Codecov / codecov/patch

src/periphery/CompressedSubmitter.sol#L39

Added line #L39 was not covered by tests

for (uint i; i < feedDatas.length; i++) {
IDataReceiver(feedDatas[i].receiver).acceptData(feedDatas[i].data);

Check warning on line 42 in src/periphery/CompressedSubmitter.sol

View check run for this annotation

Codecov / codecov/patch

src/periphery/CompressedSubmitter.sol#L41-L42

Added lines #L41 - L42 were not covered by tests
Expand All @@ -56,10 +58,7 @@ contract CompressedSubmitter is IDataReceiver, Ownable2Step {
emit FeedIdRegistered(id, signer);
}

function _parseFeedDataArray(bytes calldata data) internal returns (IBaseManager.ManagerData[] memory) {
bytes memory data2 = data[0:1];
console2.logBytes(data2);

function _parseCompressedToFeedDatas(bytes calldata data) internal returns (IBaseManager.ManagerData[] memory) {
// first byte of each byte array is number of feeds
uint8 numFeeds = sliceUint8(data, 1);

Expand Down Expand Up @@ -89,9 +88,61 @@ contract CompressedSubmitter is IDataReceiver, Ownable2Step {

/**
* The raw feed data doesn't have signer addresses encoded, so here we attach them, and build FeedData struct
* Parse the following bytes format
* 4 bytes: length of data (uint32) --> l
* [l] bytes: data;
* 8 bytes: deadline (uint64)
* 8 bytes: timestamp (uint64)
* 1 byte: number of signers (uint8) --> k
* [20 x k] bytes address[] signers;
* [65 x k] bytes[] signatures;
*/
function buildFeedDataFromRaw(bytes calldata data) internal view returns (bytes memory) {
return data;
IBaseLyraFeed.FeedData memory feedData;

uint offset = 0;

// 4 bytes of data length
uint length = bytesToUint(data[offset:offset + 4]);
offset += 4;

// [length] bytes of data
feedData.data = data[offset:offset + length];
offset += length;

// 8 bytes of deadline
feedData.deadline = uint64(bytesToUint(data[offset:offset + 8]));
offset += 8;

// 8 bytes of timestamp
feedData.timestamp = uint64(bytesToUint(data[offset:offset + 8]));
offset += 8;

{
// 1 byte of number of signers
uint8 numSigners = uint8(bytesToUint(data[offset:offset + 1]));
offset += 1;

// [20 x k] bytes address[] signers;
address[] memory _signers = new address[](numSigners);
for (uint i; i < numSigners; i++) {
bytes calldata signerIdData = data[offset:offset + 20];
_signers[i] = address(uint160(bytesToUint(signerIdData)));
offset += 20;
}
feedData.signers = _signers;

// [65 x k] bytes[] signatures;
bytes[] memory signatures = new bytes[](numSigners);
for (uint i; i < numSigners; i++) {
bytes calldata signatureData = data[offset:offset + 65];
signatures[i] = signatureData;
offset += 65;
}

feedData.signatures = signatures;
}
return abi.encode(feedData);
}

/// read a single byte and return it as a uint8
Expand All @@ -101,13 +152,6 @@ contract CompressedSubmitter is IDataReceiver, Ownable2Step {
}
}

// read 4 bytes and return as uint32
function sliceUint32(bytes memory bs, uint location) internal pure returns (uint32 x) {
assembly {
x := mload(add(bs, location))
}
}

function bytesToUint(bytes memory b) internal pure returns (uint num) {
for (uint i = 0; i < b.length; i++) {
num = num + uint(uint8(b[i])) * (2 ** (8 * (b.length - (i + 1))));
Expand Down
55 changes: 52 additions & 3 deletions test/feed/integration-tests/CompressedSubmitter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ contract CompressedSubmitterTest is LyraFeedTestUtils {
function testSubmitBatchData() public {
// prepare raw data
IBaseLyraFeed.FeedData memory spotData1 = _getDefaultSpotData();
bytes memory data1 = _signFeedData(spotFeed1, pk, spotData1);

bytes memory data1 = _transformToCompressedFeedData(_signFeedData(spotFeed1, pk, spotData1));

IBaseLyraFeed.FeedData memory spotData2 = _getDefaultSpotData();
bytes memory data2 = _signFeedData(spotFeed2, pk, spotData2);
bytes memory data2 = _transformToCompressedFeedData(_signFeedData(spotFeed2, pk, spotData2));

uint32 data1Length = uint32(data1.length);
uint32 data2Length = uint32(data2.length);
Expand All @@ -47,7 +48,7 @@ contract CompressedSubmitterTest is LyraFeedTestUtils {
// bytes[] memory managerDatas = new bytes[](2);
bytes memory compressedData = abi.encodePacked(numOfFeeds, feedId1, data1Length, data1, feedId2, data2Length, data2);

console2.log("length", compressedData.length);
console2.log("final compressed data length", compressedData.length);

submitter.submitCompressedData(compressedData);

Expand All @@ -73,4 +74,52 @@ contract CompressedSubmitterTest is LyraFeedTestUtils {
signatures: new bytes[](1)
});
}

/**
* Convert abi encoded bytes to the following format:
*
* 4 bytes: length of data (uint32) --> l
* [l] bytes: data;
* 8 bytes: deadline (uint64)
* 8 bytes: timestamp (uint64)
* 1 byte: number of signers (uint8) --> k
* [20 x k] bytes address[] signers;
* [65 x k] bytes[] signatures;
*/
function _transformToCompressedFeedData(bytes memory data) internal view returns (bytes memory) {
IBaseLyraFeed.FeedData memory feedData = abi.decode(data, (IBaseLyraFeed.FeedData));
uint32 length = uint32(feedData.data.length);
uint8 numOfSigners = uint8(feedData.signers.length);

// put all signers into a single bytes array (20 bytes each)
bytes memory signers = new bytes(numOfSigners * 20);
for (uint i; i < numOfSigners; i++) {
bytes memory signer = abi.encodePacked(feedData.signers[i]);
for (uint j; j < signer.length; j++) {
signers[i * 20 + j] = signer[j];
}
}

// pad signatures to 65 bytes and form packed bytes
bytes memory signatures = new bytes(numOfSigners * 65);

for (uint i; i < numOfSigners; i++) {
bytes memory signature = feedData.signatures[i];
for (uint j; j < signature.length; j++) {
signatures[i * 65 + j] = signature[j];
}
}

bytes memory compressedData = abi.encodePacked(
length,
feedData.data,
uint64(feedData.deadline),
uint64(feedData.timestamp),
uint8(feedData.signers.length),
signers,
signatures
);

return compressedData;
}
}

0 comments on commit 220ce5d

Please sign in to comment.