make gatekeeper extnesions abstract contracts
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
parent
424535e1f1
commit
f9015bf9a5
@ -1,36 +1,20 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Hashes} from "./libraries/Hashes.sol";
|
||||
import {IGatekeeper} from "./interfaces/IGatekeeper.sol";
|
||||
import {IGatekeeperWeaver} from "./interfaces/IGatekeeperWeaver.sol";
|
||||
|
||||
import {IGatekeeperMetadata} from "./interfaces/IGatekeeperMetadata.sol";
|
||||
import {Checkpoints} from "./libraries/Checkpoints.sol";
|
||||
|
||||
contract Gatekeeper is IGatekeeper, IGatekeeperMetadata, IGatekeeperWeaver {
|
||||
using Checkpoints for Checkpoints.Trace256;
|
||||
using Checkpoints for Checkpoints.Trace160;
|
||||
import {Metadata} from "./types/Metadata.sol";
|
||||
import {Weaver} from "./types/Weaver.sol";
|
||||
|
||||
contract Gatekeeper is IGatekeeper, Metadata, Weaver {
|
||||
uint256 public constant DIVISOR = 1e6;
|
||||
uint256 public constant DEPTH = 8;
|
||||
uint256 public constant SLOTS = 2 ** DEPTH;
|
||||
uint256 public constant ENTRIES = DEPTH * SLOTS;
|
||||
|
||||
uint256 public override existentialDeposit;
|
||||
uint256 public override ghostedSupply;
|
||||
uint256 public currentSession;
|
||||
address public immutable staking; // forge-lint: disable-line(screaming-snake-case-immutable)
|
||||
|
||||
GatekeeperMetadata private _metadata;
|
||||
uint256 private _aggregatedPublicKey;
|
||||
mapping(uint256 => mapping(uint256 => bool)) private _executedTransaction;
|
||||
|
||||
mapping(uint256 => mapping(uint256 => Checkpoints.Trace256)) internal _treeNodes;
|
||||
mapping(uint256 => mapping(uint256 => Checkpoints.Trace160)) internal _slotLenghts;
|
||||
mapping(uint256 => mapping(uint256 => bytes32[])) internal _slotValues;
|
||||
mapping(uint256 => uint256) internal _filledEntries;
|
||||
|
||||
constructor(
|
||||
address _staking,
|
||||
uint256 _ghostedSupply,
|
||||
@ -38,109 +22,10 @@ contract Gatekeeper is IGatekeeper, IGatekeeperMetadata, IGatekeeperWeaver {
|
||||
uint48 _deployedAt,
|
||||
uint104 _amountIn,
|
||||
uint104 _amountOut
|
||||
) {
|
||||
) Metadata(_deployedAt, _amountIn, _amountOut) Weaver() {
|
||||
existentialDeposit = _existential;
|
||||
ghostedSupply = _ghostedSupply;
|
||||
staking = _staking;
|
||||
_metadata = GatekeeperMetadata({
|
||||
deployedAt: _deployedAt,
|
||||
amountIn: _amountIn,
|
||||
amountOut: _amountOut
|
||||
});
|
||||
}
|
||||
|
||||
function metadata() external view returns (GatekeeperMetadata memory) {
|
||||
return _metadata;
|
||||
}
|
||||
|
||||
function getSlotValues(
|
||||
uint256 globalIndex,
|
||||
uint256 session,
|
||||
uint256 atBlock
|
||||
) external view returns (bytes32[] memory) {
|
||||
uint256 slotIndex = globalIndex % SLOTS;
|
||||
// forge-lint: disable-next-line(unsafe-typecast)
|
||||
uint256 length = _slotLenghts[session][slotIndex].upperLookupRecent(uint96(atBlock));
|
||||
bytes32[] memory values = new bytes32[](length);
|
||||
|
||||
uint256 i;
|
||||
for (; i < length; ) {
|
||||
values[i] = _slotValues[session][slotIndex][i];
|
||||
unchecked { ++i; }
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
function getRoot(uint256 session, uint256 atBlock) public view returns (bytes32, uint256) {
|
||||
uint256 currentLevelCount = SLOTS >> 1;
|
||||
bytes32[] memory currentLevel = new bytes32[](currentLevelCount);
|
||||
|
||||
uint256 i;
|
||||
for (; i < currentLevelCount;) {
|
||||
uint256 j = i << 1;
|
||||
bytes32 left = bytes32(_treeNodes[session][j].upperLookup(atBlock));
|
||||
bytes32 right = bytes32(_treeNodes[session][j | 1].upperLookup(atBlock));
|
||||
|
||||
currentLevel[i] = Hashes.efficientKeccak256(left, right);
|
||||
unchecked { ++i; }
|
||||
}
|
||||
|
||||
while (currentLevelCount > 1) {
|
||||
currentLevelCount >>= 1;
|
||||
i = 0;
|
||||
for (; i < currentLevelCount;) {
|
||||
uint256 j = i << 1;
|
||||
bytes32 left = currentLevel[j];
|
||||
bytes32 right = currentLevel[j | 1];
|
||||
|
||||
currentLevel[i] = Hashes.efficientKeccak256(left, right);
|
||||
unchecked { ++i; }
|
||||
}
|
||||
}
|
||||
|
||||
return (currentLevel[0], _filledEntries[session]);
|
||||
}
|
||||
|
||||
function getProof(
|
||||
uint256 globalIndex,
|
||||
uint256 session,
|
||||
uint256 atBlock
|
||||
) external view returns (bytes32[] memory) {
|
||||
uint256 currentLevelCount = SLOTS;
|
||||
uint256 currentIndex = globalIndex % SLOTS;
|
||||
|
||||
bytes32[] memory proof = new bytes32[](DEPTH);
|
||||
bytes32[] memory currentLevel = new bytes32[](currentLevelCount);
|
||||
uint256 i;
|
||||
|
||||
for (; i < currentLevelCount;) {
|
||||
currentLevel[i] = bytes32(_treeNodes[session][i].upperLookup(atBlock));
|
||||
unchecked { ++i; }
|
||||
}
|
||||
|
||||
uint256 proofIndex;
|
||||
while (currentLevelCount > 1) {
|
||||
currentLevelCount >>= 1;
|
||||
uint256 siblingIndex = currentIndex ^ 1;
|
||||
|
||||
proof[proofIndex] = currentLevel[siblingIndex];
|
||||
i = 0;
|
||||
|
||||
for (; i < currentLevelCount;) {
|
||||
uint256 j = i << 1;
|
||||
bytes32 left = currentLevel[j];
|
||||
bytes32 right = currentLevel[j | 1];
|
||||
|
||||
currentLevel[i] = Hashes.efficientKeccak256(left, right);
|
||||
unchecked { ++i; }
|
||||
}
|
||||
|
||||
currentIndex >>= 1;
|
||||
unchecked { ++proofIndex; }
|
||||
}
|
||||
|
||||
return proof;
|
||||
}
|
||||
|
||||
function ghost(bytes32 receiver, uint256 amount) external override returns (uint256) {
|
||||
@ -216,34 +101,4 @@ contract Gatekeeper is IGatekeeper, IGatekeeperMetadata, IGatekeeperWeaver {
|
||||
// always bad signature for now
|
||||
return true;
|
||||
}
|
||||
|
||||
function _insertTreeNode(bytes32 who, uint256 amount) private returns (uint256 globalIndex) {
|
||||
uint256 session = currentSession;
|
||||
globalIndex = _filledEntries[session];
|
||||
if (globalIndex >= ENTRIES) {
|
||||
unchecked { ++session; }
|
||||
currentSession = session;
|
||||
globalIndex = 0;
|
||||
}
|
||||
|
||||
uint256 slotIndex = globalIndex % SLOTS;
|
||||
uint256 valueIndex = globalIndex / SLOTS;
|
||||
uint160 length = uint160(_slotValues[session][slotIndex].length + 1);
|
||||
|
||||
bytes32 preimage = _computeArgumentsHash(valueIndex, amount, who);
|
||||
bytes32 currHash = Hashes.efficientKeccak256(preimage);
|
||||
bytes32 slotHash = bytes32(_treeNodes[session][slotIndex].latest());
|
||||
|
||||
slotHash = Hashes.efficientKeccak256(slotHash, currHash);
|
||||
|
||||
_treeNodes[session][slotIndex].push(block.number, uint256(slotHash));
|
||||
_slotLenghts[session][slotIndex].push(uint96(block.number), length);
|
||||
_slotValues[session][slotIndex].push(preimage);
|
||||
|
||||
unchecked { ++_filledEntries[session]; }
|
||||
}
|
||||
|
||||
function _computeArgumentsHash(uint256 i, uint256 a, bytes32 r) internal pure returns (bytes32) {
|
||||
return Hashes.efficientKeccak256(bytes32(i), Hashes.efficientKeccak256(bytes32(a), r));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
interface IGatekeeperMetadata {
|
||||
interface IMetadata {
|
||||
struct GatekeeperMetadata {
|
||||
uint48 deployedAt;
|
||||
uint104 amountIn;
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
interface IGatekeeperWeaver {
|
||||
interface IWeaver {
|
||||
function getSlotValues(uint256 globalIndex, uint256 session, uint256 atBlock) external returns (bytes32[] memory);
|
||||
function getProof(uint256 globalIndex, uint256 session, uint256 atBlock) external returns (bytes32[] memory);
|
||||
function getRoot(uint256 session, uint256 atBlock) external returns (bytes32, uint256);
|
||||
24
src/types/Metadata.sol
Normal file
24
src/types/Metadata.sol
Normal file
@ -0,0 +1,24 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {IMetadata} from "../interfaces/IMetadata.sol";
|
||||
|
||||
abstract contract Metadata is IMetadata {
|
||||
GatekeeperMetadata internal _metadata;
|
||||
|
||||
constructor(
|
||||
uint48 _deployedAt,
|
||||
uint104 _amountIn,
|
||||
uint104 _amountOut
|
||||
) {
|
||||
_metadata = GatekeeperMetadata({
|
||||
deployedAt: _deployedAt,
|
||||
amountIn: _amountIn,
|
||||
amountOut: _amountOut
|
||||
});
|
||||
}
|
||||
|
||||
function metadata() external view returns (GatekeeperMetadata memory) {
|
||||
return _metadata;
|
||||
}
|
||||
}
|
||||
145
src/types/Weaver.sol
Normal file
145
src/types/Weaver.sol
Normal file
@ -0,0 +1,145 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {IWeaver} from "../interfaces/IWeaver.sol";
|
||||
|
||||
import {Hashes} from "../libraries/Hashes.sol";
|
||||
import {Checkpoints} from "../libraries/Checkpoints.sol";
|
||||
|
||||
abstract contract Weaver is IWeaver {
|
||||
using Checkpoints for Checkpoints.Trace256;
|
||||
using Checkpoints for Checkpoints.Trace160;
|
||||
|
||||
uint256 public constant DEPTH = 8;
|
||||
uint256 public constant SLOTS = 2 ** DEPTH;
|
||||
uint256 public constant ENTRIES = DEPTH * SLOTS;
|
||||
|
||||
uint256 public currentSession;
|
||||
|
||||
mapping(uint256 => mapping(uint256 => Checkpoints.Trace256)) internal _treeNodes;
|
||||
mapping(uint256 => mapping(uint256 => Checkpoints.Trace160)) internal _slotLenghts;
|
||||
mapping(uint256 => mapping(uint256 => bytes32[])) internal _slotValues;
|
||||
mapping(uint256 => uint256) internal _filledEntries;
|
||||
|
||||
constructor() {}
|
||||
|
||||
function getSlotValues(
|
||||
uint256 globalIndex,
|
||||
uint256 session,
|
||||
uint256 atBlock
|
||||
) external view returns (bytes32[] memory) {
|
||||
uint256 slotIndex = globalIndex % SLOTS;
|
||||
// forge-lint: disable-next-line(unsafe-typecast)
|
||||
uint256 length = _slotLenghts[session][slotIndex].upperLookupRecent(uint96(atBlock));
|
||||
bytes32[] memory values = new bytes32[](length);
|
||||
|
||||
uint256 i;
|
||||
for (; i < length; ) {
|
||||
values[i] = _slotValues[session][slotIndex][i];
|
||||
unchecked { ++i; }
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
function getRoot(uint256 session, uint256 atBlock) public view returns (bytes32, uint256) {
|
||||
uint256 currentLevelCount = SLOTS >> 1;
|
||||
bytes32[] memory currentLevel = new bytes32[](currentLevelCount);
|
||||
|
||||
uint256 i;
|
||||
for (; i < currentLevelCount;) {
|
||||
uint256 j = i << 1;
|
||||
bytes32 left = bytes32(_treeNodes[session][j].upperLookup(atBlock));
|
||||
bytes32 right = bytes32(_treeNodes[session][j | 1].upperLookup(atBlock));
|
||||
|
||||
currentLevel[i] = Hashes.efficientKeccak256(left, right);
|
||||
unchecked { ++i; }
|
||||
}
|
||||
|
||||
while (currentLevelCount > 1) {
|
||||
currentLevelCount >>= 1;
|
||||
i = 0;
|
||||
for (; i < currentLevelCount;) {
|
||||
uint256 j = i << 1;
|
||||
bytes32 left = currentLevel[j];
|
||||
bytes32 right = currentLevel[j | 1];
|
||||
|
||||
currentLevel[i] = Hashes.efficientKeccak256(left, right);
|
||||
unchecked { ++i; }
|
||||
}
|
||||
}
|
||||
|
||||
return (currentLevel[0], _filledEntries[session]);
|
||||
}
|
||||
|
||||
function getProof(
|
||||
uint256 globalIndex,
|
||||
uint256 session,
|
||||
uint256 atBlock
|
||||
) external view returns (bytes32[] memory) {
|
||||
uint256 currentLevelCount = SLOTS;
|
||||
uint256 currentIndex = globalIndex % SLOTS;
|
||||
|
||||
bytes32[] memory proof = new bytes32[](DEPTH);
|
||||
bytes32[] memory currentLevel = new bytes32[](currentLevelCount);
|
||||
uint256 i;
|
||||
|
||||
for (; i < currentLevelCount;) {
|
||||
currentLevel[i] = bytes32(_treeNodes[session][i].upperLookup(atBlock));
|
||||
unchecked { ++i; }
|
||||
}
|
||||
|
||||
uint256 proofIndex;
|
||||
while (currentLevelCount > 1) {
|
||||
currentLevelCount >>= 1;
|
||||
uint256 siblingIndex = currentIndex ^ 1;
|
||||
|
||||
proof[proofIndex] = currentLevel[siblingIndex];
|
||||
i = 0;
|
||||
|
||||
for (; i < currentLevelCount;) {
|
||||
uint256 j = i << 1;
|
||||
bytes32 left = currentLevel[j];
|
||||
bytes32 right = currentLevel[j | 1];
|
||||
|
||||
currentLevel[i] = Hashes.efficientKeccak256(left, right);
|
||||
unchecked { ++i; }
|
||||
}
|
||||
|
||||
currentIndex >>= 1;
|
||||
unchecked { ++proofIndex; }
|
||||
}
|
||||
|
||||
return proof;
|
||||
}
|
||||
|
||||
function _insertTreeNode(bytes32 who, uint256 amount) internal returns (uint256 globalIndex) {
|
||||
uint256 session = currentSession;
|
||||
globalIndex = _filledEntries[session];
|
||||
if (globalIndex >= ENTRIES) {
|
||||
unchecked { ++session; }
|
||||
currentSession = session;
|
||||
globalIndex = 0;
|
||||
}
|
||||
|
||||
uint256 slotIndex = globalIndex % SLOTS;
|
||||
uint256 valueIndex = globalIndex / SLOTS;
|
||||
uint160 length = uint160(_slotValues[session][slotIndex].length + 1);
|
||||
|
||||
bytes32 preimage = _computeArgumentsHash(valueIndex, amount, who);
|
||||
bytes32 currHash = Hashes.efficientKeccak256(preimage);
|
||||
bytes32 slotHash = bytes32(_treeNodes[session][slotIndex].latest());
|
||||
|
||||
slotHash = Hashes.efficientKeccak256(slotHash, currHash);
|
||||
|
||||
_treeNodes[session][slotIndex].push(block.number, uint256(slotHash));
|
||||
_slotLenghts[session][slotIndex].push(uint96(block.number), length);
|
||||
_slotValues[session][slotIndex].push(preimage);
|
||||
|
||||
unchecked { ++_filledEntries[session]; }
|
||||
}
|
||||
|
||||
function _computeArgumentsHash(uint256 i, uint256 a, bytes32 r) internal pure returns (bytes32) {
|
||||
return Hashes.efficientKeccak256(bytes32(i), Hashes.efficientKeccak256(bytes32(a), r));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user