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

Group/v2 #93

Merged
merged 41 commits into from
Dec 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4b6d1f7
v2 impl setup
drewstone Dec 24, 2021
b417de6
Updates to contracts
drewstone Dec 24, 2021
685996d
Compilation updates
drewstone Dec 24, 2021
6464917
updates
akileshtangella Dec 24, 2021
debd484
updates
akileshtangella Dec 25, 2021
1ed3d28
updates all existing tests working
akileshtangella Dec 26, 2021
1f7acb2
change naming remove comments
akileshtangella Dec 27, 2021
22478b5
passing in resourceID instead of entire anchor class
akileshtangella Dec 27, 2021
544353a
Updates
drewstone Dec 27, 2021
72edcbf
Fix vbridge vote proposal
drewstone Dec 27, 2021
2c323b2
contracts compiling
akileshtangella Dec 27, 2021
7abd875
updates
akileshtangella Dec 27, 2021
e685702
implement handler proposal in class
akileshtangella Dec 28, 2021
9593d49
More cleanup
drewstone Dec 28, 2021
31fbfa9
Updates
drewstone Dec 28, 2021
eee9d98
Gets test passing
drewstone Dec 28, 2021
40d2319
Cleanup
drewstone Dec 28, 2021
1a12471
More updates to contracts / tests
drewstone Dec 28, 2021
9a382da
Fix tests
drewstone Dec 28, 2021
1335212
fixed addEdges tests
akileshtangella Dec 28, 2021
761238f
fix updateEdges tests
akileshtangella Dec 28, 2021
5e53ec0
fix cancelUpdateProposa.js
akileshtangella Dec 28, 2021
e8e7633
fix createUpdateProposal.js
akileshtangella Dec 28, 2021
294b86e
fixes
akileshtangella Dec 28, 2021
5c03471
fixes
akileshtangella Dec 28, 2021
e9259b7
fixes to historicalRootWithdraw.js
akileshtangella Dec 28, 2021
d79bb57
fix sender is not the handler
akileshtangella Dec 28, 2021
adec7fb
fix merge conflicts
akileshtangella Dec 28, 2021
fbde7a6
cleanup
akileshtangella Dec 28, 2021
714b44c
unskip/remove skipped tests
akileshtangella Dec 28, 2021
4f25ab4
remove it.only
akileshtangella Dec 28, 2021
c9338df
v2 vanchor
akileshtangella Dec 29, 2021
5141afa
Cleanup
drewstone Dec 29, 2021
a482d9e
Fix up vanchor
drewstone Dec 29, 2021
58777ad
Spacing
drewstone Dec 29, 2021
56635db
View over verification
drewstone Dec 29, 2021
337f740
Update
drewstone Dec 29, 2021
f6f1adb
vanchor/vbridge v2 tests are all passing
akileshtangella Dec 29, 2021
d8a923a
cleanup
akileshtangella Dec 29, 2021
9a3cfeb
clear merge conflicts
akileshtangella Dec 29, 2021
a2b2a41
updates
akileshtangella Dec 29, 2021
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
18 changes: 13 additions & 5 deletions contracts/anchors/AnchorBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,28 @@ abstract contract AnchorBase is LinkableTree {
@dev Inserts a commitment into the tree
@param _commitment the note commitment = Poseidon(chainId, nullifier, secret)
*/
function insert(bytes32 _commitment) public payable nonReentrant returns(uint32) {
function insert(bytes32 _commitment) internal returns(uint32) {
require(!commitments[_commitment], "The commitment has been submitted");

uint32 insertedIndex = _insert(_commitment);
commitments[_commitment] = true;
_processInsertion();

emit Insertion(_commitment, insertedIndex, block.timestamp);

return insertedIndex;
}

/** @dev this function is defined in a child contract */
function _processInsertion() internal virtual;
function insertTwo(bytes32 _firstCommitment, bytes32 _secondCommitment) internal returns(uint32) {
require(!commitments[_firstCommitment], "The commitment has been submitted");
require(!commitments[_secondCommitment], "The commitment has been submitted");

uint32 insertedIndex = _insertTwo(_firstCommitment, _secondCommitment);
commitments[_firstCommitment] = true;
commitments[_secondCommitment] = true;
emit Insertion(_firstCommitment, insertedIndex, block.timestamp);
emit Insertion(_secondCommitment, insertedIndex + 1, block.timestamp);

return insertedIndex;
}

function verify(
bytes memory _proof,
Expand Down
66 changes: 26 additions & 40 deletions contracts/anchors/FixedDepositAnchor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ contract FixedDepositAnchor is AnchorBase, IFixedDepositAnchor {

address public immutable token;
uint256 public immutable denomination;

// currency events
event Deposit(address sender, uint32 indexed leafIndex, bytes32 indexed commitment, uint256 timestamp);
event Withdrawal(address to, bytes32 nullifierHash, address indexed relayer, uint256 fee);
event Withdrawal(address to, address indexed relayer, uint256 fee);
event Refresh(bytes32 indexed commitment, bytes32 nullifierHash, uint32 insertedIndex);

struct EncodeInputsData {
Expand All @@ -34,6 +35,7 @@ contract FixedDepositAnchor is AnchorBase, IFixedDepositAnchor {
uint256 _fee;
uint256 _refund;
}

/**
@dev The constructor
@param _verifier the address of SNARK verifier for this contract
Expand All @@ -56,13 +58,10 @@ contract FixedDepositAnchor is AnchorBase, IFixedDepositAnchor {
}

function deposit(bytes32 _commitment) override public payable {
uint32 insertedIndex = insert(_commitment);
emit Deposit(msg.sender, insertedIndex, _commitment, block.timestamp);
}

function _processInsertion() internal override {
require(msg.value == 0, "ETH value is supposed to be 0 for ERC20 instance");
uint32 insertedIndex = insert(_commitment);
IMintableERC20(token).transferFrom(msg.sender, address(this), denomination);
emit Deposit(msg.sender, insertedIndex, _commitment, block.timestamp);
}

/**
Expand All @@ -80,17 +79,8 @@ contract FixedDepositAnchor is AnchorBase, IFixedDepositAnchor {
require(_publicInputs._fee <= denomination, "Fee exceeds transfer value");
require(!isSpent(_publicInputs._nullifierHash), "The note has been already spent");

(bytes memory encodedInput, bytes32[] memory roots) = _encodeInputs(
_publicInputs._roots,
EncodeInputsData(
_publicInputs._nullifierHash,
_publicInputs._refreshCommitment,
address(_publicInputs._recipient),
address(_publicInputs._relayer),
_publicInputs._fee,
_publicInputs._refund
)
);
(bytes memory encodedInput, bytes32[] memory roots) = _encodeInputsWithPublicInputs(_publicInputs);

require(isValidRoots(roots), "Invalid roots");
require(verify(_proof, encodedInput), "Invalid withdraw proof");

Expand All @@ -103,11 +93,6 @@ contract FixedDepositAnchor is AnchorBase, IFixedDepositAnchor {
_publicInputs._fee,
_publicInputs._refund
);
emit Withdrawal(_publicInputs._recipient,
_publicInputs._nullifierHash,
_publicInputs._relayer,
_publicInputs._fee
);
} else {
require(!commitments[_publicInputs._refreshCommitment], "The commitment has been submitted");
uint32 insertedIndex = _insert(_publicInputs._refreshCommitment);
Expand Down Expand Up @@ -144,6 +129,8 @@ contract FixedDepositAnchor is AnchorBase, IFixedDepositAnchor {
}
}

emit Withdrawal(_recipient, _relayer, _fee);

if (_refund > 0) {
(bool success, ) = _recipient.call{ value: _refund }("");
if (!success) {
Expand Down Expand Up @@ -207,17 +194,7 @@ contract FixedDepositAnchor is AnchorBase, IFixedDepositAnchor {
require(_publicInputs._fee <= denomination, "Fee exceeds transfer value");
require(!nullifierHashes[_publicInputs._nullifierHash], "The note has been already spent");

(bytes memory encodedInput, bytes32[] memory roots) = _encodeInputs(
_publicInputs._roots,
EncodeInputsData(
_publicInputs._nullifierHash,
_publicInputs._refreshCommitment,
address(_publicInputs._recipient),
address(_publicInputs._relayer),
_publicInputs._fee,
_publicInputs._refund
)
);
(bytes memory encodedInput, bytes32[] memory roots) = _encodeInputsWithPublicInputs(_publicInputs);

require(isValidRoots(roots), "Invalid roots");
require(verify(_proof, encodedInput), "Invalid withdraw proof");
Expand All @@ -236,13 +213,6 @@ contract FixedDepositAnchor is AnchorBase, IFixedDepositAnchor {
denomination - _publicInputs._fee,
address(_publicInputs._recipient)
);

emit Withdrawal(
_publicInputs._recipient,
_publicInputs._nullifierHash,
_publicInputs._relayer,
_publicInputs._fee
);
}

function getDenomination() override external view returns (uint) {
Expand All @@ -253,6 +223,22 @@ contract FixedDepositAnchor is AnchorBase, IFixedDepositAnchor {
return token;
}

function _encodeInputsWithPublicInputs(
PublicInputs calldata _publicInputs
) internal view returns (bytes memory encodedInput, bytes32[] memory roots) {
return _encodeInputs(
_publicInputs._roots,
EncodeInputsData(
_publicInputs._nullifierHash,
_publicInputs._refreshCommitment,
address(_publicInputs._recipient),
address(_publicInputs._relayer),
_publicInputs._fee,
_publicInputs._refund
)
);
}

function _encodeInputs(
bytes calldata _roots,
EncodeInputsData memory encodeInputsData
Expand Down
17 changes: 17 additions & 0 deletions contracts/anchors/LinkableTree.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ abstract contract LinkableTree is MerkleTreePoseidon, ReentrancyGuard {
}
}

/** @dev */
function getLatestNeighborEdges() public view returns (Edge[] memory edges) {
edges = new Edge[](maxEdges);
for (uint256 i = 0; i < maxEdges; i++) {
if (edgeList.length >= i + 1) {
edges[i] = edgeList[i];
} else {
edges[i] = Edge({
// merkle tree height for zeros
root: zeros(levels),
chainID: 0,
latestLeafIndex: 0
});
}
}
}

function getLatestNeighborRoots() public view returns (bytes32[] memory roots) {
roots = new bytes32[](maxEdges);
for (uint256 i = 0; i < maxEdges; i++) {
Expand Down
4 changes: 4 additions & 0 deletions contracts/handlers/AnchorHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ contract AnchorHandler is IExecutor, HandlerHelpers {
uint32 leafIndex = uint32(bytes4(arguments[8:12]));
bytes32 merkleRoot = bytes32(arguments[12:44]);
anchor.updateEdge(sourceChainId, merkleRoot, leafIndex);
} else if (functionSig == bytes4(keccak256("configureLimits(uint256,uint256)"))) {
uint256 _minimalWithdrawalAmount = uint256(bytes32(arguments[4:36]));
uint256 _maximumDepositAmount = uint256(bytes32(arguments[36:68]));
anchor.configureLimits(_minimalWithdrawalAmount, _maximumDepositAmount);
} else {
revert("Invalid function sig");
}
Expand Down
2 changes: 2 additions & 0 deletions contracts/interfaces/ILinkableAnchor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pragma solidity ^0.8.0;
interface ILinkableAnchor {
function setHandler(address _handler, uint32 nonce) external;
function setVerifier(address _verifier) external;
function configureLimits(uint256 _minimalWithdrawalAmount, uint256 _maximumDepositAmount) external;

function updateEdge(
uint256 sourceChainID,
bytes32 root,
Expand Down
33 changes: 32 additions & 1 deletion contracts/trees/MerkleTreeWithHistoryPoseidon.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
pragma solidity ^0.8.0;

import "./Poseidon.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";

abstract contract MerkleTreeWithHistoryPoseidon {
abstract contract MerkleTreeWithHistoryPoseidon is Initializable {
uint256 public constant FIELD_SIZE = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 public constant ZERO_VALUE = 21663839004416932945382355908790599225266501822907911457504978515578255421292; // = keccak256("tornado") % FIELD_SIZE
IPoseidonT3 public immutable hasher;
Expand Down Expand Up @@ -62,6 +63,34 @@ abstract contract MerkleTreeWithHistoryPoseidon {
return _nextIndex;
}

// Modified to insert pairs of leaves for better efficiency
function _insertTwo(bytes32 _leaf1, bytes32 _leaf2) internal returns (uint32 index) {
uint32 _nextIndex = nextIndex;
require(_nextIndex != uint32(2)**levels, "Merkle tree is full. No more leaves can be added");
uint32 currentIndex = _nextIndex / 2;
bytes32 currentLevelHash = hashLeftRight(hasher, _leaf1, _leaf2);
bytes32 left;
bytes32 right;
for (uint32 i = 1; i < levels; i++) {
if (currentIndex % 2 == 0) {
left = currentLevelHash;
right = zeros(i);
filledSubtrees[i] = currentLevelHash;
} else {
left = filledSubtrees[i];
right = currentLevelHash;
}
currentLevelHash = hashLeftRight(hasher, left, right);
currentIndex /= 2;
}

uint32 newRootIndex = (currentRootIndex + 1) % ROOT_HISTORY_SIZE;
currentRootIndex = newRootIndex;
roots[newRootIndex] = currentLevelHash;
nextIndex = _nextIndex + 2;
return _nextIndex;
}

/**
@dev Whether the root is present in the root history
*/
Expand Down Expand Up @@ -92,4 +121,6 @@ abstract contract MerkleTreeWithHistoryPoseidon {

/** @dev this function is defined in a child contract */
function zeros(uint256 i) public virtual pure returns (bytes32);

function _initialize() internal {}
}
Loading