Commit 582f906f authored by LianaHus's avatar LianaHus

browser-test for signing a msg using ethutil

parent 30600aa4
......@@ -171,6 +171,7 @@
"make-mock-compiler": "node ci/makeMockCompiler.js",
"minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false",
"nightwatch_local": "nightwatch --config nightwatch.js --env local",
"nightwatch_local_general": "nightwatch ./test-browser/tests/generalTests.js --config nightwatch.js --env local ",
"nightwatch_local_debugger": "nightwatch --config nightwatch_debugger.js --env local",
"nightwatch_remote_chrome": "nightwatch --config nightwatch.js --env chrome",
"nightwatch_remote_firefox": "nightwatch --config nightwatch.js --env default",
......
......@@ -73,6 +73,10 @@ class Settings {
return (!isVM && !isInjected)
}
isInjectedWeb3 () {
return executionContext.getProvider() === 'injected'
}
signMessage (message, account, passphrase, cb) {
var isVM = executionContext.isVM()
var isInjected = executionContext.getProvider() === 'injected'
......@@ -93,6 +97,7 @@ class Settings {
const hashedMsg = executionContext.web3().sha3(message)
try {
executionContext.web3().eth.sign(account, hashedMsg, (error, signedData) => {
if (!error) alert("Please check your provider")
cb(error, hashedMsg, signedData)
})
} catch (e) {
......
......@@ -58,11 +58,11 @@ class SettingsUI {
<select id="selectExEnvOptions" onchange=${() => { this.updateNetwork() }} class="form-control ${css.select}">
<option id="vm-mode"
title="Execution environment does not connect to any node, everything is local and in memory only."
value="vm" checked name="executionContext"> JavaScript VM
value="vm" name="executionContext"> JavaScript VM
</option>
<option id="injected-mode"
title="Execution environment has been provided by Metamask or similar provider."
value="injected" checked name="executionContext"> Injected Web3
value="injected" name="executionContext"> Injected Web3
</option>
<option id="web3-mode"
title="Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse!
......@@ -92,7 +92,7 @@ class SettingsUI {
<div class=${css.account}>
<select name="txorigin" class="form-control ${css.select}" id="txorigin"></select>
${copyToClipboard(() => document.querySelector('#runTabView #txorigin').value)}
<i class="fas fa-edit ${css.icon}" aria-hiden="true" onclick=${this.signMessage.bind(this)} title="Sign a message using this account key"></i>
<i id="remixRunSignMsg" class="fas fa-edit ${css.icon}" aria-hiden="true" onclick=${this.signMessage.bind(this)} title="Sign a message using this account key"></i>
</div>
</div>
`
......@@ -223,6 +223,8 @@ class SettingsUI {
var signMessageDialog = { 'title': 'Sign a message', 'text': 'Enter a message to sign', 'inputvalue': 'Message to sign' }
var $txOrigin = this.el.querySelector('#txorigin')
if (!$txOrigin.selectedOptions[0] && this.settings.isInjectedWeb3())
return addTooltip(`Account list is empty, please login to your wallet to load it`)
var account = $txOrigin.selectedOptions[0].value
var promptCb = (passphrase) => {
......@@ -231,13 +233,26 @@ class SettingsUI {
if (err) {
return addTooltip(err)
}
modalDialogCustom.alert(yo`<div><b>hash:</b>${msgHash}<br><b>signature:</b>${signedData}</div>`)
modalDialogCustom.alert(yo`
<div>
<b>hash:</b><br>
<span id="remixRunSignMsgHash">${msgHash}</span>
<br><b>signature:</b><br>
<span id="remixRunSignMsgSignature">${signedData}</span>
</div>
`)
})
}, false)
}
if (this.settings.isWeb3Provider()) {
return modalDialogCustom.promptPassphrase('Passphrase to sign a message', 'Enter your passphrase for this account to sign the message', '', promptCb, false)
return modalDialogCustom.promptPassphrase(
'Passphrase to sign a message',
'Enter your passphrase for this account to sign the message',
'',
promptCb,
false
)
}
promptCb()
})
......
......@@ -67,7 +67,7 @@ module.exports = class SettingsTab extends BaseApi {
var gistAddToken = yo`<input class="${css.savegisttoken} btn btn-sm btn-primary" id="savegisttoken" onclick=${() => { this.config.set('settings/gist-access-token', gistAccessToken.value); tooltip('Access token saved') }} value="Save" type="button">`
var gistRemoveToken = yo`<input class="btn btn-sm btn-primary" id="removegisttoken" onclick=${() => { gistAccessToken.value = ''; this.config.set('settings/gist-access-token', ''); tooltip('Access token removed') }} value="Remove" type="button">`
this._view.gistToken = yo`<div class="${css.checkboxText}">${gistAccessToken}${copyToClipboard(() => this.config.get('settings/gist-access-token'))}${gistAddToken}${gistRemoveToken}</div>`
this._view.optionVM = yo`<input onchange=${onchangeOption} class="align-middle form-check-input" id="alwaysUseVM" type="checkbox">`
this._view.optionVM = yo`<input onchange=${onchangeOption} checked class="align-middle form-check-input" id="alwaysUseVM" type="checkbox">`
if (this.config.get('settings/always-use-vm')) this._view.optionVM.setAttribute('checked', '')
this._view.personal = yo`<input onchange=${onchangePersonal} id="personal" type="checkbox" class="align-middle form-check-input">`
if (this.config.get('settings/personal-mode')) this._view.personal.setAttribute('checked', '')
......
......@@ -25,7 +25,8 @@ module.exports = {
removeFile,
getAddressAtPosition,
clickLaunchIcon,
scrollInto
scrollInto,
signMsg
}
function clickLaunchIcon (icon) {
......@@ -168,6 +169,30 @@ function scrollInto (target) {
})
}
function signMsg (browser, msg, cb) {
let hash, signature
browser
.click('i[id="remixRunSignMsg"]')
.setValue('textarea[id="prompt_text"]', msg, ()=>{
browser.modalFooterOKClick().perform(
(client, done)=>{
browser.getText('span[id="remixRunSignMsgHash"]', (v)=>{ hash = v; done()})
}
)
.perform(
(client, done)=>{
browser.getText('span[id="remixRunSignMsgSignature"]', (v)=>{ signature = v; done()})
}
)
.modalFooterOKClick()
.perform(
()=>{
cb(hash, signature)
}
)
})
}
function _scrollInto (browser, target, cb) {
browser.execute(function (target) {
document.querySelector(target).scrollIntoView()
......
......@@ -21,6 +21,8 @@ function runTests (browser) {
browser.setEditorValue = contractHelper.setEditorValue
browser.getEditorValue = contractHelper.getEditorValue
browser.clickLaunchIcon = contractHelper.clickLaunchIcon
browser.modalFooterOKClick = contractHelper.modalFooterOKClick
browser.clickFunction = contractHelper.clickFunction
browser.scrollInto = contractHelper.scrollInto
browser
.waitForElementVisible('#icon-panel', 10000)
......@@ -34,7 +36,8 @@ function runTests (browser) {
testFailedImport, /* testGitHubImport */
addDeployLibTestFile,
testAutoDeployLib,
testManualDeployLib
testManualDeployLib,
testSignature
],
function () {
browser.end()
......@@ -158,6 +161,36 @@ function checkDeployShouldSucceed (browser, address, callback) {
})
}
function testSignature (browser, callback) {
let hash, signature
browser.clickLaunchIcon("run").pause(4000).perform((client, done)=>{
contractHelper.signMsg(browser, "test message", (h, s)=>{
hash = h
signature = s
contractHelper.addFile(browser, "signMassage.sol", sources[6]["browser/signMassage.sol"], ()=>{
contractHelper.switchFile(browser, 'browser/signMassage.sol', () => {
contractHelper.selectContract(browser, 'ECVerify', () => { // deploy lib
contractHelper.createContract(browser, '', () => {
browser.waitForElementPresent('.instance:nth-of-type(4)')
.click('.instance:nth-of-type(4) > div > button')
.clickFunction("ecrecovery - call", {types: "bytes32 hash, bytes sig", values: `"${hash.value}","${signature.value}"`}).perform(
()=>{
contractHelper.verifyCallReturnValue(
browser,
"0x08970fed061e7747cd9a38d680a601510cb659fb",
['0: address: 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c'],
()=>{callback(null, browser)}
)
}
)
})
})
})
})
})
})
}
/*
function testGitHubImport (browser, callback) {
contractHelper.addFile(browser, 'Untitled4.sol', sources[3]['browser/Untitled4.sol'], () => {
......@@ -320,6 +353,46 @@ var sources = [
function get () public view returns (uint) {
return lib.getInt();
}
}`}
}`}
},
{
'browser/signMassage.sol': {content: `
contract SignMassageTest {
function testRecovery(bytes32 h, uint8 v, bytes32 r, bytes32 s) public pure returns (address) {
return ecrecover(h, v, r, s);
}
}
library ECVerify {
function ecrecovery(bytes32 hash, bytes memory sig) public pure returns (address) {
bytes32 r;
bytes32 s;
uint8 v;
if (sig.length != 65) {
return address(0);
}
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := and(mload(add(sig, 65)), 255)
}
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return address(0);
}
return ecrecover(hash, v, r, s);
}
function ecverify(bytes32 hash, bytes memory sig, address signer) public pure returns (bool) {
return signer == ecrecovery(hash, sig);
}
}`}
}
]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment