Skip to content

Commit

Permalink
feat: parse validator indexes as arrays from solidity
Browse files Browse the repository at this point in the history
  • Loading branch information
merklefruit committed Jul 5, 2024
1 parent 025d296 commit d9c722a
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 5 deletions.
74 changes: 69 additions & 5 deletions bolt-contracts/script/RegisterValidators.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@ contract RegisterValidators is Script {
uint64[] public validatorIndexes;
address public registryAddress = 0xdF11D829eeC4C192774F3Ec171D822f6Cb4C14d9;

using StringToUintArrayLib for string;

function run() public {
signerKey = vm.envUint("PRIVATE_KEY");
string[] memory indexStrings = vm.envString("VALIDATOR_INDEXES", ",");
string memory rpc = vm.envString("RPC_ADDR");
vm.startBroadcast(signerKey);

string memory validatorIndexesEnv = vm.envString("VALIDATOR_INDEXES");
uint256[] memory indexes = StringToUintArrayLib.fromStr(validatorIndexesEnv);
for (uint256 i = 0; i < indexes.length; i++) {
validatorIndexes.push(uint64(indexes[i]));
}

console.log("Bolt registry address:", registryAddress);
BoltRegistry registry = BoltRegistry(registryAddress);

Expand All @@ -33,10 +40,6 @@ contract RegisterValidators is Script {
revert("Insufficient balance");
}

for (uint256 i = 0; i < indexStrings.length; i++) {
validatorIndexes.push(uint64(vm.parseUint(indexStrings[i])));
}

// Register with minimal collateral
registry.register{value: registry.MINIMUM_COLLATERAL()}(
validatorIndexes,
Expand All @@ -47,3 +50,64 @@ contract RegisterValidators is Script {
vm.stopBroadcast();
}
}

library StringToUintArrayLib {
// Maximum number of validators parsed in a single function call
uint256 constant MAX_VALIDATORS = 256;

function fromStr(string memory s) internal pure returns (uint256[] memory) {
bytes memory strBytes = bytes(s);
uint256[] memory vec = new uint256[](MAX_VALIDATORS); // Initial allocation, will resize later
uint256 vecIndex = 0;
uint256 tempNum;
bool parsingRange = false;
uint256 rangeStart;

for (uint256 i = 0; i < strBytes.length; i++) {
if (strBytes[i] == ',') {
if (parsingRange) {
// Handle end of range
for (uint256 j = rangeStart; j <= tempNum; j++) {
vec[vecIndex] = j;
vecIndex++;
}
parsingRange = false;
} else {
// Handle single number
vec[vecIndex] = tempNum;
vecIndex++;
}
tempNum = 0;
} else if (strBytes[i] == '.') {
if (i + 1 < strBytes.length && strBytes[i + 1] == '.') {
// Handle start of range
parsingRange = true;
rangeStart = tempNum;
tempNum = 0;
i++; // Skip next dot
}
} else if (strBytes[i] >= '0' && strBytes[i] <= '9') {
tempNum = tempNum * 10 + (uint8(strBytes[i]) - 48); // Convert ASCII to integer
}
}

// Handle the last part after the final comma (or single number/range end)
if (parsingRange) {
for (uint256 j = rangeStart; j <= tempNum; j++) {
vec[vecIndex] = j;
vecIndex++;
}
} else {
vec[vecIndex] = tempNum;
vecIndex++;
}

// Resize array to actual size
uint256[] memory result = new uint256[](vecIndex);
for (uint256 i = 0; i < vecIndex; i++) {
result[i] = vec[i];
}

return result;
}
}
82 changes: 82 additions & 0 deletions bolt-contracts/test/StringToUintArrayLib.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "../script/RegisterValidators.s.sol";

contract StringToUintArrayTest is Test {

function setUp() public {}

function testParseValidatorIndexes1() public pure {
uint256[] memory indexes = StringToUintArrayLib.fromStr("1,2,3,4");
uint256[4] memory expected;
expected[0] = 1;
expected[1] = 2;
expected[2] = 3;
expected[3] = 4;

assertEq(indexes.length, expected.length);
for (uint256 i = 0; i < indexes.length; i++) {
assertEq(indexes[i], expected[i]);
}
}

function testParseValidatorIndexes2() public pure {
uint256[] memory indexes = StringToUintArrayLib.fromStr("1..4");
uint256[4] memory expected;
expected[0] = 1;
expected[1] = 2;
expected[2] = 3;
expected[3] = 4;

assertEq(indexes.length, expected.length);
for (uint256 i = 0; i < indexes.length; i++) {
assertEq(indexes[i], expected[i]);
}
}

function testParseValidatorIndexes3() public pure {
uint256[] memory indexes = StringToUintArrayLib.fromStr("1..4,6..8");
uint256[7] memory expected;
expected[0] = 1;
expected[1] = 2;
expected[2] = 3;
expected[3] = 4;
expected[4] = 6;
expected[5] = 7;
expected[6] = 8;

assertEq(indexes.length, expected.length);
for (uint256 i = 0; i < indexes.length; i++) {
assertEq(indexes[i], expected[i]);
}
}

function testParseValidatorIndexes4() public pure {
uint256[] memory indexes = StringToUintArrayLib.fromStr("1,2..4,6..8");
uint256[7] memory expected;
expected[0] = 1;
expected[1] = 2;
expected[2] = 3;
expected[3] = 4;
expected[4] = 6;
expected[5] = 7;
expected[6] = 8;

assertEq(indexes.length, expected.length);
for (uint256 i = 0; i < indexes.length; i++) {
assertEq(indexes[i], expected[i]);
}
}

function testParse100Indexes() public pure {
string memory input = "1..100";

uint256[] memory indexes = StringToUintArrayLib.fromStr(input);
assertEq(indexes.length, 100);
for (uint256 i = 0; i < indexes.length; i++) {
assertEq(indexes[i], i + 1);
}
}
}

0 comments on commit d9c722a

Please sign in to comment.