汪晓明对区块链、以太坊的思考

记录创业、生活的所思所感,探讨去中心化思想,推动区块链的发展。

HPB74:HPB主网接入最佳实践之JS版

1、开始准备

1.1 学习门槛

1.2 源码地址

1
https://github.com/loglos/web3.git

2、HPB JavaScript API使用说明

This is the HPB compatible JavaScript API which implements the Generic JSON RPC spec.

You need to run a local HPB node to use this library.

2.1 Table of Contents

As a Browser module

CDN

1
<script type="text/javascript" src="https://hpb.io/web_hpb.min.js"></script>
  • Include web3_hpb.min.js in your html file.

2.2 Usage

Use the web3_hpb object directly from the global namespace:

1
2
3
var Web3ForHpb = require('web3_hpb');
var web3Hpb = new Web3ForHpb();
console.log(web3Hpb); //{ hpb:..., shh:... }

Set a provider (HttpProvider):

1
2
// Set the provider you want from Web3.providers
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));

There you go, now you can use it:

1
2
var coinbase = web3Hpb.hpb.coinbase;
var balance = web3Hpb.hpb.getBalance(coinbase);

3、HPB JavaScript API examples

3.1 balance

https://github.com/yanranxiaoxiaoshu/web3/blob/master/web3_hpb/example/balance.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE html>
<html>

<head>
    <script type="text/javascript" src="../node_modules/bignumber.js/bignumber.min.js"></script>
    <script type="text/javascript" src="../dist/web3_hpb-light.js"></script>
    <script type="text/javascript">

        var web3_hpb = require('web3_hpb');
        var web3_hpb = new web3_hpb();
        web3_hpb.setProvider(new web3_hpb.providers.HttpProvider());

        function watchBalance() {
            var coinbase = web3_hpb.hpb.coinbase;

            var originalBalance = web3_hpb.hpb.getBalance(coinbase).toNumber();
            document.getElementById('coinbase').innerText = 'coinbase: ' + coinbase;
            document.getElementById('original').innerText = ' original balance: ' + originalBalance + '    watching...';

            web3_hpb.hpb.filter('latest').watch(function () {
                var currentBalance = web3_hpb.hpb.getBalance(coinbase).toNumber();
                document.getElementById("current").innerText = 'current: ' + currentBalance;
                document.getElementById("diff").innerText = 'diff:    ' + (currentBalance - originalBalance);
            });
        }

    </script>
</head>

<body>
    <h1>coinbase balance</h1>
    <button type="button" onClick="watchBalance();">watch balance</button>
    <div></div>
    <div id="coinbase"></div>
    <div id="original"></div>
    <div id="current"></div>
    <div id="diff"></div>
</body>

</html>

3.2 contract

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<!DOCTYPE html>
<html>

<head>
<script type="text/javascript" src="../dist/web3_hpb.js"></script>
<script type="text/javascript">
    var web3_hpb = require('web3_hpb');
    var web3_hpb = new web3_hpb();
    web3_hpb.setProvider(new web3_hpb.providers.HttpProvider("http://localhost:8545"));
    // solidity code code
    var source = "" +
    "pragma solidity ^0.4.6;" +
    "contract test {\n" +
    "   function multiply(uint a) constant returns(uint d) {\n" +
    "       return a * 7;\n" +
    "   }\n" +
    "}\n";
    var compiled = web3_hpb.hpb.compile.solidity(source);
    var code = compiled.code;
    // contract json abi, this is autogenerated using solc CLI
    var abi = compiled.info.abiDefinition;
    var myContract;
    function createExampleContract() {
        // hide create button
        document.getElementById('create').style.visibility = 'hidden';
        document.getElementById('code').innerText = code;
        // let's assume that coinbase is our account
        web3_hpb.hpb.defaultAccount = web3_hpb.hpb.coinbase;
        // create contract
        document.getElementById('status').innerText = "transaction sent, waiting for confirmation";
        web3_hpb.hpb.contract(abi).new({data: code}, function (err, contract) {
            if(err) {
                console.error(err);
                return;
            // callback fires twice, we only want the second call when the contract is deployed
            } else if(contract.address){
                myContract = contract;
                console.log('address: ' + myContract.address);
                document.getElementById('status').innerText = 'Mined!';
                document.getElementById('call').style.visibility = 'visible';
            }
        });
    }
    function callExampleContract() {
        // this should be generated by hpber
        var param = parseInt(document.getElementById('value').value);
        // call the contract
        var res = myContract.multiply(param);
        document.getElementById('result').innerText = res.toString(10);
    }
</script>
</head>
<body>
    <h1>contract</h1>
    <div id="code"></div> 
    <div id="status"></div>
    <div id='create'>
        <button type="button" onClick="createExampleContract();">create example contract</button>
    </div>
    <div id='call' style='visibility: hidden;'>
        <input type="number" id="value" onkeyup='callExampleContract()'></input>
    </div>
    <div id="result"></div>
</body>
</html>

3.3 contract_array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<!DOCTYPE html>
<html>

<head>
<script type="text/javascript" src="../dist/web3_hpb.js"></script>
<script type="text/javascript">
    var web3_hpb = require('web3_hpb');
    var web3_hpb = new web3_hpb();
    web3_hpb.setProvider(new web3_hpb.providers.HttpProvider("http://localhost:8545"));
    // solidity code code
    var source = "" +
    "pragma solidity ^0.4.6;" +
    "contract test {\n" +
    "   function take(uint[] a, uint b) constant returns(uint d) {\n" +
    "       return a[b];\n" +
    "   }\n" +
    "}\n";
    var compiled = web3_hpb.hpb.compile.solidity(source);
    var code = compiled.code;
    // contract json abi, this is autogenerated using solc CLI
    var abi = compiled.info.abiDefinition;
    var myContract;
    function createExampleContract() {
        // hide create button
        document.getElementById('create').style.visibility = 'hidden';
        document.getElementById('code').innerText = code;
        // let's assume that coinbase is our account
        web3_hpb.hpb.defaultAccount = web3_hpb.hpb.coinbase;
        // create contract
        document.getElementById('status').innerText = "transaction sent, waiting for confirmation";
        web3_hpb.hpb.contract(abi).new({data: code}, function (err, contract) {
            if (err) {
                console.error(err);
                return;
            // callback fires twice, we only want the second call when the contract is deployed
            } else if(contract.address){
                myContract = contract;
                console.log('address: ' + myContract.address);
                document.getElementById('status').innerText = 'Mined!';
                document.getElementById('call').style.visibility = 'visible';
            }
        });
    }
    function callExampleContract() {
        // this should be generated by hpber
        var param = parseInt(document.getElementById('value').value);
        // call the contract
        var res = myContract.take([0,6,5,2,1,5,6], param);
        document.getElementById('result').innerText = res.toString(10);
    }
</script>
</head>
<body>
    <h1>contract</h1>
    <div id="code"></div> 
    <div id="status"></div>
    <div id='create'>
        <button type="button" onClick="createExampleContract();">create example contract</button>
    </div>
    <div id='call' style='visibility: hidden;'>
        <div>var array = [0,6,5,2,1,5,6];</div>
        <div>var x = array[
            <input type="number" id="value" onkeyup='callExampleContract()'></input>
        ];
        </div>
    </div>
    <div id="result"></div>
</body>
</html>

3.4 event_inc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<!DOCTYPE html>
<html>
    <head>
    <script type="text/javascript" src="../dist/web3_hpb.js"></script>
    <script type="text/javascript">
        var web3_hpb = require('web3_hpb');
        var web3_hpb = new web3_hpb();
        web3_hpb.setProvider(new web3_hpb.providers.HttpProvider('http://localhost:8545'));
        var source = "" +
        "pragma solidity ^0.4.6;" +
        "contract Contract { " +
        "   event Incremented(bool indexed odd, uint x); " +
        "   function Contract() { " +
        "        x = 70; " +
        "    } " +
        "    function inc() { " +
        "        ++x; " +
        "        Incremented(x % 2 == 1, x); " +
        "    } " +
        "    uint x; " +
        "}";
        var compiled = web3_hpb.hpb.compile.solidity(source);
        var code = compiled.code;
        var abi = compiled.info.abiDefinition;
        var address;
        var contract;
        var inc;
        var update = function (err, x) {
            document.getElementById('result').textContent = JSON.stringify(x, null, 2);
        };

        var createContract = function () {
            // let's assume that we have a private key to coinbase ;)
            web3_hpb.hpb.defaultAccount = web3_hpb.hpb.coinbase;

            document.getElementById('create').style.visibility = 'hidden';
            document.getElementById('status').innerText = "transaction sent, waiting for confirmation";
            web3_hpb.hpb.contract(abi).new({data: code}, function (err, c) {
                if (err) {
                    console.error(err);
                    return;
                // callback fires twice, we only want the second call when the contract is deployed
                } else if(c.address){
                    contract = c;
                    console.log('address: ' + contract.address);
                    document.getElementById('status').innerText = 'Mined!';
                    document.getElementById('call').style.visibility = 'visible';
                    inc = contract.Incremented({odd: true}, update);
                }
            });
        };
        var counter = 0;
        var callContract = function () {
            counter++;
            var all = 70 + counter;
            document.getElementById('count').innerText = 'Transaction sent ' + counter + ' times. ' +
                'Expected x value is: ' + (all - (all % 2 ? 0 : 1)) + ' ' +
                'Waiting for the blocks to be mined...';

            contract.inc();
        };
    </script>
    </head>

    <body>
        <div id="status"></div>
        <div>
            <button id="create" type="button" onClick="createContract();">create contract</button>
        </div>
        <div>
            <button id="call" style="visibility: hidden;" type="button" onClick="callContract();">test1</button>
        </div>
        <div id='count'></div>
        <div id="result">
        </div>
    </body>

3.5 icap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
<!DOCTYPE html>
<html>

<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script type="text/javascript" src="../dist/web3_hpb.js"></script>
<script type="text/javascript">
    var web3_hpb = require('web3_hpb');
    var web3_hpb = new web3_hpb();
    var BigNumber = require('bignumber.js');
    web3_hpb.setProvider(new web3_hpb.providers.HttpProvider("http://localhost:8545"));
    var from = web3_hpb.hpb.coinbase;
    web3_hpb.hpb.defaultAccount = from;
    var nameregAbi = [
        {"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"name","outputs":[{"name":"o_name","type":"bytes32"}],"type":"function"},
        {"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},
        {"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"content","outputs":[{"name":"","type":"bytes32"}],"type":"function"},
        {"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"addr","outputs":[{"name":"","type":"address"}],"type":"function"},
        {"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[],"type":"function"},
        {"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"subRegistrar","outputs":[{"name":"o_subRegistrar","type":"address"}],"type":"function"},
        {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_newOwner","type":"address"}],"name":"transfer","outputs":[],"type":"function"},
        {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_registrar","type":"address"}],"name":"setSubRegistrar","outputs":[],"type":"function"},
        {"constant":false,"inputs":[],"name":"Registrar","outputs":[],"type":"function"},
        {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_a","type":"address"},{"name":"_primary","type":"bool"}],"name":"setAddress","outputs":[],"type":"function"},
        {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_content","type":"bytes32"}],"name":"setContent","outputs":[],"type":"function"},
        {"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"disown","outputs":[],"type":"function"},
        {"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"address"}],"type":"function"},
        {"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"}],"name":"Changed","type":"event"},
        {"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"addr","type":"address"}],"name":"PrimaryChanged","type":"event"}
    ];
    var depositAbi = [{"constant":false,"inputs":[{"name":"name","type":"bytes32"}],"name":"deposit","outputs":[],"type":"function"}];
    var Namereg = web3_hpb.hpb.contract(nameregAbi);
    var Deposit = web3_hpb.hpb.contract(depositAbi);
    var namereg = web3_hpb.hpb.ibanNamereg;
    var deposit;
    var iban;
    function validateNamereg() {
        var address = document.getElementById('namereg').value;
        var ok = web3_hpb.isAddress(address) || address === 'default';
        if (ok) {
            namereg = address === 'default' ? web3_hpb.hpb.ibanNamereg : Namereg.at(address);
            document.getElementById('nameregValidation').innerText = 'ok!';
        } else {
            document.getElementById('nameregValidation').innerText = 'namereg address is incorrect!';
        }
        return ok;
    };
    function onNameregKeyUp() {
        updateIBAN(validateNamereg());
        onExchangeKeyUp();
    };

    function validateExchange() {
        var exchange = document.getElementById('exchange').value;
        var ok = /^[0-9A-Z]{4}$/.test(exchange);
        if (ok) {
            var address = namereg.addr(exchange);
            deposit = Deposit.at(address);
            document.getElementById('exchangeValidation').innerText = 'ok! address of exchange: ' + address;
        } else {
            document.getElementById('exchangeValidation').innerText = 'exchange id is incorrect';
        }
        return ok;
    };
    function onExchangeKeyUp() {
        updateIBAN(validateExchange());
    };
    function validateClient() {
        var client = document.getElementById('client').value;
        var ok = /^[0-9A-Z]{9}$/.test(client);
        if (ok) {
            document.getElementById('clientValidation').innerText = 'ok!';
        } else {
            document.getElementById('clientValidation').innerText = 'client id is incorrect';
        }
        return ok;
    };
    function onClientKeyUp() {
        updateIBAN(validateClient());
    };
    function validateValue() {
        try {
            var value = document.getElementById('value').value;
            var bnValue = new BigNumber(value);
            document.getElementById('valueValidation').innerText = bnValue.toString(10);
            return true;
        } catch (err) {
            document.getElementById('valueValidation').innerText = 'Value is incorrect, cannot parse';
            return false;
        }
    };
    function onValueKeyUp() {
        validateValue();
    };
    function validateIBAN() {
        if (!iban.isValid()) {
            return document.getElementById('ibanValidation').innerText = ' - IBAN number is incorrect';
        }
        document.getElementById('ibanValidation').innerText = ' - IBAN number correct';
    };
    function updateIBAN(ok) {
        var exchangeId = document.getElementById('exchange').value;
        var clientId = document.getElementById('client').value;
        iban = web3_hpb.hpb.iban.createIndirect({
            institution: exchangeId,
            identifier: clientId
        });
        document.getElementById('iban').innerText = iban.toString();
        validateIBAN();
    };
    function transfer() {
        var value = new BigNumber(document.getElementById('value').value);
        var exchange = document.getElementById('exchange').value;
        var client = document.getElementById('client').value;
        deposit.deposit(web3_hpb.fromAscii(client), {value: value});
        displayTransfer("deposited client's " + client + " funds " + value.toString(10) + " to exchange " + exchange);
    };
    function displayTransfer(text) {
        var node = document.createElement('li');
        var textnode = document.createTextNode(text);
        node.appendChild(textnode);
        document.getElementById('transfers').appendChild(node);
    }

</script>
</head>
<body>
    <div class="col-lg-12">
        <i>This page expects ghpb with JSON-RPC running at port 8545</i>
        <div class="page-header">
            <h1>ICAP transfer</h1>
        </div>
        <div class="col-lg-6">
            <div class="well">
                <legend class="lead">namereg address</legend>
                <small>eg. 0x436474facc88948696b371052a1befb801f003ca or 'default')</small>
                <div class="form-group">
                    <input class="form-control" type="text" id="namereg" onkeyup='onNameregKeyUp()' value="default"></input>
                    <text id="nameregValidation"></text>
                </div>

                <legend class="lead">exchange identifier</legend>
                <small>eg. WYWY</small>
                <div class="form-group">
                    <input class="form-control" type="text" id="exchange" onkeyup='onExchangeKeyUp()'></input>
                    <text id="exchangeValidation"></text>
                </div>

                <legend class="lead">client identifier</legend>
                <small>eg. GAVOFYORK</small>
                <div class="form-group">
                    <input class="form-control" type="text" id="client" onkeyup='onClientKeyUp()'></input>
                    <text id="clientValidation"></text>
                </div>

                <legend class="lead">value</legend>
                <small>eg. 100</small>
                <div class="form-group">
                    <input class="form-control" type="text" id="value" onkeyup='onValueKeyUp()'></input>
                    <text id="valueValidation"></text>
                </div>

                <legend class="lead">IBAN: </legend>
                <div class="form-group">

                    <text id="iban"></text>
                    <text id="ibanValidation"></text>
                </div>
                <div>
                    <button class="btn btn-default" id="transfer" type="button" onClick="transfer()">Transfer!</button>
                    <text id="transferValidation"></text>
                </div>
            </div>
        </div>
        <div class="col-lg-6">
            <div class="well">
                <div>
                    <legend class="lead">transfers</legend>
                </div>
                <div>
                    <ul id='transfers'></ul>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

3.6 namereg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<!DOCTYPE html>
<html>

<head>
<script type="text/javascript" src="../dist/web3_hpb.js"></script>
<script type="text/javascript">
    var web3_hpb = require('web3_hpb');
    var web3_hpb = new web3_hpb();
    web3_hpb.setProvider(new web3_hpb.providers.HttpProvider("http://localhost:8545"));
    var from = web3_hpb.hpb.coinbase;
    web3_hpb.hpb.defaultAccount = from;
    window.onload = function () {
        var filter = web3_hpb.hpb.namereg().Changed();
        filter.watch(function (err, event) {
            // live update all fields
            onAddressKeyUp();
            onNameKeyUp();
            onRegisterOwnerKeyUp();
        });
    };
    function registerOwner() {
        var name = document.getElementById('registerOwner').value;
        web3_hpb.hpb.namereg().reserve(name);
        document.getElementById('nameAvailability').innerText += ' Registering name in progress, please wait...';
    };

    function changeAddress() {
        var name = document.getElementById('registerOwner').value;
        var address = document.getElementById('newAddress').value;
        web3_hpb.hpb.namereg().setAddress(name, address, true);
        document.getElementById('currentAddress').innerText += ' Changing address in progress. Please wait.';
    };
    function onRegisterOwnerKeyUp() {
        var name = document.getElementById('registerOwner').value;
        var owner = web3_hpb.hpb.namereg().owner(name)
        document.getElementById('currentAddress').innerText = web3_hpb.hpb.namereg().addr(name);
        if (owner !== '0x0000000000000000000000000000000000000000') {
            if (owner === from) {
                document.getElementById('nameAvailability').innerText = "This name is already owned by you " + owner;
            } else {
                document.getElementById('nameAvailability').innerText = "This name is not available. It's already registered by " + owner;
            }
            return;
        }
        document.getElementById('nameAvailability').innerText = "This name is available. You can register it.";
    };
    function onAddressKeyUp() {
        var address = document.getElementById('address').value;
        document.getElementById('nameOf').innerText = web3_hpb.hpb.namereg().name(address);
    };

    function onNameKeyUp() {
        var name = document.getElementById('name').value;
        document.getElementById('addressOf').innerText = web3_hpb.hpb.namereg().addr(name);
    };
</script>
</head>
<body>
    <i>This example shows only part of namereg functionalities. Namereg contract is available <a href="https://github.com/hpber/dapp-bin/blob/master/GlobalRegistrar/contract.sol">here</a>
    </i>
    <h1>Namereg</h1>
    <h3>Search for name</h3>
    <div>
        <text>Address: </text>
        <input type="text" id="address" onkeyup='onAddressKeyUp()'></input>
        <text>Name: </text>
        <text id="nameOf"></text>
    </div>
    <h3>Search for address</h3>
    <div>
        <text>Name: </text>
        <input type="text" id="name" onkeyup='onNameKeyUp()'></input>
        <text>Address: </text>
        <text id="addressOf"></text>
    </div>
    <h3>Register name</h3>
    <div>
        <text>Check if name is available: </text>
        <input type="text" id="registerOwner" onkeyup='onRegisterOwnerKeyUp()'></input>
        <text id='nameAvailability'></text>
    </div>
    <div>
        <button id="registerOwnerButton" type="button" onClick="registerOwner()">Register!</button>
    </div>
    <h3></h3>
    <i>If you own the name, you can  also change the address it points to</i>
    <div>
        <text>Address: </text>
        <input type="text" id="newAddress"></input>
        <button id="changeAddress" type="button" onClick="changeAddress()">Change address!</button>
        <text>Current address :</text>
        <text id="currentAddress"></text>
    </div>

</body>
</html>

3.7 node-app

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env node

var web3_hpb = require('../index.js');
var web3_hpb = new web3_hpb();

web3_hpb.setProvider(new web3_hpb.providers.HttpProvider('http://localhost:8545'));

var coinbase = web3_hpb.hpb.coinbase;
console.log(coinbase);

var balance = web3_hpb.hpb.getBalance(coinbase);
console.log(balance.toString(10));

3.8 signature-verifier

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
var web3_hpb = require('../index.js');
var hpbURL = "";
var defaultAc = "";
var defaultAcPWD="";
var signatureContractCodeReadable="\n\tcontract SignatureVerifier {\n\t\tfunction verify( bytes32 hash, uint8 v, bytes32 r, bytes32 s) \n"+
    "\t\tconstant returns(address returnAddress) {\n \t\t\treturnAddress = ecrecover(hash, v, r, s);\n\t\t}\n\t}\n\n";

var sigContractInstance = null;
var sigContractAddress= "";
var sigContractInstance = null;
var strAbi='[{"constant":true,"inputs":[{"name":"hash","type":"bytes32"},{"name":"v","type":"uint8"},{"name":"r","type":"bytes32"},{"name":"s","type":"bytes32"}],"name":"verify","outputs":[{"name":"returnAddress","type":"address"}],"payable":false,"type":"function"}]';
var signMessage="";

var hpbweb3_hpb = null;

function setContractAddress(conAddress){
    sigContractAddress = conAddress;
}

function setAccount(act){
    defaultAc = act;
}

function setPassword(pwd){
    defaultAcPWD = pwd;
}

function setHpbURL(url){
    hpbURL = url;
}

function setMessage(msg){
    signMessage = msg;
}

function initializeHpbConnection(){
   if(hpbweb3_hpb!=null && hpbweb3_hpb.isConnected()==true)  {
    return true;
  }

  hpbweb3_hpb = new web3_hpb(new web3_hpb.providers.HttpProvider(hpbURL));

  if(hpbweb3_hpb.isConnected()==true){
      if(defaultAc==''){
        defaultAc=hpbweb3_hpb.hpb.accounts[1];
      }
      return true;
  }

  return false;
}

function unlockAccount(acAddress){
  if(acAddress!=undefined && acAddress!=null){
    var state=hpbweb3_hpb.personal.unlockAccount(defaultAc, defaultAcPWD, 100);
    return state;
  }

  return false;
}


function initializeContract(){
    initializeHpbConnection();
    if(hpbweb3_hpb.isConnected()==false){
        return;
    }
    var abi = JSON.parse(strAbi);
    var contract = hpbweb3_hpb.hpb.contract(abi);

    sigContractInstance =  contract.at(sigContractAddress)
}

function signMessage(message){

    initializeHpbConnection();
    if(hpbweb3_hpb.isConnected()==false){
        return false;
    }

    var state=unlockAccount(defaultAc);

    const msg = new Buffer(message);
    const sig = hpbweb3_hpb.hpb.sign(defaultAc, '0x' + msg.toString('hex'));

    return sig;
}

function verifySignedByAc(message, sig){
    initializeHpbConnection();

    if(hpbweb3_hpb.isConnected()==false){
        return false;
    }
    initializeContract();

    const res = splitSig(sig);

    // Unfortunately Ghpb client adds this line to the message as a prefix while signing
    // So while finding who signed it we need to prefix this part 
    const prefix = new Buffer("\x19Hpb Signed Message:\n");
    const msg = new Buffer(message);
    const prefixedMsg = hpbweb3_hpb.sha3(
    Buffer.concat([prefix, new Buffer(String(msg.length)), msg]).toString('utf8')
    );

    var strPrefixedMsg=prefixedMsg;

    var finalAddress=sigContractInstance.verify.call(strPrefixedMsg, res.v, res.r, '0x'+ res.s);

    return finalAddress;
}

function splitSig(sig) {
  return {
    v: hpbweb3_hpb.toDecimal('0x' + sig.slice(130, 132)),
    r: sig.slice(0, 66),
    s: sig.slice(66, 130)
  }

}

function sign(){
    var message = document.getElementById('txtMessage').value;
    var signMsg = signMessage(message);
    document.getElementById('dvSig').innerText = signMsg;
}

function verify(){
    var message = document.getElementById('txtMessage').value;
    var actAddr = verifySignedByAc(message, document.getElementById('dvSig').innerText);
    document.getElementById('dvSignedBy').innerText = actAddr;
}


function execute(){
    console.log("\n\n**********************************************************************");
    console.log("Steps to Run");
    console.log("**********************************************************************");
    console.log("1. Deploy the following contract in your hpber environment");
    console.log(signatureContractCodeReadable);
    console.log("2. Set the following parameters (i.e. at the end of the code)");
    console.log("\ta. Hpb URL");
    console.log("\tb. Hpb Account Address");
    console.log("\tc. Hpb Account Passphrase");
    console.log("\td. Signature Contract Address");
    console.log("\te. Message for signing");
    console.log("**********************************************************************");

    if(hpbURL==''){
        console.log("Error: Hpb URL is not specified");
        return;
    }
    if(defaultAc==''){
        console.log("Error: Account Address is not specified");
        return;
    }
    if(defaultAcPWD==''){
        console.log("Error: Account password is not specified");
        return;
    }
    if(sigContractAddress==''){
        console.log("Error: Signature Contract Address is not specified");
        return;
    }
    if(signMessage==''){
        console.log("Error: Message for signing is not specified");
        return;
    }


    console.log("Following parameters applied");
    console.log("\ta. Hpb URL                  :",hpbURL);
    console.log("\tb. Hpb Account Address      :",defaultAc);
    console.log("\tc. Hpb Account Passphrase   :",defaultAcPWD);
    console.log("\td. Signature Contract Address    :",sigContractAddress);
    console.log("\te. Message for signing           :",signMessage);

    console.log("**********************************************************************");
    console.log("Result");
    console.log("**********************************************************************");

    var sig=signMessage(signMessage);
    console.log("Signature");
    console.log(sig);

    var addr=verifySignedByAc(signMessage, sig);
    console.log("Signed By");
    console.log(addr);

    console.log("**********************************************************************");
    console.log("Exit");
    console.log("**********************************************************************");
}

// Please uncomment the below listed three lines of code and provide the required values

// Value 1- Please provide the hpber account address which you want to use to perform the operation
//setAccount('<Provide the account address>');

// Value 2- Please provide the password of the accound to be used 
//setPassword('<Provide the password>');

// Value 3- Please update the address of the contract after deployment
// The contract code is made available at the top under signatureContractCodeReadable variable
// Please deploy the contract and update the contract address here
//setContractAddress('<Provide the deployed contract address>');

// Value 4- If required please update with a different message
setHpbURL('http://localhost:8545');

// Value 5- If required please update with a Hpb URL
setMessage('This the test sign message');


execute();

感谢HPB技术团队整理。

关于我

蓝莲花(汪晓明):HPB芯链(hpb.io)创始人,巴比特专栏作家。十余年金融大数据、区块链技术开发经验,曾参与创建银联大数据。主创区块链教学视频节目《明说》30多期,编写了《以太坊官网文档中文版》,并作为主要作者编写了《区块链开发指南》,在中国区块链社区以ID“蓝莲花”知名。2018年6月9日, HPB芯链荣登《2018胡润区块链企业排行榜》区块链创新企业TOP50。

公众号
小明微思考公众号

HPB

« HPB73:HPB P2P网络介绍