Added creator's signature to address book entry. Re-factory somethings and improve the merge of them
This commit is contained in:
parent
108824e294
commit
313fcd4808
4 changed files with 168 additions and 81 deletions
|
|
@ -753,16 +753,19 @@
|
||||||
<th>Address</td>
|
<th>Address</td>
|
||||||
<th>Creator</td>
|
<th>Creator</td>
|
||||||
<th>Date</td>
|
<th>Date</td>
|
||||||
<th> </td>
|
<th>Signature</td>
|
||||||
|
<th>Hidden</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="(addr, info) in $root.wallet.addressBook" ng-if="info.copayerId != -1">
|
<tr ng-repeat="(addr, info) in $root.wallet.addressBook track by $index" ng-if="info.copayerId != -1">
|
||||||
<td><a ng-click="copyAddress(addr)" title="Copy address">{{info.label}}</a></td>
|
<td><a ng-click="copyAddress(addr)" title="Copy address">{{info.label}}</a></td>
|
||||||
<td>{{addr}}</td>
|
<td>{{addr}}</td>
|
||||||
<td>{{$root.wallet.publicKeyRing.nicknameForCopayer(info.copayerId)}}</td>
|
<td>{{$root.wallet.publicKeyRing.nicknameForCopayer(info.copayerId)}}</td>
|
||||||
<td><time>{{info.createdTs | amCalendar}}</time></td>
|
<td><time>{{info.createdTs | amCalendar}}</time></td>
|
||||||
<td><a ng-click="deleteAddressBook(addr)"><i class="fi-trash"></i></a></td>
|
<td
|
||||||
|
ng-init="checkSignAddressBook(addr)">{{signAddressBook[addr]}}</td>
|
||||||
|
<td><a ng-click="toggleAddressBookEntry(addr)">{{info.hidden}}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
||||||
|
|
@ -186,23 +186,23 @@ angular.module('copayApp.controllers').controller('SendController',
|
||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.deleteAddressBook = function(addressBook) {
|
$scope.signAddressBook = {};
|
||||||
var w = $rootScope.wallet;
|
|
||||||
$timeout(function() {
|
|
||||||
var errorMsg;
|
|
||||||
try {
|
|
||||||
w.deleteAddressBook(addressBook);
|
|
||||||
} catch (e) {
|
|
||||||
errorMsg = e.message;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorMsg) {
|
$scope.checkSignAddressBook = function(key) {
|
||||||
notification.error('Error', errorMsg);
|
if (key) {
|
||||||
} else {
|
$timeout(function() {
|
||||||
notification.success('Success', 'Entry removed successfully');
|
var w = $rootScope.wallet;
|
||||||
}
|
var sign = w.verifySignAddressBook(key);
|
||||||
$rootScope.$digest();
|
$scope.signAddressBook[key] = sign;
|
||||||
}, 500);
|
}, 10);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.toggleAddressBookEntry = function(key) {
|
||||||
|
if (key) {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
w.toggleAddressBookEntry(key);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.copyAddress = function(address) {
|
$scope.copyAddress = function(address) {
|
||||||
|
|
@ -250,11 +250,11 @@ angular.module('copayApp.controllers').controller('SendController',
|
||||||
if (errorMsg) {
|
if (errorMsg) {
|
||||||
notification.error('Error', errorMsg);
|
notification.error('Error', errorMsg);
|
||||||
} else {
|
} else {
|
||||||
|
$scope.checkSignAddressBook(entry.address);
|
||||||
notification.success('Success', 'New entry has been created');
|
notification.success('Success', 'New entry has been created');
|
||||||
}
|
}
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
}, 500);
|
}, 500);
|
||||||
$anchorScroll();
|
|
||||||
// reset fields
|
// reset fields
|
||||||
$scope.newaddress = $scope.newlabel = null;
|
$scope.newaddress = $scope.newlabel = null;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -146,11 +146,6 @@ Wallet.prototype._handleAddressBook = function(senderId, data, isInbound) {
|
||||||
if (!this.addressBook[key]) {
|
if (!this.addressBook[key]) {
|
||||||
this.addressBook[key] = rcv[key];
|
this.addressBook[key] = rcv[key];
|
||||||
hasChange = true;
|
hasChange = true;
|
||||||
} else {
|
|
||||||
if (rcv[key].createdTs > this.addressBook[key].createdTs) {
|
|
||||||
this.addressBook[key] = rcv[key];
|
|
||||||
hasChange = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasChange) {
|
if (hasChange) {
|
||||||
|
|
@ -244,7 +239,6 @@ Wallet.prototype.getMyCopayerIdPriv = function() {
|
||||||
return this.privateKey.getIdPriv(); //copayer idpriv is hex of a private key
|
return this.privateKey.getIdPriv(); //copayer idpriv is hex of a private key
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Wallet.prototype.getSecret = function() {
|
Wallet.prototype.getSecret = function() {
|
||||||
var pubkeybuf = new Buffer(this.getMyCopayerId(), 'hex');
|
var pubkeybuf = new Buffer(this.getMyCopayerId(), 'hex');
|
||||||
var str = Base58Check.encode(pubkeybuf);
|
var str = Base58Check.encode(pubkeybuf);
|
||||||
|
|
@ -838,21 +832,42 @@ Wallet.prototype._checkAddressBook = function(key) {
|
||||||
|
|
||||||
Wallet.prototype.setAddressBook = function(key, label) {
|
Wallet.prototype.setAddressBook = function(key, label) {
|
||||||
this._checkAddressBook(key);
|
this._checkAddressBook(key);
|
||||||
|
var copayerId = this.getMyCopayerId();
|
||||||
|
var ts = Date.now();
|
||||||
|
var payload = {
|
||||||
|
address: key,
|
||||||
|
label: label,
|
||||||
|
copayerId: copayerId,
|
||||||
|
createdTs: ts
|
||||||
|
};
|
||||||
var addressbook = {
|
var addressbook = {
|
||||||
createdTs: Date.now(),
|
hidden: false,
|
||||||
copayerId: this.getMyCopayerId(),
|
createdTs: ts,
|
||||||
label: label
|
copayerId: copayerId,
|
||||||
|
label: label,
|
||||||
|
signature: this.signObject(payload)
|
||||||
};
|
};
|
||||||
this.addressBook[key] = addressbook;
|
this.addressBook[key] = addressbook;
|
||||||
this.sendAddressBook();
|
this.sendAddressBook();
|
||||||
this.store();
|
this.store();
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.deleteAddressBook = function(key) {
|
Wallet.prototype.verifySignAddressBook = function(key) {
|
||||||
if (key) {
|
if (key) {
|
||||||
this.addressBook[key].copayerId = -1;
|
var signature = this.addressBook[key].signature;
|
||||||
this.addressBook[key].createdTs = Date.now();
|
var payload = {
|
||||||
this.sendAddressBook();
|
address: key,
|
||||||
|
label: this.addressBook[key].label,
|
||||||
|
copayerId: this.addressBook[key].copayerId,
|
||||||
|
createdTs: this.addressBook[key].createdTs
|
||||||
|
};
|
||||||
|
return this.verifySignedObject(payload, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Wallet.prototype.toggleAddressBookEntry = function(key) {
|
||||||
|
if (key) {
|
||||||
|
this.addressBook[key].hidden = !this.addressBook[key].hidden;
|
||||||
this.store();
|
this.store();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -867,4 +882,19 @@ Wallet.prototype.offerBackup = function() {
|
||||||
this.store();
|
this.store();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.signObject = function(payload) {
|
||||||
|
var key = new bitcore.Key();
|
||||||
|
key.private = new Buffer(this.getMyCopayerIdPriv(), 'hex');
|
||||||
|
key.regenerateSync();
|
||||||
|
var sign = bitcore.Message.sign(JSON.stringify(payload), key);
|
||||||
|
return sign.toString('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
Wallet.prototype.verifySignedObject = function(payload, signature) {
|
||||||
|
var pubkey = new Buffer(this.getMyCopayerId(), 'hex');
|
||||||
|
var sign = new Buffer(signature, 'hex');
|
||||||
|
var v = bitcore.Message.verifyWithPubKey(pubkey, JSON.stringify(payload), sign);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = require('soop')(Wallet);
|
module.exports = require('soop')(Wallet);
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,13 @@ describe('Wallet model', function() {
|
||||||
label: 'John',
|
label: 'John',
|
||||||
copayerId: '026a55261b7c898fff760ebe14fd22a71892295f3b49e0ca66727bc0a0d7f94d03',
|
copayerId: '026a55261b7c898fff760ebe14fd22a71892295f3b49e0ca66727bc0a0d7f94d03',
|
||||||
createdTs: 1403102115,
|
createdTs: 1403102115,
|
||||||
|
hidden: false
|
||||||
},
|
},
|
||||||
'2MtP8WyiwG7ZdVWM96CVsk2M1N8zyfiVQsY': {
|
'2MtP8WyiwG7ZdVWM96CVsk2M1N8zyfiVQsY': {
|
||||||
label: 'Jennifer',
|
label: 'Jennifer',
|
||||||
copayerId: '032991f836543a492bd6d0bb112552bfc7c5f3b7d5388fcbcbf2fbb893b44770d7',
|
copayerId: '032991f836543a492bd6d0bb112552bfc7c5f3b7d5388fcbcbf2fbb893b44770d7',
|
||||||
createdTs: 1403103115,
|
createdTs: 1403103115,
|
||||||
|
hidden: false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -760,61 +762,113 @@ describe('Wallet model', function() {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
var contacts = [{
|
describe('#AddressBook', function() {
|
||||||
label: 'Charles',
|
var contacts = [{
|
||||||
address: '2N8pJWpXCAxmNLHKVEhz3TtTcYCtHd43xWU ',
|
label: 'Charles',
|
||||||
}, {
|
address: '2N8pJWpXCAxmNLHKVEhz3TtTcYCtHd43xWU ',
|
||||||
label: 'Linda',
|
}, {
|
||||||
address: '2N4Zq92goYGrf5J4F4SZZq7jnPYbCiyRYT2 ',
|
label: 'Linda',
|
||||||
}];
|
address: '2N4Zq92goYGrf5J4F4SZZq7jnPYbCiyRYT2 ',
|
||||||
|
}];
|
||||||
|
|
||||||
it('should create new entry for address book', function() {
|
it('should create new entry for address book', function() {
|
||||||
var w = createW();
|
var w = createW();
|
||||||
contacts.forEach(function(c) {
|
contacts.forEach(function(c) {
|
||||||
w.setAddressBook(c.address, c.label);
|
w.setAddressBook(c.address, c.label);
|
||||||
|
});
|
||||||
|
Object.keys(w.addressBook).length.should.equal(4);
|
||||||
});
|
});
|
||||||
Object.keys(w.addressBook).length.should.equal(4);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail if create a duplicate address', function() {
|
it('should fail if create a duplicate address', function() {
|
||||||
var w = createW();
|
var w = createW();
|
||||||
w.setAddressBook(contacts[0].address, contacts[0].label);
|
|
||||||
(function() {
|
|
||||||
w.setAddressBook(contacts[0].address, contacts[0].label);
|
w.setAddressBook(contacts[0].address, contacts[0].label);
|
||||||
}).should.
|
(function() {
|
||||||
throw();
|
w.setAddressBook(contacts[0].address, contacts[0].label);
|
||||||
});
|
}).should.
|
||||||
|
throw();
|
||||||
it('should delete an entry for address book', function() {
|
});
|
||||||
var w = createW();
|
|
||||||
contacts.forEach(function(c) {
|
it('should show/hide everywhere', function() {
|
||||||
w.setAddressBook(c.address, c.label);
|
var w = createW();
|
||||||
|
var key = '2NFR2kzH9NUdp8vsXTB4wWQtTtzhpKxsyoJ';
|
||||||
|
w.toggleAddressBookEntry(key);
|
||||||
|
w.addressBook[key].hidden.should.equal(true);
|
||||||
|
w.toggleAddressBookEntry(key);
|
||||||
|
w.addressBook[key].hidden.should.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle network addressBook correctly', function() {
|
||||||
|
var w = createW();
|
||||||
|
var data = {
|
||||||
|
walletId: w.id,
|
||||||
|
addressBook: {
|
||||||
|
'msj42CCGruhRsFrGATiUuh25dtxYtnpbTx': {
|
||||||
|
label: 'Faucet',
|
||||||
|
copayerId: '026a55261b7c898fff760ebe14fd22a71892295f3b49e0ca66727bc0a0d7f94d03',
|
||||||
|
createdTs: 1403102115,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type: 'addressbook'
|
||||||
|
};
|
||||||
|
Object.keys(w.addressBook).length.should.equal(2);
|
||||||
|
// New address
|
||||||
|
w._handleAddressBook('senderID', data, true);
|
||||||
|
Object.keys(w.addressBook).length.should.equal(3);
|
||||||
|
// Existent address
|
||||||
|
w._handleAddressBook('senderID', data, true);
|
||||||
|
Object.keys(w.addressBook).length.should.equal(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return signed object', function() {
|
||||||
|
var w = createW();
|
||||||
|
var payload = {
|
||||||
|
address: 'msj42CCGruhRsFrGATiUuh25dtxYtnpbTx',
|
||||||
|
label: 'Faucet',
|
||||||
|
copayerId: '026a55261b7c898fff760ebe14fd22a71892295f3b49e0ca66727bc0a0d7f94d03',
|
||||||
|
createdTs: 1403102115
|
||||||
|
};
|
||||||
|
should.exist(w.signObject(payload));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should verify signed object', function() {
|
||||||
|
var w = createW();
|
||||||
|
var data = {
|
||||||
|
address: 'msj42CCGruhRsFrGATiUuh25dtxYtnpbTx',
|
||||||
|
label: 'Faucet',
|
||||||
|
copayerId: '026a55261b7c898fff760ebe14fd22a71892295f3b49e0ca66727bc0a0d7f94d03',
|
||||||
|
createdTs: 1403102115,
|
||||||
|
};
|
||||||
|
var signature = w.signObject(data);
|
||||||
|
|
||||||
|
w.verifySignedObject(data, signature).should.equal(true);
|
||||||
|
data.label = 'Another';
|
||||||
|
w.verifySignedObject(data, signature).should.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should verify signed addressbook entry', function() {
|
||||||
|
var w = createW();
|
||||||
|
var key = 'msj42CCGruhRsFrGATiUuh25dtxYtnpbTx';
|
||||||
|
var payload = {
|
||||||
|
address: key,
|
||||||
|
label: 'Faucet',
|
||||||
|
copayerId: '026a55261b7c898fff760ebe14fd22a71892295f3b49e0ca66727bc0a0d7f94d03',
|
||||||
|
createdTs: 1403102115,
|
||||||
|
};
|
||||||
|
|
||||||
|
var addressbook = {
|
||||||
|
hidden: false,
|
||||||
|
createdTs: payload.createdTs,
|
||||||
|
copayerId: payload.copayerId,
|
||||||
|
label: payload.label,
|
||||||
|
signature: w.signObject(payload)
|
||||||
|
};
|
||||||
|
w.addressBook[key] = addressbook;
|
||||||
|
|
||||||
|
w.verifySignAddressBook(key).should.equal(true);
|
||||||
|
w.addressBook[key].label = 'Another';
|
||||||
|
w.verifySignAddressBook(key).should.equal(false);
|
||||||
});
|
});
|
||||||
Object.keys(w.addressBook).length.should.equal(4);
|
|
||||||
var key = contacts[0].address;
|
|
||||||
w.deleteAddressBook(key);
|
|
||||||
w.addressBook[key].copayerId.should.equal(-1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('handle network addressBook correctly', function() {
|
|
||||||
var w = createW();
|
|
||||||
var data = {
|
|
||||||
walletId: w.id,
|
|
||||||
addressBook: {
|
|
||||||
'msj42CCGruhRsFrGATiUuh25dtxYtnpbTx': {
|
|
||||||
label: 'Faucet',
|
|
||||||
copayerId: '026a55261b7c898fff760ebe14fd22a71892295f3b49e0ca66727bc0a0d7f94d03',
|
|
||||||
createdTs: 1403102115,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
type: 'addressbook'
|
|
||||||
};
|
|
||||||
Object.keys(w.addressBook).length.should.equal(2);
|
|
||||||
w._handleAddressBook('senderID', data, true);
|
|
||||||
Object.keys(w.addressBook).length.should.equal(3);
|
|
||||||
data.addressBook['msj42CCGruhRsFrGATiUuh25dtxYtnpbTx'].createdTs = 1403102215;
|
|
||||||
w._handleAddressBook('senderID', data, true);
|
|
||||||
Object.keys(w.addressBook).length.should.equal(3);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#getNetworkName', function() {
|
it('#getNetworkName', function() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue