Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support a potentially localStorage backed database #48

Merged
merged 4 commits into from
Oct 22, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,304 changes: 2,162 additions & 2,142 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
}
},
"dependencies": {
"node-localstorage": "^1.3.1",
"web3": "^1.0.0-beta.36"
}
}
2 changes: 1 addition & 1 deletion test/keymanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('Key Manager', function() {
let km2 = new keymanager();
km2.getSecretKey();

let pubkey = km2.publicKey.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '0x');
let pubkey = km2.getPublicKey();

let cyphertext = await km1.encrypt("0x1234abcdef", pubkey);

Expand Down
8 changes: 4 additions & 4 deletions test/mockgateway/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ async function handleRequest (req) {
};
// Arbitrarily chosen.
let manager = new keymanager();
manager.secretKey = new Uint8Array(Buffer.from(
'263357bd55c11524811cccf8c9303e3298dd71abeb1b20f3ea7db07655dba9e9', 'hex'));
manager.publicKey = new Uint8Array(Buffer.from(
'59e35409ffdb0be6a74acc88d5e99e2b50782662fa5bf834b8b9d53bc59c7c4a', 'hex'));
manager._db.setItem('me', JSON.stringify({
'secretKey': '0x263357bd55c11524811cccf8c9303e3298dd71abeb1b20f3ea7db07655dba9e9',
'publicKey': '0x59e35409ffdb0be6a74acc88d5e99e2b50782662fa5bf834b8b9d53bc59c7c4a'
}));

if (req.method == 'confidential_getPublicKey') {
obj.result = {
Expand Down
2 changes: 1 addition & 1 deletion test/mockgateway/responses.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const CONFIDENTIAL_DEPLOY_TX_RECEIPT = {
gasUsed: '0x11577',
logs: [
{
address: '0x5b064f279ab3f4f0b8f7b03395968d29e9ef875c',
address: '0x5e0c135583ad36933ec1b36e8d034b15b747dd2e',
blockHash: '0x3640f09fc74d999ef2487effff4a62371229cfad6cb9502e34d67cf57cc49e2a',
blockNumber: '0x40',
// long term public key for the confidential contract
Expand Down
12 changes: 11 additions & 1 deletion web3c/confidential.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ const Confidential = function (web3) {
method.attachToObject(this);
});

/**
* web3.confidential.Contract behaves like web3.eth.Contract, except that
* because of the object `this` binding, developers don't use `new` when
* instantiating a confidential contract.
* @param {Object} abi
* @param {String} address
* @param {Object} options
* @param {String} options.key The longterm key of the contract.
* @param {bool} options.saveSession false to disable storing keys.
*/
this.Contract = (abi, address, options) => {
let c = new web3.eth.Contract(abi, address, options);
c.setProvider(confidentialShim);
Expand All @@ -28,7 +38,7 @@ const Confidential = function (web3) {
data.topics[0] == '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') {
keymanager.add(data.address, data.data);
} else {
// decoding happens at requet manager.
// decoding happens at request manager.
}
return boundEvent.call(c, data);
};
Expand Down
48 changes: 34 additions & 14 deletions web3c/confidentialprovider.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ const CONFIDENTIAL_PREFIX = '00707269';
* transactiosn to a web3 gateway.
*/
function ConfidentialProvider (keymanager, internalManager) {
let outstanding = [];
return {
send: ConfidentialProvider.send.bind({
keymanager: keymanager,
outstanding: outstanding,
manager: internalManager,
}),
sendBatch: ConfidentialProvider.sendBatch.bind({
Expand All @@ -38,13 +40,13 @@ ConfidentialProvider.send = function confidentialSend (payload, callback) {
let transform = new ConfidentialSendTransform(this.manager.provider, this.keymanager);

if (payload.method === 'eth_sendTransaction') {
transform.ethSendTransaction(payload, callback);
transform.ethSendTransaction(payload, callback, this.outstanding);
} else if (payload.method == 'eth_call') {
transform.ethCall(payload, callback);
} else if (payload.method == 'eth_getLogs') {
transform.ethLogs(payload, callback);
} else if (payload.method == 'eth_getTransactionReceipt') {
transform.ethTransactionReciept(payload, callback);
transform.ethTransactionReciept(payload, callback, this.outstanding);
} else {
const provider = this.manager.provider;
return provider[provider.sendAsync ? 'sendAsync' : 'send'](payload, callback);
Expand All @@ -65,12 +67,18 @@ class ConfidentialSendTransform {
this.keymanager = keymanager;
}

ethSendTransaction(payload, callback) {
ethSendTransaction(payload, callback, outstanding) {
const tx = payload.params[0];
if (!tx.to) {
// deploy transaction doesn't encrypt anything for v0.5
tx.data = this.prependConfidential(tx.data);
return this.provider[this.provider.sendAsync ? 'sendAsync' : 'send'](payload, callback);
return this.provider[this.provider.sendAsync ? 'sendAsync' : 'send'](payload, (err, res) => {
if (!err) {
// track deploy txn receipts to trust them in transaction receipts.
outstanding.push(res.result);
}
callback(err, res);
});
}
this.encryptTx(tx, (err) => {
if (err) {
Expand All @@ -80,13 +88,24 @@ class ConfidentialSendTransform {
});
}

async tryDecryptLogs(logs) {
/**
*
* @param {Array} logs The Eth logs to trial decrypt
* @param {bool} tryAdd Look for longterm contract deploy keys to add to
* to the key manager.
*/
async tryDecryptLogs(logs, tryAdd) {
for (let i = 0; i < logs.length; i++) {
try {
let plain = await this.keymanager.decrypt(logs[i].data);
logs[i].data = plain;
} catch (e) {
// not a log for us.
if (tryAdd && logs[i].logIndex == 0 && logs[i].topics &&
logs[i].topics[0] == '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') {
this.keymanager.add(logs[i].address, logs[i].data);
willscott marked this conversation as resolved.
Show resolved Hide resolved
} else {
try {
let plain = await this.keymanager.decrypt(logs[i].data);
logs[i].data = plain;
} catch (e) {
// not a log for us.
willscott marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
return logs;
Expand All @@ -95,16 +114,17 @@ class ConfidentialSendTransform {
ethLogs(payload, callback) {
return this.provider[this.provider.sendAsync ? 'sendAsync' : 'send'](payload, async (err, res) => {
if (!err) {
res.result = await this.tryDecryptLogs(res.result);
res.result = await this.tryDecryptLogs(res.result, false);
}
callback(err, res);
});
}

ethTransactionReciept(payload, callback) {
ethTransactionReciept(payload, callback, outstanding) {
let tryAdd = outstanding.indexOf(payload.params[0]) > -1;
return this.provider[this.provider.sendAsync ? 'sendAsync' : 'send'](payload, async (err, res) => {
if (!err && res.result && res.result.logs && res.result.logs.lenght) {
res.result.logs = await this.tryDecryptLogs(res.result.logs);
if (!err && res.result && res.result.logs && res.result.logs.length) {
res.result.logs = await this.tryDecryptLogs(res.result.logs, tryAdd);
}
callback(err, res);
});
Expand Down
Loading