Skip to content

Commit

Permalink
Replace pubkeyHashToValidatorID by pubkeyAddressToValidatorID (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
thaarok authored Nov 5, 2024
1 parent 1e9b6a1 commit df772a2
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 9 deletions.
2 changes: 2 additions & 0 deletions contracts/interfaces/ISFC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ interface ISFC {

function getValidatorPubkey(uint256) external view returns (bytes memory);

function pubkeyAddressToValidatorID(address pubkeyAddress) external view returns (uint256);

function getWithdrawalRequest(
address,
uint256,
Expand Down
17 changes: 11 additions & 6 deletions contracts/sfc/SFC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ contract SFC is Initializable, Ownable, Version {
// the governance contract (to recalculate votes when the stake changes)
address public voteBookAddress;

// keccak256(pubkey bytes) => validator ID (prevents using the same key by multiple validators)
mapping(bytes32 pubkeyHash => uint256 validatorID) internal pubkeyHashToValidatorID;
// address derived from the validator pubkey => validator id
mapping(address pubkeyAddress => uint256 validatorID) public pubkeyAddressToValidatorID;

// address authorized to initiate redirection
address public redirectionAuthorizer;
Expand Down Expand Up @@ -358,7 +358,7 @@ contract SFC is Initializable, Ownable, Version {
if (pubkey.length != 66 || pubkey[0] != 0xc0) {
revert MalformedPubkey();
}
if (pubkeyHashToValidatorID[keccak256(pubkey)] != 0) {
if (pubkeyAddressToValidatorID[_pubkeyToAddress(pubkey)] != 0) {
revert PubkeyUsedByOtherValidator();
}
_createValidator(msg.sender, pubkey);
Expand Down Expand Up @@ -932,7 +932,7 @@ contract SFC is Initializable, Ownable, Version {
}

/// Create a new validator.
function _createValidator(address auth, bytes memory pubkey) internal {
function _createValidator(address auth, bytes calldata pubkey) internal {
uint256 validatorID = ++lastValidatorID;
_rawCreateValidator(auth, validatorID, pubkey, OK_STATUS, currentEpoch(), _now(), 0, 0);
}
Expand All @@ -941,7 +941,7 @@ contract SFC is Initializable, Ownable, Version {
function _rawCreateValidator(
address auth,
uint256 validatorID,
bytes memory pubkey,
bytes calldata pubkey,
uint256 status,
uint256 createdEpoch,
uint256 createdTime,
Expand All @@ -959,7 +959,7 @@ contract SFC is Initializable, Ownable, Version {
getValidator[validatorID].deactivatedEpoch = deactivatedEpoch;
getValidator[validatorID].auth = auth;
getValidatorPubkey[validatorID] = pubkey;
pubkeyHashToValidatorID[keccak256(pubkey)] = validatorID;
pubkeyAddressToValidatorID[_pubkeyToAddress(pubkey)] = validatorID;

emit CreatedValidator(validatorID, auth, createdEpoch, createdTime);
if (deactivatedEpoch != 0) {
Expand Down Expand Up @@ -1068,6 +1068,11 @@ contract SFC is Initializable, Ownable, Version {
return (rawReward * commission) / Decimal.unit();
}

/// Derive address from validator private key
function _pubkeyToAddress(bytes calldata pubkey) private pure returns (address) {
return address(uint160(uint256(keccak256(pubkey[2:]))));
}

/// Get current time.
function _now() internal view virtual returns (uint256) {
return block.timestamp;
Expand Down
13 changes: 10 additions & 3 deletions test/SFC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,9 +394,9 @@ describe('SFC', () => {
const node = new BlockchainNode(this.sfc);
const [validator, secondValidator] = await ethers.getSigners();
const pubkey =
'0xc000a2941866e485442aa6b17d67d77f8a6c4580bb556894cc1618473eff1e18203d8cce50b563cf4c75e408886079b8f067069442ed52e2ac9e556baa3f8fcc525f';
'0xc0040220af695ae100c370c7acff4f57e5a0c507abbbc8ac6cc2ae0ce3a81747e0cd3c6892233faae1af5d982d05b1c13a0ad4449685f0b5a6138b301cc5263f8316';
const secondPubkey =
'0xc000a2941866e485442aa6b17d67d77f8a6c4580bb556894cc1618473eff1e18203d8cce50b563cf4c75e408886079b8f067069442ed52e2ac9e556baa3f8fcc5251';
'0xc00499a876465bc626061bb2f0326df1a223c14e3bcdc3fff3deb0f95f316b9d586b03f00bbc2349be3d7908de8626cfd8f7fd6f73bff49df1299f44b6855562c33d';
await this.sfc.enableNonNodeCalls();

expect(await this.sfc.lastValidatorID()).to.equal(0);
Expand Down Expand Up @@ -428,6 +428,13 @@ describe('SFC', () => {
expect(await this.sfc.getValidatorPubkey(firstValidatorID)).to.equal(pubkey);
expect(await this.sfc.getValidatorPubkey(secondValidatorID)).to.equal(secondPubkey);

expect(await this.sfc.pubkeyAddressToValidatorID('0x65Db23D0c4FA8Ec58151a30E54e6a6046c97cD10')).to.equal(
firstValidatorID,
);
expect(await this.sfc.pubkeyAddressToValidatorID('0x1AA3196683eE97Adf5B398875828E322a34E8085')).to.equal(
secondValidatorID,
);

const firstValidatorObj = await this.sfc.getValidator(firstValidatorID);
const secondValidatorObj = await this.sfc.getValidator(secondValidatorID);

Expand Down Expand Up @@ -695,7 +702,7 @@ describe('SFC', () => {
expect(await this.sfc.rewardsStash(this.delegator, this.validatorId)).to.equal(9_180);
});

it('Should succeed andupdate the validator on node', async function () {
it('Should succeed and update the validator on node', async function () {
await this.constants.updateOfflinePenaltyThresholdTime(10000);
await this.constants.updateOfflinePenaltyThresholdBlocksNum(500);

Expand Down

0 comments on commit df772a2

Please sign in to comment.