Contract Overview
Balance: 0 Ether
Ether Value: $0
Transactions: 6 txns
 Latest 6 txns

TxHash Age From To Value [TxFee]
0xf617041d236e93b01c08265789dd17e993305a81183a952465a959951d1250ba126 days 17 hrs ago0x00c2b10d58daeaaa7c11a8e79542fb7568e1c2c7  IN   0xf8cadbcadbeac3b5192ba29df5007746054102a40 Ether0.0001247076
0xffb70ad6d99a597eea4288e3bfdaa1f3f56c31db3a7260f9a51c6ae004e06e5d167 days 12 mins ago0x00c2b10d58daeaaa7c11a8e79542fb7568e1c2c7  IN   0xf8cadbcadbeac3b5192ba29df5007746054102a40 Ether0.0001247652
0x7b839dafdd50b761f9017b27447c85bb522d19ce06759fff851eef8c42444e42263 days 19 hrs ago0x00c2b10d58daeaaa7c11a8e79542fb7568e1c2c7  IN   0xf8cadbcadbeac3b5192ba29df5007746054102a40 Ether0.0000415884
0x93175ed7098dbb88c8190d6f88174b465ac0753ae9c1f1e9560dd1dd2f678215264 days 2 hrs ago0x00c2b10d58daeaaa7c11a8e79542fb7568e1c2c7  IN   0xf8cadbcadbeac3b5192ba29df5007746054102a40 Ether0.0000321246
0x679acf4490dcf61e6f51a520dbc0832b1ff54cfcbfd11ac55b3f9a8a6b5e9318264 days 3 hrs ago0x00c2b10d58daeaaa7c11a8e79542fb7568e1c2c7  IN   0xf8cadbcadbeac3b5192ba29df5007746054102a40 Ether0.0000131466
0x5f2a9ca1b22b72def5b31e3a5f356b1668ac8fd8289bfc4724324785c439e7c1264 days 23 hrs ago0x00c2b10d58daeaaa7c11a8e79542fb7568e1c2c7  IN    Contract Creation0 Ether0.001285776
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
View All
ParentTxHash Block Age From To Value
Warning: The Compiled Contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity), NestedArrayFunctionCallDecoder (medium-severity) SolidityCompiler Bugs.

Contract Source Code Verified (Exact Match)
Contract Name: PubKeyTrust
Compiler Text: v0.4.18+commit.9cf6e910
Optimization Enabled: No
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

pragma solidity 0.4.18;

/**
 * This contract is used to protect the users of Storm4:
 * https://www.storm4.cloud
 * 
 * That is, to ensure the public keys of users are verifiable, auditable & tamper-proof.
 * 
 * Here's the general idea:
 * - We batch the public keys of multiple users into a merkle tree.
 * - We publish the merkle tree root to this contract.
 * - The merkle tree root for any given user can only be assigned once (per hash algorithm).
 * 
 * In order to verify a user:
 * - Use this contract to fetch the merkle tree root value for the userID.
 * - Then use HTTPS to fetch the corresponding merkle file from our server.
 *   For example, if the merkle tree root value is
 *   "0xcd59b7bda6dc1dd82cb173d0cdfa408db30e9a747d4366eb5b60597899eb69c1",
 *   then you could fetch the corresponding JSON file at
 *   https://blockchain.storm4.cloud/cd59b7bda6dc1dd82cb173d0cdfa408db30e9a747d4366eb5b60597899eb69c1.json
 * - The JSON file allows you to independently verify the public key information
 *   by calculating the merkle tree root for yourself.
**/
contract PubKeyTrust {
	address public owner;

	/**
	 * Rather than hard-coding a specific hash algorithm, we allow for upgradeability,
	 * should it become important to do so in the future for security reasons.
	 * 
	 * In order to support this, we keep a "register" of supported hash algorithms.
	 * Every hash algorithm in the system is assigned a unique ID (a uint8),
	 * along with a corresponding short identifier.
	 * 
	 * For example: 0 => "sha256"
	 * 
	 * Note: Since we are expecting there to be very few hash algorithms used
	 * in practice (probably just 1 or 2), we artificially limit the size of
	 * the hashTypes array to 256 entries. This allows us to use uint8 throughout
	 * the rest of the contract.
	**/
	string[] public hashTypes;

	/**
	 * We batch the public keys of multiple users into a single merkle tree,
	 * and then publish the merkle tree root to the blockchain.
	 * 
	 * Note: merkleTreeRoots[0] is initialized in the constructor to store
	 * the block number of when the contract was published.
	**/
	struct MerkleInfo {
		bytes merkleTreeRoot;
		uint blockNumber;
	}
	MerkleInfo[] public merkleTreeRoots;

	/**
	 * users[userID][hashTypeID] => merkleTreeRootsIndex
	 * 
	 * A value of zero indicates that a merkleTreeRoot has not been
	 * published for the <userID, hashTypeID> tuple.
	 * A nonzero value can be used as the index for the merkleTreeRoots array.
	 * 
	 * Note: merkleTreeRoots[0] is initialized in the constructor to store
	 * the block number of when the contract was published.
	 * Thus: merkleTreeRoots[0].merkleTreeRoot.length == 0
	**/
	mapping(bytes20 => mapping(uint8 => uint)) public users;

	event HashTypeAdded(uint8 hashTypeID);
	event MerkleTreeRootAdded(uint8 hashTypeID, bytes merkleTreeRoot);

	function PubKeyTrust() public {
		owner = msg.sender;
		merkleTreeRoots.push(MerkleInfo(new bytes(0), block.number));
	}

	modifier onlyByOwner()
	{
		if (msg.sender != owner)
			require(false);
		else
			_;
	}

	function numHashTypes() public view returns (uint) {

		return hashTypes.length;
	}

	function addHashType(string description) public onlyByOwner returns(bool, uint8) {

		uint hashTypeID = hashTypes.length;

		// Restrictions:
		// - there cannot be more than 256 different hash types
		// - the description cannot be the empty string
		// - the description cannot be over 64 bytes long
		if (hashTypeID >= 256) require(false);
		if (bytes(description).length == 0) require(false);
		if (bytes(description).length > 64) require(false);

		// Ensure the given description doesn't already exist
		for (uint i = 0; i < hashTypeID; i++)
		{
			if (stringsEqual(hashTypes[i], description)) {
				return (false, uint8(0));
			}
		}

		// Go ahead and add the new hash type
		hashTypes.push(description);
		HashTypeAdded(uint8(hashTypeID));

		return (true, uint8(hashTypeID));
	}

	/**
	 * We originally passed the userIDs as: bytes20[] userIDs
	 * But it was discovered that this was inefficiently packed,
	 * and ended up sending 12 bytes of zero's per userID.
	 * Since gtxdatazero is set to 4 gas/bytes, this translated into
	 * 48 gas wasted per user due to inefficient packing.
	**/
	function addMerkleTreeRoot(uint8 hashTypeID, bytes merkleTreeRoot, bytes userIDsPacked) public onlyByOwner {

		if (hashTypeID >= hashTypes.length) require(false);
		if (merkleTreeRoot.length == 0) require(false);

		uint index = merkleTreeRoots.length;
		bool addedIndexForUser = false;

		uint numUserIDs = userIDsPacked.length / 20;
		for (uint i = 0; i < numUserIDs; i++)
		{
			bytes20 userID;
			assembly {
				userID := mload(add(userIDsPacked, add(32, mul(20, i))))
			}

			uint existingIndex = users[userID][hashTypeID];
			if (existingIndex == 0)
			{
				users[userID][hashTypeID] = index;
				addedIndexForUser = true;
			}
		}

		if (addedIndexForUser)
		{
			merkleTreeRoots.push(MerkleInfo(merkleTreeRoot, block.number));
			MerkleTreeRootAdded(hashTypeID, merkleTreeRoot);
		}
	}

	function getMerkleTreeRoot(bytes20 userID, uint8 hashTypeID) public view returns (bytes) {

		uint merkleTreeRootsIndex = users[userID][hashTypeID];
		if (merkleTreeRootsIndex == 0) {
			return new bytes(0);
		}
		else {
			MerkleInfo storage merkleInfo = merkleTreeRoots[merkleTreeRootsIndex];
			return merkleInfo.merkleTreeRoot;
		}
	}

	function getBlockNumber(bytes20 userID, uint8 hashTypeID) public view returns (uint) {

		uint merkleTreeRootsIndex = users[userID][hashTypeID];
		if (merkleTreeRootsIndex == 0) {
			return 0;
		}
		else {
			MerkleInfo storage merkleInfo = merkleTreeRoots[merkleTreeRootsIndex];
			return merkleInfo.blockNumber;
		}
	}

	// Utility function (because string comparison doesn't exist natively in Solidity yet)
	function stringsEqual(string storage _a, string memory _b) internal view returns (bool) {

		bytes storage a = bytes(_a);
		bytes memory b = bytes(_b);
		if (a.length != b.length) {
			return false;
		}
		for (uint i = 0; i < a.length; i++) {
			if (a[i] != b[i]) {
				return false;
			}
		}
		return true;
	}
}

    Contract ABI  
[{"constant":false,"inputs":[{"name":"hashTypeID","type":"uint8"},{"name":"merkleTreeRoot","type":"bytes"},{"name":"userIDsPacked","type":"bytes"}],"name":"addMerkleTreeRoot","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"merkleTreeRoots","outputs":[{"name":"merkleTreeRoot","type":"bytes"},{"name":"blockNumber","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numHashTypes","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"userID","type":"bytes20"},{"name":"hashTypeID","type":"uint8"}],"name":"getMerkleTreeRoot","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes20"},{"name":"","type":"uint8"}],"name":"users","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"userID","type":"bytes20"},{"name":"hashTypeID","type":"uint8"}],"name":"getBlockNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"description","type":"string"}],"name":"addHashType","outputs":[{"name":"","type":"bool"},{"name":"","type":"uint8"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"hashTypes","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"hashTypeID","type":"uint8"}],"name":"HashTypeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"hashTypeID","type":"uint8"},{"indexed":false,"name":"merkleTreeRoot","type":"bytes"}],"name":"MerkleTreeRootAdded","type":"event"}]

  Contract Creation Code Switch To Opcodes View
606060405234156200001057600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060028054806001018281620000669190620000e6565b9160005260206000209060020201600060408051908101604052806000604051805910620000915750595b9080825280601f01601f191660200182016040525081526020014381525090919091506000820151816000019080519060200190620000d29291906200011b565b506020820151816001015550505062000252565b8154818355818115116200011657600202816002028360005260206000209182019101620001159190620001a2565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200015e57805160ff19168380011785556200018f565b828001600101855582156200018f579182015b828111156200018e57825182559160200191906001019062000171565b5b5090506200019e9190620001de565b5090565b620001db91905b80821115620001d75760008082016000620001c5919062000206565b600182016000905550600201620001a9565b5090565b90565b6200020391905b80821115620001ff576000816000905550600101620001e5565b5090565b90565b50805460018160011615610100020316600290046000825580601f106200022e57506200024f565b601f0160209004906000526020600020908101906200024e9190620001de565b5b50565b6110b280620002626000396000f300606060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063084d113b1461009e5780631c7b10aa1461014a57806340aee1a91461020a5780634326e22b1461023357806367578f65146102ea5780638051d02d1461033c5780638da5cb5b1461038e578063de0fe922146103e3578063fececa8414610465575b600080fd5b34156100a957600080fd5b610148600480803560ff1690602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610501565b005b341561015557600080fd5b61016b60048080359060200190919050506107b6565b60405180806020018381526020018281038252848181546001816001161561010002031660029004815260200191508054600181600116156101000203166002900480156101fa5780601f106101cf576101008083540402835291602001916101fa565b820191906000526020600020905b8154815290600101906020018083116101dd57829003601f168201915b5050935050505060405180910390f35b341561021557600080fd5b61021d6107e8565b6040518082815260200191505060405180910390f35b341561023e57600080fd5b61026f60048080356bffffffffffffffffffffffff191690602001909190803560ff169060200190919050506107f5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102af578082015181840152602081019050610294565b50505050905090810190601f1680156102dc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156102f557600080fd5b61032660048080356bffffffffffffffffffffffff191690602001909190803560ff16906020019091905050610946565b6040518082815260200191505060405180910390f35b341561034757600080fd5b61037860048080356bffffffffffffffffffffffff191690602001909190803560ff1690602001909190505061096b565b6040518082815260200191505060405180910390f35b341561039957600080fd5b6103a16109fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103ee57600080fd5b61043e600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610a21565b60405180831515151581526020018260ff1660ff1681526020019250505060405180910390f35b341561047057600080fd5b6104866004808035906020019091905050610bb7565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104c65780820151818401526020810190506104ab565b50505050905090810190601f1680156104f35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000806000806000806000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610572576000151561056d57600080fd5b6107ab565b6001805490508960ff16101515610591576000151561059057600080fd5b5b6000885114156105a957600015156105a857600080fd5b5b600280549050955060009450601487518115156105c257fe5b049350600092505b838310156106915782601402602001870151915060036000836bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200190815260200160002060008a60ff1660ff1681526020019081526020016000205490506000811415610684578560036000846bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200190815260200160002060008b60ff1660ff16815260200190815260200160002081905550600194505b82806001019350506105ca565b84156107aa57600280548060010182816106ab9190610dfc565b9160005260206000209060020201600060408051908101604052808c815260200143815250909190915060008201518160000190805190602001906106f1929190610e2e565b50602082015181600101555050507f6c20fcdd9bacac0fd0070f001e89ac1bb7080f9ec3712529d475139910f2cd2c8989604051808360ff1660ff16815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561076e578082015181840152602081019050610753565b50505050905090810190601f16801561079b5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a15b5b505050505050505050565b6002818154811015156107c557fe5b906000526020600020906002020160009150905080600001908060010154905082565b6000600180549050905090565b6107fd610eae565b60008060036000866bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200190815260200160002060008560ff1660ff168152602001908152602001600020549150600082141561087f5760006040518059106108635750595b9080825280601f01601f1916602001820160405250925061093e565b60028281548110151561088e57fe5b90600052602060002090600202019050806000018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109365780601f1061090b57610100808354040283529160200191610936565b820191906000526020600020905b81548152906001019060200180831161091957829003601f168201915b505050505092505b505092915050565b6003602052816000526040600020602052806000526040600020600091509150505481565b600080600060036000866bffffffffffffffffffffffff19166bffffffffffffffffffffffff1916815260200190815260200160002060008560ff1660ff16815260200190815260200160002054915060008214156109cd57600092506109f4565b6002828154811015156109dc57fe5b90600052602060002090600202019050806001015492505b505092915050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000806000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610a8f5760001515610a8a57600080fd5b610bb0565b600180549050915061010082101515610ab05760001515610aaf57600080fd5b5b600085511415610ac85760001515610ac757600080fd5b5b604085511115610ae05760001515610adf57600080fd5b5b600090505b81811015610b2e57610b10600182815481101515610aff57fe5b906000526020600020900186610c73565b15610b215760008093509350610baf565b8080600101915050610ae5565b60018054806001018281610b429190610ec2565b916000526020600020900160008790919091509080519060200190610b68929190610eee565b50507f8f1cc94e8773f773b1550f5e9f243135f26ad89dbd49b0c62c36fd6a2f69d59782604051808260ff1660ff16815260200191505060405180910390a1600182935093505b5b5050915091565b600181815481101515610bc657fe5b90600052602060002090016000915090508054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c6b5780601f10610c4057610100808354040283529160200191610c6b565b820191906000526020600020905b815481529060010190602001808311610c4e57829003601f168201915b505050505081565b600080610c7e610eae565b6000859250849150815183805460018160011615610100020316600290049050141515610cae5760009350610df3565b600090505b82805460018160011615610100020316600290049050811015610dee578181815181101515610cde57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191683828154600181600116156101000203166002900481101515610d6a57fe5b815460011615610d895790600052602060002090602091828204019190065b9054901a7f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141515610de15760009350610df3565b8080600101915050610cb3565b600193505b50505092915050565b815481835581811511610e2957600202816002028360005260206000209182019101610e289190610f6e565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610e6f57805160ff1916838001178555610e9d565b82800160010185558215610e9d579182015b82811115610e9c578251825591602001919060010190610e81565b5b509050610eaa9190610fa5565b5090565b602060405190810160405280600081525090565b815481835581811511610ee957818360005260206000209182019101610ee89190610fca565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610f2f57805160ff1916838001178555610f5d565b82800160010185558215610f5d579182015b82811115610f5c578251825591602001919060010190610f41565b5b509050610f6a9190610fa5565b5090565b610fa291905b80821115610f9e5760008082016000610f8d9190610ff6565b600182016000905550600201610f74565b5090565b90565b610fc791905b80821115610fc3576000816000905550600101610fab565b5090565b90565b610ff391905b80821115610fef5760008181610fe6919061103e565b50600101610fd0565b5090565b90565b50805460018160011615610100020316600290046000825580601f1061101c575061103b565b601f01602090049060005260206000209081019061103a9190610fa5565b5b50565b50805460018160011615610100020316600290046000825580601f106110645750611083565b601f0160209004906000526020600020908101906110829190610fa5565b5b505600a165627a7a723058206f908417c40dd3bc5af85ef04361caa41a2ef5da3f03de60c1da6f6d11f7a41a0029

   Swarm Source:
bzzr://6f908417c40dd3bc5af85ef04361caa41a2ef5da3f03de60c1da6f6d11f7a41a

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.