Skip to content

Commit

Permalink
Merge pull request thehubbleproject#23 from thehubbleproject/create-a…
Browse files Browse the repository at this point in the history
…ccount

Create Account
  • Loading branch information
ChihChengLiang authored Jul 12, 2020
2 parents 076fe84 + 1df7bf9 commit e6d111c
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 0 deletions.
154 changes: 154 additions & 0 deletions contracts/CreateAccount.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
pragma solidity ^0.5.15;
pragma experimental ABIEncoderV2;

import {FraudProofHelpers} from "./FraudProof.sol";
import {Types} from "./libs/Types.sol";
import {ITokenRegistry} from "./interfaces/ITokenRegistry.sol";
import {RollupUtils} from "./libs/RollupUtils.sol";
import {MerkleTreeUtils as MTUtils} from "./MerkleTreeUtils.sol";
import {Governance} from "./Governance.sol";
import {NameRegistry as Registry} from "./NameRegistry.sol";
import {ParamManager} from "./libs/ParamManager.sol";

contract CreateAccount is FraudProofHelpers {
/*********************
* Constructor *
********************/
constructor(address _registryAddr) public {
nameRegistry = Registry(_registryAddr);

governance = Governance(
nameRegistry.getContractDetails(ParamManager.Governance())
);

merkleUtils = MTUtils(
nameRegistry.getContractDetails(ParamManager.MERKLE_UTILS())
);

tokenRegistry = ITokenRegistry(
nameRegistry.getContractDetails(ParamManager.TOKEN_REGISTRY())
);
}

function generateTxRoot(Types.CreateAccount[] memory _txs)
public
view
returns (bytes32 txRoot)
{
// generate merkle tree from the txs provided by user
bytes[] memory txs = new bytes[](_txs.length);
for (uint256 i = 0; i < _txs.length; i++) {
txs[i] = RollupUtils.CompressCreateAccount(_txs[i]);
}
txRoot = merkleUtils.getMerkleRoot(txs);
return txRoot;
}

/**
* @notice processBatch processes a whole batch
* @return returns updatedRoot, txRoot and if the batch is valid or not
* */
function processBatch(
bytes32 stateRoot,
bytes32 accountsRoot,
Types.CreateAccount[] memory _txs,
Types.BatchValidationProofs memory batchProofs,
bytes32 expectedTxRoot
)
public
view
returns (
bytes32,
bytes32,
bool
)
{
bytes32 actualTxRoot = generateTxRoot(_txs);
// if there is an expectation set, revert if it's not met
if (expectedTxRoot == ZERO_BYTES32) {
// if tx root while submission doesnt match tx root of given txs
// dispute is unsuccessful
require(
actualTxRoot == expectedTxRoot,
"Invalid dispute, tx root doesn't match"
);
}

bool isTxValid;
{
for (uint256 i = 0; i < _txs.length; i++) {
// call process tx update for every transaction to check if any
// tx evaluates correctly
(stateRoot, , , , isTxValid) = processTx(
stateRoot,
accountsRoot,
_txs[i],
batchProofs.pdaProof[i],
batchProofs.accountProofs[i]
);

if (!isTxValid) {
break;
}
}
}
return (stateRoot, actualTxRoot, !isTxValid);
}

function ValidateZeroAccount(Types.UserAccount memory account)
public
pure
returns (bool)
{
return
account.ID == 0 &&
account.tokenType == 0 &&
account.balance == 0 &&
account.nonce == 0;
}

function processTx(
bytes32 _balanceRoot,
bytes32 _accountsRoot,
Types.CreateAccount memory _tx,
Types.PDAMerkleProof memory _to_pda_proof,
Types.AccountProofs memory accountProofs
)
public
view
returns (
bytes32,
bytes memory,
bytes memory,
uint256,
bool
)
{
Types.UserAccount memory createdAccount;
createdAccount.ID = _tx.toIndex;
createdAccount.tokenType = 1; // Arbitrary assign a default token
createdAccount.balance = 0;
createdAccount.nonce = 0;

// Assuming Reddit have run rollup.sol::createPublickeys
ValidatePubkeyAvailability(_accountsRoot, _to_pda_proof, _tx.toIndex);

// accountProofs.to.accountIP.account should to be a zero account
bool result = ValidateZeroAccount(accountProofs.to.accountIP.account);
if (result == false) {
return ("", "", "", 0, false);
}

ValidateAccountMP(_balanceRoot, accountProofs.to);

bytes32 newRoot = UpdateAccountWithSiblings(
createdAccount,
accountProofs.to // We only use the pathToAccount and siblings but not the proof itself
);
bytes memory createdAccountBytes = RollupUtils.BytesFromAccount(
createdAccount
);

return (newRoot, createdAccountBytes, "", 0, true);
}
}
33 changes: 33 additions & 0 deletions contracts/libs/RollupUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,16 @@ library RollupUtils {
return _tx;
}

function DecompressCreateAccount(bytes memory txBytes)
public
pure
returns (Types.CreateAccount memory)
{
Types.CreateAccount memory _tx;
(_tx.toIndex, _tx.tokenType) = abi.decode(txBytes, (uint256, uint256));
return _tx;
}

function CompressDrop(Types.Drop memory drop)
public
pure
Expand All @@ -271,6 +281,14 @@ library RollupUtils {
return abi.encode(_tx);
}

function CompressCreateAccount(Types.CreateAccount memory _tx)
public
pure
returns (bytes memory)
{
return abi.encode(_tx);
}

function CompressDropNoStruct(
uint256 toIndex,
uint256 tokenType,
Expand Down Expand Up @@ -316,6 +334,14 @@ library RollupUtils {
);
}

function BytesFromCreateAccount(Types.CreateAccount memory _tx)
public
pure
returns (bytes memory)
{
return abi.encodePacked(_tx.toIndex, _tx.tokenType);
}

function BytesFromAirdrop(Types.Drop memory _tx)
public
pure
Expand Down Expand Up @@ -362,6 +388,13 @@ library RollupUtils {
return abi.encodePacked(from, to, tokenType, nonce, txType, amount);
}

function BytesFromTxCreateAccountDeconstructed(
uint256 to,
uint256 tokenType
) public pure returns (bytes memory) {
return abi.encodePacked(to, tokenType);
}

function BytesFromTxAirdropDeconstructed(
uint256 to,
uint256 tokenType,
Expand Down
6 changes: 6 additions & 0 deletions contracts/libs/Types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ library Types {
bytes signature;
}

struct CreateAccount {
uint256 toIndex;
uint256 tokenType;
bytes signature;
}

struct Drop {
uint256 toIndex;
uint256 tokenType;
Expand Down
16 changes: 16 additions & 0 deletions contracts/rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,22 @@ contract Rollup is RollupHelpers {
addNewBatch(ZERO_BYTES32, genesisStateRoot, Types.Usage.Genesis);
}

function createPublickeys(bytes[] calldata publicKeys)
external
onlyCoordinator
returns (uint256[] memory)
{
uint256[] memory accountIDs = new uint256[](publicKeys.length);
for (uint256 i = 0; i < publicKeys.length; i++) {
Types.PDALeaf memory newPDALeaf;
newPDALeaf.pubkey = publicKeys[i];
accountIDs[i] = accountsTree.appendLeaf(
RollupUtils.PDALeafToHash(newPDALeaf)
);
}
return accountIDs;
}

/**
* @notice Submits a new batch to batches
* @param _txs Compressed transactions .
Expand Down

0 comments on commit e6d111c

Please sign in to comment.