From fc60f22403be2542045959b219a4d405c31346a9 Mon Sep 17 00:00:00 2001 From: Will Scott Date: Wed, 17 Oct 2018 17:09:44 -0700 Subject: [PATCH] log hooks --- test/mockgateway/index.js | 8 ++++---- test/web3c.js | 13 ++++++------ web3c/confidential.js | 13 ++++++++++++ web3c/confidentialprovider.js | 37 ++++++++++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/test/mockgateway/index.js b/test/mockgateway/index.js index e25c939..9bfa8b2 100644 --- a/test/mockgateway/index.js +++ b/test/mockgateway/index.js @@ -96,10 +96,10 @@ async function handleRequest (req) { } } else if (req.method == 'eth_getCode') { obj.result = artifact.bytecode; - } else if (req.method == 'eth_getPastLogs') { - if (req.params[0] === responses.CONFIDENTIAL_GET_PAST_LOGS.address) { - obj.result = responses.CONFIDENTIAL_GET_PAST_LOGS; - } + } else if (req.method == 'eth_getLogs') { + if (req.params[0].address === responses.CONFIDENTIAL_GET_PAST_LOGS[0].address) { + obj.result = responses.CONFIDENTIAL_GET_PAST_LOGS; + } } return obj; diff --git a/test/web3c.js b/test/web3c.js index 2660bbf..708a9f4 100644 --- a/test/web3c.js +++ b/test/web3c.js @@ -77,7 +77,8 @@ describe('Web3', () => { }).timeout(5000); it ('should get confidential getPastLogs logs', async() => { - let counterContract = (new web3c(gw)).confidential.Contract(artifact.abi); + let client = new web3c(gw); + let counterContract = client.confidential.Contract(artifact.abi); let instance; try { instance = await counterContract.deploy({ @@ -95,10 +96,10 @@ describe('Web3', () => { gasPrice: '0x3b9aca00', gasLimit: '0x100000', }); - // todo: this should use our confidential getPastLogs implementation - let logs = await (new web3c(gw)).eth.getPastLogs({ - address: instance._address - }); - // todo: assert the logs emitted the number 1 + + let logs = await instance.getPastEvents(); + assert.equal(logs.length, 1); + // since the client will use a different ephemeral key each time, it + // won't be able to decrypt previous logs. }).timeout(5000); }); diff --git a/web3c/confidential.js b/web3c/confidential.js index e13105a..b1503af 100644 --- a/web3c/confidential.js +++ b/web3c/confidential.js @@ -21,11 +21,24 @@ const Confidential = function (web3) { let c = new web3.eth.Contract(abi, address, options); c.setProvider(confidentialShim); + let keymanager = this.keyManager; + let boundEvent = c._decodeEventABI; + c._decodeEventABI = function (data) { + if (data.logIndex == 0 && data.topics && + data.topics[0] == '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') { + keymanager.add(data.address, data.data); + } else { + // decoding happens at requet manager. + } + return boundEvent.call(c, data); + }; + // hook to ensure deployed contracts retain the confidential provider. let boundClone = c.clone.bind(c); c.clone = () => { let cloned = boundClone(); cloned.setProvider(confidentialShim); + cloned._decodeEventABI = c._decodeEventABI; return cloned; }; diff --git a/web3c/confidentialprovider.js b/web3c/confidentialprovider.js index beb49a8..85861c0 100644 --- a/web3c/confidentialprovider.js +++ b/web3c/confidentialprovider.js @@ -41,6 +41,10 @@ ConfidentialProvider.send = function confidentialSend (payload, callback) { transform.ethSendTransaction(payload, callback); } 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); } else { const provider = this.manager.provider; return provider[provider.sendAsync ? 'sendAsync' : 'send'](payload, callback); @@ -76,7 +80,38 @@ class ConfidentialSendTransform { }); } - // TODO: get call data signed by the user wallet + async tryDecryptLogs(logs) { + 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. + } + } + return logs; + } + + ethLogs(payload, callback) { + return this.provider[this.provider.sendAsync ? 'sendAsync' : 'send'](payload, async (err, res) => { + if (!err) { + res.result = await this.tryDecryptLogs(res.result); + } + callback(err, res); + }); + } + + ethTransactionReciept(payload, callback) { + 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); + } + callback(err, res); + }); + } + + //TODO: eth_getFilterChanges, eth_getFilterLogs + ethCall(payload, callback) { const tx = payload.params[0]; this.encryptTx(tx, (err) => {