Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added migration function to Sharding table v2 contract #247

Merged
merged 16 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions abi/ShardingTableV2.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
"internalType": "address",
"name": "hubAddress",
"type": "address"
},
{
"internalType": "uint256",
"name": "migrationPeriodEnd_",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
Expand Down Expand Up @@ -245,6 +250,42 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint72",
"name": "startingIdentityId",
"type": "uint72"
},
{
"internalType": "uint16",
"name": "numberOfNodes",
"type": "uint16"
},
{
"internalType": "address",
"name": "shardingTableStorageV1Address",
"type": "address"
}
],
"name": "migrateOldShardingTable",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "migrationPeriodEnd",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "name",
Expand Down
32 changes: 30 additions & 2 deletions contracts/v2/ShardingTable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.16;

import {ProfileStorage} from "../v1/storage/ProfileStorage.sol";
import {ShardingTableStorageV2} from "./storage/ShardingTableStorage.sol";
import {ShardingTableStorage} from "../v1/storage/ShardingTableStorage.sol";
import {StakingStorage} from "../v1/storage/StakingStorage.sol";
import {ContractStatus} from "../v1/abstract/ContractStatus.sol";
import {Initializable} from "../v1/interface/Initializable.sol";
Expand All @@ -20,21 +21,30 @@ contract ShardingTableV2 is Named, Versioned, ContractStatus, Initializable {
event NodeRemoved(uint72 indexed identityId, bytes nodeId);

string private constant _NAME = "ShardingTable";
string private constant _VERSION = "2.0.0";
string private constant _VERSION = "2.0.1";

ProfileStorage public profileStorage;
ShardingTableStorageV2 public shardingTableStorage;
StakingStorage public stakingStorage;

uint256 public migrationPeriodEnd;

// solhint-disable-next-line no-empty-blocks
constructor(address hubAddress) ContractStatus(hubAddress) {}
constructor(address hubAddress, uint256 migrationPeriodEnd_) ContractStatus(hubAddress) {
migrationPeriodEnd = migrationPeriodEnd_;
}

function initialize() public onlyHubOwner {
profileStorage = ProfileStorage(hub.getContractAddress("ProfileStorage"));
shardingTableStorage = ShardingTableStorageV2(hub.getContractAddress("ShardingTableStorage"));
stakingStorage = StakingStorage(hub.getContractAddress("StakingStorage"));
}

modifier timeLimited() {
require(block.timestamp < migrationPeriodEnd, "Migration period has ended");
_;
}

function name() external pure virtual override returns (string memory) {
return _NAME;
}
Expand Down Expand Up @@ -65,6 +75,24 @@ contract ShardingTableV2 is Named, Versioned, ContractStatus, Initializable {
_insertNode(index, identityId, uint256(profileStorage.getNodeAddress(identityId, 1)));
}

function migrateOldShardingTable(
uint72 startingIdentityId,
uint16 numberOfNodes,
address shardingTableStorageV1Address
) external onlyHubOwner timeLimited {
ShardingTableStorageV2 stsv2 = shardingTableStorage;
ShardingTableStorage stsv1 = ShardingTableStorage(shardingTableStorageV1Address);

ShardingTableStructsV1.Node[] memory nodes = stsv1.getMultipleNodes(startingIdentityId, numberOfNodes);

for (uint i = 0; i < nodes.length; i++) {
if (!stsv2.nodeExists(nodes[i].identityId)) {
uint256 nodeHashRingPosition = uint256(profileStorage.getNodeAddress(nodes[i].identityId, 1));
_insertNode(_binarySearchForIndex(nodeHashRingPosition), nodes[i].identityId, nodeHashRingPosition);
}
}
}

function removeNode(uint72 identityId) external onlyContracts {
ShardingTableStorageV2 sts = shardingTableStorage;

Expand Down
58 changes: 57 additions & 1 deletion deploy/027_deploy_sharding_table_v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,76 @@ import { DeployFunction } from 'hardhat-deploy/types';
import { HardhatRuntimeEnvironment } from 'hardhat/types';

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const isMigration = hre.helpers.contractDeployments.contracts['ShardingTable']?.migration || false;

if (
hre.helpers.isDeployed('ShardingTable') &&
(hre.helpers.contractDeployments.contracts['ShardingTable'].version === undefined ||
hre.helpers.contractDeployments.contracts['ShardingTable'].version?.startsWith('1.'))
hre.helpers.contractDeployments.contracts['ShardingTable'].version?.startsWith('1.')) &&
!isMigration
) {
return;
}

const oldShardingTableAddress = hre.helpers.contractDeployments.contracts['ShardingTable']?.evmAddress;

console.log('Deploying ShardingTable V2...');

const blockTimeNow = (await hre.ethers.provider.getBlock('latest')).timestamp;

await hre.helpers.deploy({
newContractName: 'ShardingTableV2',
newContractNameInHub: 'ShardingTable',
additionalArgs: [isMigration ? blockTimeNow + 3600 : blockTimeNow],
});

if (hre.helpers.contractDeployments.contracts['ShardingTable'].migration && hre.network.name.startsWith('otp')) {
const { deployer } = await hre.getNamedAccounts();

console.log(`Executing sharding table storage v1 to v2 migration`);
const newShardingTableAddress = hre.helpers.contractDeployments.contracts['ShardingTable'].evmAddress;
const shardingTableStorageAddress = hre.helpers.contractDeployments.contracts['ShardingTableStorage'].evmAddress;

console.log(
`Old ShardingTable: ${oldShardingTableAddress}, New ShardingTable: ${newShardingTableAddress}, ShardingTableStorage: ${shardingTableStorageAddress}`,
);

const oldShardingTable = await hre.ethers.getContractAt('ShardingTable', oldShardingTableAddress, deployer);
const newShardingTable = await hre.ethers.getContractAt('ShardingTable', newShardingTableAddress, deployer);

const nodes = await oldShardingTable.getShardingTable();
let identityId = nodes[0]?.identityId;
console.log(`Found ${nodes.length} nodes in the old ShardingTable, starting identityId: ${identityId}`);

const numberOfNodesInBatch = 10;
let iteration = 1;

const encodedDataArray = [];

while (identityId) {
console.log(
`Migrating sharding table with starting identityId: ${identityId}, number of nodes in batch: ${numberOfNodesInBatch}, ShardingTableStorage: ${shardingTableStorageAddress}`,
);

encodedDataArray.push(
newShardingTable.interface.encodeFunctionData('migrateOldShardingTable', [
identityId,
numberOfNodesInBatch,
oldShardingTableAddress,
]),
);

console.log(
`Migration COMPLETED iteration: ${iteration} with starting identityId: ${identityId}, number of nodes in batch: ${numberOfNodesInBatch}, ShardingTableStorage: ${shardingTableStorageAddress}`,
);
iteration += 1;
identityId = nodes[iteration * numberOfNodesInBatch]?.identityId;
}

for (let i = 0; i < encodedDataArray.length; i++) {
hre.helpers.setParametersEncodedData.push(['ShardingTable', [encodedDataArray[i]]]);
}
}
};

export default func;
Expand Down
175 changes: 0 additions & 175 deletions deployments/hardhat_contracts.json

This file was deleted.

2 changes: 1 addition & 1 deletion test/v2/unit/ShardingTableV2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ describe('@v2 @unit ShardingTableV2 contract', function () {
const version = await ShardingTable.version();

expect(name).to.equal('ShardingTable');
expect(version).to.equal('2.0.0');
expect(version).to.equal('2.0.1');
});

it('Insert 5 nodes, nodes are sorted expect to pass', async () => {
Expand Down
1 change: 1 addition & 0 deletions utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type ContractDeployments = {
deploymentBlock: number;
deploymentTimestamp: number;
deployed: boolean;
migration?: boolean;
};
};
};
Expand Down
Loading