add SLI mode

main
cyhhao 2 years ago
parent 480d10da6e
commit 7b498b35c1

@ -0,0 +1,150 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
// import "hardhat/console.sol";
import "./Git3HubStorage.sol";
contract Git3Hub_SLI is Git3HubStorage_SLI {
event RepoCreated(bytes repoName, address owner);
event RepoOwnerTransfer(bytes repoName, address oldOwner, address newOwner);
event PushRef(bytes repoName, bytes ref);
constructor() Git3HubStorage_SLI() {}
modifier onlyOwner(bytes memory repoName) {
require(repoNameToOwner[repoName] == msg.sender, "only owner");
_;
}
function createRepo(bytes memory repoName) external {
require(
repoName.length > 0 && repoName.length <= 100,
"RepoName length must be 1-100"
);
for (uint i; i < repoName.length; i++) {
bytes1 char = repoName[i];
require(
(char >= 0x61 && char <= 0x7A) || //a-z
(char >= 0x41 && char <= 0x5A) || //A-Z
(char >= 0x30 && char <= 0x39) || //0-9
(char == 0x2D || char == 0x2E || char == 0x5F), //-._
"RepoName must be alphanumeric or -._"
);
}
require(
repoNameToOwner[repoName] == address(0),
"RepoName already exist"
);
repoNameToOwner[repoName] = msg.sender;
emit RepoCreated(repoName, msg.sender);
}
function transferOwnership(
bytes memory repoName,
address newOwner
) external onlyOwner(repoName) {
require(newOwner != address(0), "newOwner must not be zero address");
repoNameToOwner[repoName] = newOwner;
emit RepoOwnerTransfer(repoName, msg.sender, newOwner);
}
function download(
bytes memory repoName,
bytes memory path
) external view returns (bytes memory) {
return pathToHash[keccak256(bytes.concat(repoName, "/", path))];
}
function upload(
bytes memory repoName,
bytes memory path,
bytes calldata data
) external payable onlyOwner(repoName) {
pathToHash[keccak256(bytes.concat(repoName, "/", path))] = data;
}
function remove(
bytes memory repoName,
bytes memory path
) external onlyOwner(repoName) {
// The actually process of remove will remove all the chunks
pathToHash[keccak256(bytes.concat(repoName, "/", path))] = "";
}
function listRefs(
bytes memory repoName
) external view returns (refData[] memory list) {
list = new refData[](repoNameToRefs[repoName].length);
for (uint index = 0; index < repoNameToRefs[repoName].length; index++) {
list[index] = _convertRefInfo(
repoName,
nameToRefInfo[repoNameToRefs[repoName][index]]
);
}
}
function setRef(
bytes memory repoName,
bytes memory ref,
bytes20 refHash
) external onlyOwner(repoName) {
bytes memory fullName = bytes.concat(repoName, "/", ref);
// only execute `sload` once to reduce gas consumption
refInfo memory srs;
srs = nameToRefInfo[fullName];
uint256 refsLen = repoNameToRefs[repoName].length;
if (srs.hash == bytes20(0)) {
// store refHash for the first time
require(
refsLen <= uint256(uint96(int96(-1))),
"Refs exceed valid length"
);
nameToRefInfo[fullName].hash = refHash;
nameToRefInfo[fullName].index = uint96(refsLen);
repoNameToRefs[repoName].push(fullName);
} else {
// only update refHash
nameToRefInfo[fullName].hash = refHash;
}
emit PushRef(repoName, ref);
}
function delRef(
bytes memory repoName,
bytes memory ref
) external onlyOwner(repoName) {
bytes memory fullName = bytes.concat(repoName, "/", ref);
// only execute `sload` once to reduce gas consumption
refInfo memory srs;
srs = nameToRefInfo[fullName];
uint256 refsLen = repoNameToRefs[repoName].length;
require(
srs.hash != bytes20(0),
"Reference of this name does not exist"
);
require(srs.index < refsLen, "System Error: Invalid index");
if (srs.index < refsLen - 1) {
repoNameToRefs[repoName][srs.index] = repoNameToRefs[repoName][
refsLen - 1
];
nameToRefInfo[repoNameToRefs[repoName][refsLen - 1]].index = srs
.index;
}
repoNameToRefs[repoName].pop();
delete nameToRefInfo[fullName];
}
function _convertRefInfo(
bytes memory repoName,
refInfo memory info
) internal view returns (refData memory res) {
res.hash = info.hash;
res.name = repoNameToRefs[repoName][info.index];
}
}

@ -0,0 +1,22 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
contract Git3HubStorage_SLI {
struct refInfo {
bytes20 hash;
uint96 index;
}
struct refData {
bytes20 hash;
bytes name;
}
// FileStorage Storage Layout
mapping(bytes32 => bytes) public pathToHash;
// Git3Hub Storage Layout
mapping(bytes => address) public repoNameToOwner;
mapping(bytes => refInfo) public nameToRefInfo; // dev => {hash: 0x1234..., index: 1 }
mapping(bytes => bytes[]) public repoNameToRefs; // [main, dev, test, staging]
}

@ -0,0 +1,10 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
contract Hello{
string public abc;
constructor(){
abc="Hello World";
}
}

@ -5,7 +5,7 @@ pragma solidity ^0.8.0;
// import "@openzeppelin/contracts/access/Ownable.sol";
import "./v2/LargeStorageManagerV2.sol";
contract Git3Hub is LargeStorageManagerV2 {
contract Git3Hub_ES is LargeStorageManagerV2 {
event RepoCreated(bytes repoName, address owner);
event RepoOwnerTransfer(bytes repoName, address oldOwner, address newOwner);
event PushRef(bytes repoName, bytes ref);

@ -1,7 +1,7 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
contract Git3HubStorage {
contract Git3HubStorage_ES {
struct refInfo {
bytes20 hash;
uint96 index;
@ -14,10 +14,10 @@ contract Git3HubStorage {
// LargeStorageManagerV2 Storage Layout
mapping(bytes32 => mapping(uint256 => bytes32)) internal keyToMetadata;
mapping(bytes32 => mapping(uint256 => mapping(uint256 => bytes32)))
internal keyToSlots;
internal keyToSlots;
// Git3Hub Storage Layout
mapping(bytes => address) public repoNameToOwner;
mapping(bytes => refInfo) public nameToRefInfo; // dev => {hash: 0x1234..., index: 1 }
mapping(bytes => bytes[]) public repoNameToRefs; // [main, dev, test, staging]
}
}

@ -7,11 +7,11 @@ import "./StorageSlotSelfDestructableV2.sol";
import "../Git3HubStorage.sol";
// Large storage manager to support arbitrarily-sized data with multiple chunk
contract LargeStorageManagerV2 is Git3HubStorage {
contract LargeStorageManagerV2 is Git3HubStorage_ES {
using SlotHelper for bytes32;
using SlotHelper for address;
uint8 internal constant SLOT_LIMIT = 0;
uint8 internal constant SLOT_LIMIT = 0;
function isOptimize() public pure returns (bool) {
return SLOT_LIMIT > 0;

@ -3,25 +3,40 @@ const { ethers } = hre;
import fs from "fs";
async function main() {
const accounts = await ethers.getSigners();
console.log(accounts[0].address);
const accounts = await ethers.getSigners();
console.log(accounts[0].address);
let provider = ethers.provider;
let price = await provider.getFeeData();
const Git3 = await hre.ethers.getContractAt(
"Git3Hub",
"0xee2879cd03A3D82C0Ffb648AA5773bcEBb0d5741"
);
let rept
// let owner = await Git3.repoNameToOwner(Buffer.from("helloworld1"))
// console.log(owner)
// return
rept = await Git3.createRepo(Buffer.from("helloworld"))
console.log("rept", "https://explorer.galileo.web3q.io/tx/" + rept.hash);
const Git3 = await hre.ethers.getContractAt(
"Git3Hub_SLI",
"0xF56A1dd941667911896B9B872AC79E56cfc6a3dB"
);
let rept;
let repoName = Buffer.from("h2");
let owner = await Git3.repoNameToOwner(repoName);
console.log(owner);
// rept = await Git3.transferOwnership(Buffer.from("helloworld"), "0x1eD9c2F6814eA5225Bb78f2F2CA802Ded120077A")
// console.log("rept", "https://explorer.galileo.web3q.io/tx/" + rept.hash)
rept = await Git3.createRepo(repoName, {
type: 2,
maxFeePerGas: price.maxFeePerGas!,
maxPriorityFeePerGas: price.maxPriorityFeePerGas!,
});
console.log("rept", "https://explorer.galileo.web3q.io/tx/" + rept.hash);
rept = await Git3.transferOwnership(
repoName,
"0x1eD9c2F6814eA5225Bb78f2F2CA802Ded120077A",
{
type: 2,
maxFeePerGas: price.maxFeePerGas!,
maxPriorityFeePerGas: price.maxPriorityFeePerGas!,
}
);
console.log("rept", "https://explorer.galileo.web3q.io/tx/" + rept.hash);
}
main().catch((error) => {
console.error(error);
process.exit(1);
console.error(error);
process.exit(1);
});

@ -11,7 +11,7 @@ async function main() {
console.log(operator.address, nonce)
const Git3 = await ethers.getContractFactory("Git3Hub");
const Git3 = await ethers.getContractFactory("Git3Hub_ES");
const git3 = await Git3.deploy({ nonce: nonce });
let logicReceipt = await git3.deployed()

@ -0,0 +1,51 @@
import { ethers } from "hardhat";
async function main() {
let provider = ethers.provider;
let [operator] = await ethers.getSigners();
let nonce = await operator.getTransactionCount();
console.log(operator.address, nonce, await operator.getBalance());
let price = await provider.getFeeData();
let net = await provider.getNetwork();
console.log(price, net.chainId);
const Git3 = await ethers.getContractFactory("Git3Hub_SLI");
const git3 = await Git3.deploy({
nonce: nonce,
type: 2,
maxFeePerGas: price.maxFeePerGas!,
maxPriorityFeePerGas: price.maxPriorityFeePerGas!,
gasLimit: 3000000,
});
let logicReceipt = await git3.deployed();
console.log(logicReceipt.deployTransaction.hash);
nonce++;
let factory1 = await ethers.getContractFactory("UpgradeableProxy");
// Proxy don't need to init Git3 contract because the constructor is empty.
let initSelector = "0x";
let proxyInstance = await factory1
.connect(operator)
.deploy(git3.address, operator.address, initSelector, {
nonce: nonce,
type: 2,
maxFeePerGas: price.maxFeePerGas,
maxPriorityFeePerGas: price.maxPriorityFeePerGas,
});
let proxyReceipt = await proxyInstance.deployed();
console.log(proxyReceipt.deployTransaction.hash);
// console.log({logicReceipt,proxyReceipt});
console.log("Logic Contract", git3.address);
console.log("Proxy Contract", proxyInstance.address);
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});

@ -0,0 +1,24 @@
import hre from "hardhat";
const { ethers } = hre;
import fs from "fs";
async function main() {
const accounts = await ethers.getSigners();
console.log(accounts[0].address);
const Git3 = await hre.ethers.getContractAt(
"Git3Hub_SLI",
"0xF56A1dd941667911896B9B872AC79E56cfc6a3dB"
);
let res = await Git3.download(
Buffer.from("h1"),
Buffer.from("objects/9f/2781f252bddce27d26a4e9ae4acf965f09ba9f")
);
console.log(res);
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
Loading…
Cancel
Save