- Clone this project from Github
- Install node modules: `npm install'
- Navigate to /eth-contracts
- Add a
.secretfile with your gnache mnemonic - Compile the code:
truffle compile - Migrate the contracts
truffle migrate
- run the test command:
truffle test
Deploying 'SolnSquareVerifier'
------------------------------
> transaction hash: 0x59d61229234dc10d44e1795a88709cb9e38025b768b9c1504fcbf8b5429dda0c
> Blocks: 0 Seconds: 8
> contract address: 0x24DFd3A84eed987de9D3F6CB3e157a99aCfC88ca
> block number: 5253138
> block timestamp: 1570936133
> account: 0x90b727c60f559cDD0e1DFf8c097D8a90c23d2df5
> balance: 11.714218817
> gas used: 6220649
> gas price: 10 gwei
> value sent: 0 ETH
> total cost: 0.06220649 ETH
OpenSea URL
https://rinkeby.opensea.io/recent/awesometitle
Assuming you don't want to just go get it from the compiled code yourself.
[
{
"constant": true,
"inputs": [
{
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "to",
"type": "address"
},
{
"name": "tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "from",
"type": "address"
},
{
"name": "to",
"type": "address"
},
{
"name": "tokenId",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_myid",
"type": "bytes32"
},
{
"name": "_result",
"type": "string"
}
],
"name": "__callback",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "owner",
"type": "address"
},
{
"name": "index",
"type": "uint256"
}
],
"name": "tokenOfOwnerByIndex",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_myid",
"type": "bytes32"
},
{
"name": "_result",
"type": "string"
},
{
"name": "_proof",
"type": "bytes"
}
],
"name": "__callback",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "unpause",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "to",
"type": "address"
},
{
"name": "tokenId",
"type": "uint256"
}
],
"name": "mint",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "from",
"type": "address"
},
{
"name": "to",
"type": "address"
},
{
"name": "tokenId",
"type": "uint256"
}
],
"name": "safeTransferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "account",
"type": "address"
}
],
"name": "isPauser",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "index",
"type": "uint256"
}
],
"name": "tokenByIndex",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "paused",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "a",
"type": "uint256[2]"
},
{
"name": "b",
"type": "uint256[2][2]"
},
{
"name": "c",
"type": "uint256[2]"
},
{
"name": "input",
"type": "uint256[2]"
}
],
"name": "verifyTx",
"outputs": [
{
"name": "r",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "renouncePauser",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "account",
"type": "address"
}
],
"name": "addPauser",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "pause",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "isOwner",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "account",
"type": "address"
}
],
"name": "addMinter",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "renounceMinter",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "to",
"type": "address"
},
{
"name": "approved",
"type": "bool"
}
],
"name": "setApprovalForAll",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "account",
"type": "address"
}
],
"name": "isMinter",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "awesomeTitleTest",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "from",
"type": "address"
},
{
"name": "to",
"type": "address"
},
{
"name": "tokenId",
"type": "uint256"
},
{
"name": "_data",
"type": "bytes"
}
],
"name": "safeTransferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "tokenId",
"type": "uint256"
}
],
"name": "tokenURI",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "to",
"type": "address"
},
{
"name": "tokenId",
"type": "uint256"
},
{
"name": "tokenURI",
"type": "string"
}
],
"name": "mint",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "owner",
"type": "address"
},
{
"name": "operator",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "submittedBy",
"type": "address"
}
],
"name": "SolutionSubmitted",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "theHash",
"type": "bytes32"
}
],
"name": "HashCreated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "theString",
"type": "string"
}
],
"name": "AddSolutionCalled",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "aString",
"type": "string"
}
],
"name": "TestingYo",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "s",
"type": "string"
}
],
"name": "Verified",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "aString",
"type": "string"
}
],
"name": "AwesomeTitleTest",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "aString",
"type": "string"
}
],
"name": "AwesomeTitleTest2",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "isSuccessful",
"type": "bool"
}
],
"name": "AwesomeTitleMint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "account",
"type": "address"
}
],
"name": "MinterAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "account",
"type": "address"
}
],
"name": "MinterRemoved",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "from",
"type": "address"
},
{
"indexed": true,
"name": "to",
"type": "address"
},
{
"indexed": true,
"name": "tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "owner",
"type": "address"
},
{
"indexed": true,
"name": "approved",
"type": "address"
},
{
"indexed": true,
"name": "tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "owner",
"type": "address"
},
{
"indexed": true,
"name": "operator",
"type": "address"
},
{
"indexed": false,
"name": "approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "account",
"type": "address"
}
],
"name": "Paused",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "account",
"type": "address"
}
],
"name": "Unpaused",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "account",
"type": "address"
}
],
"name": "PauserAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "account",
"type": "address"
}
],
"name": "PauserRemoved",
"type": "event"
},
{
"constant": false,
"inputs": [],
"name": "testFunction",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "pa",
"type": "uint256[2]"
},
{
"name": "pb",
"type": "uint256[2][2]"
},
{
"name": "pc",
"type": "uint256[2]"
},
{
"name": "i",
"type": "uint256[2]"
},
{
"name": "to",
"type": "address"
}
],
"name": "addSolution",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
]The capstone will build upon the knowledge you have gained in the course in order to build a decentralized housing product.
- Remix - Solidity IDE
- Visual Studio Code
- Truffle Framework
- Ganache - One Click Blockchain
- Open Zeppelin
- Interactive zero knowledge 3-colorability demonstration
- Docker
- ZoKrates
So, having defined the program, Victor is now ready to compile the code:
./zokrates compile -i hashexample.code
Based on that Victor can run the setup phase and export verifier smart contract as a Solidity file:
./zokrates setup
./zokrates export-verifier
setup creates a verifiation.key file and a proving.key file. Victor gives the proving key to Peggy.
export-verifier creates a verifier.sol contract that contains our verification key and a function verifyTx. Victor deploys this smart contract to the Ethereum network.
Peggy provides the correct pre-image as an argument to the program.
./zokrates compute-witness -a 0 0 0 5
Finally, Peggy can run the command to construct the proof:
./zokrates generate-proof
As the inputs were declared as private in the program, they do not appear in the proof thanks to the zero knowledge property of the protocol.
ZoKrates creates a file, proof.json, consisting of the three elliptic curve points that make up the zkSNARKs proof. The verifyTx function in the smart contract deployed by Victor accepts these three values, along with an array of public inputs. The array of public inputs consists of:
any public inputs to the main function, declared without the private keyword the return values of the ZoKrates function In the example we're considering, all inputs are private and there is a single return value of 1, hence Peggy has to define her public input array as follows: [1]
Peggy can then submit her proof by calling verifyTx.
Victor monitors the verification smart contract for the Verified event, which is emitted upon successful verification of a transaction. As soon as he observes the event triggered by a transaction from Peggy's public address, he can be sure that Peggy has a valid pre-image for the hash he set in the smart contract.