Creating a specification file

Nodes of every network share a common specification file. This file tells the node about the genesis block, who the validators are, and so on. We will create a smart contract, which will contain the validators list. There are two types of validator contracts: non-reporting contract and reporting contract. We have to provide only one.

The difference is that non-reporting contract only returns a list of validators, whereas reporting contract can take action for benign (benign misbehaviour may be simply not receiving a block from a designated validator) and malicious misbehavior (malicious misbehaviour would be releasing two different blocks for the same step).

The non-reporting contract should have at least this interface:

{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"}

The getValidators function will be called on every block to determine the current list. The switching rules are then determined by the contract implementing that method.

A reporting contract should have at least this interface:

[ 
{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"},
{"constant":false,"inputs":[{"name":"validator","type":"address"}],"name":"reportMalicious","outputs":[],"payable":false,"type":"function"},
{"constant":false,"inputs":[{"name":"validator","type":"address"}],"name":"reportBenign","outputs":[],"payable":false,"type":"function"}
]

When there is benign or malicious behavior, the consensus engine calls the reportBenign and reportMalicious functions respectively.

Let's create a reporting contract. Here is a basic example:

contract ReportingContract { 
address[] public validators = [0x831647ec69be4ca44ea4bd1b9909debfbaaef55c, 0x12a6bda0d5f58538167b2efce5519e316863f9fd];
mapping(address => uint) indices;
address public disliked;

function ReportingContract() {
for (uint i = 0; i < validators.length; i++) {
indices[validators[i]] = i;
}
}

// Called on every block to update node validator list.
function getValidators() constant returns (address[]) {
return validators;
}

// Expand the list of validators.
function addValidator(address validator) {
validators.push(validator);
}

// Remove a validator from the list.
function reportMalicious(address validator) {
validators[indices[validator]] = validators[validators.length-1];
delete indices[validator];
delete validators[validators.length-1];
validators.length--;
}

function reportBenign(address validator) {
disliked = validator;
}
}

This code is self-explanatory. Make sure that in the validators array replaces the addresses with the first address of validator 1 and validator 2 nodes as we will be using those addresses for validation. Now compile the preceding contract using whatever you feel comfortable with.

Now let's create the specification file. Create a file named spec.json, and place this code in it:

{ 
"name": "ethereum",
"engine": {
"authorityRound": {
"params": {
"gasLimitBoundDivisor": "0x400",
"stepDuration": "5",
"validators" : {
"contract": "0x0000000000000000000000000000000000000005"
}
}
}
},
"params": {
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2323"
},
"genesis": {
"seal": {
"authorityRound": {
"step": "0x0",
"signature": "0x00000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000"
}
},
"difficulty": "0x20000",
"gasLimit": "0x5B8D80"
},
"accounts": {
"0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0x0000000000000000000000000000000000000005": { "balance": "1", "constructor" : "0x606060405260406040519081016040528073831647" },
"0x004ec07d2329997267Ec62b4166639513386F32E": { "balance": "10000000000000000000000" }
}
}

Here is how the preceding file works:

  • The engine property is used to set the consensus protocol and the protocol-specific parameters. Here, the engine is authorityRound, which is aura. gasLimitBoundDivisor determines gas limit adjustment and has the usual ethereum value. In the validators property, we have a contract property, which is the address of the reporting contract. stepDuration is the block time in seconds.
  • In the params property, only the network ID is what matters; others are standard for all chains.
  • genesis has some standard values for the authorityRound consensus.
  • accounts is used to list the initial accounts and contracts that exist in the network. The first four are standard Ethereum built-in contracts; these should be included to use the Solidity contract writing language. The fifth one is the reporting contract. Make sure you replace the byte code with your byte code in the constructor param. The last account is the second account we generated in the validator 1 shell. It is used to supply ether to the network. Replace this address with yours.

Before we proceed further, create another file called as node.pwds. In that file, place the password of the accounts you created. This file will be used by the validators to unlock the accounts to sign the blocks.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.52.8