Merge pull request #775 from ethereum/addremixlibAPI

Refactor encoding transaction data
pull/7/head
yann300 7 years ago committed by GitHub
commit 12e2a974cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 149
      remix-lib/src/execution/txFormat.js
  2. 91
      remix-lib/test/txFormat.js

@ -32,18 +32,143 @@ module.exports = {
},
/**
* build the transaction data
*
* @param {String} contractName
* @param {Object} contract - abi definition of the current contract.
* @param {Object} contracts - map of all compiled contracts.
* @param {Bool} isConstructor - isConstructor.
* @param {Object} funAbi - abi definition of the function to call. null if building data for the ctor.
* @param {Object} params - input paramater of the function to call
* @param {Function} callback - callback
* @param {Function} callbackStep - callbackStep
* @param {Function} callbackDeployLibrary - callbackDeployLibrary
*/
* encode function / constructor parameters
*
* @param {Object} params - input paramater of the function to call
* @param {Object} funAbi - abi definition of the function to call. null if building data for the ctor.
* @param {Function} callback - callback
*/
encodeParams: function (params, funAbi, callback) {
var data = ''
var dataHex = ''
var funArgs
if (params.indexOf('raw:0x') === 0) {
// in that case we consider that the input is already encoded and *does not* contain the method signature
dataHex = params.replace('raw:0x', '')
data = Buffer.from(dataHex, 'hex')
} else {
try {
params = params.replace(/(^|,\s+|,)(\d+)(\s+,|,|$)/g, '$1"$2"$3') // replace non quoted number by quoted number
params = params.replace(/(^|,\s+|,)(0[xX][0-9a-fA-F]+)(\s+,|,|$)/g, '$1"$2"$3') // replace non quoted hex string by quoted hex string
funArgs = JSON.parse('[' + params + ']')
} catch (e) {
callback('Error encoding arguments: ' + e)
return
}
if (funArgs.length > 0) {
try {
data = helper.encodeParams(funAbi, funArgs)
dataHex = data.toString('hex')
} catch (e) {
callback('Error encoding arguments: ' + e)
return
}
}
if (data.slice(0, 9) === 'undefined') {
dataHex = data.slice(9)
}
if (data.slice(0, 2) === '0x') {
dataHex = data.slice(2)
}
}
callback(null, { data: data, dataHex: dataHex, funArgs: funArgs })
},
/**
* encode function call (function id + encoded parameters)
*
* @param {Object} params - input paramater of the function to call
* @param {Object} funAbi - abi definition of the function to call. null if building data for the ctor.
* @param {Function} callback - callback
*/
encodeFunctionCall: function (params, funAbi, callback) {
this.encodeParams(params, funAbi, (error, encodedParam) => {
if (error) return callback(error)
callback(null, { dataHex: helper.encodeFunctionId(funAbi) + encodedParam.dataHex, funAbi, funArgs: encodedParam.funArgs })
})
},
/**
* encode constructor creation and link with provided libraries if needed
*
* @param {Object} contract - input paramater of the function to call
* @param {Object} params - input paramater of the function to call
* @param {Object} funAbi - abi definition of the function to call. null if building data for the ctor.
* @param {Object} linkLibraries - contains {linkReferences} object which list all the addresses to be linked
* @param {Object} linkReferences - given by the compiler, contains the proper linkReferences
* @param {Function} callback - callback
*/
encodeConstructorCallAndLinkLibraries: function (contract, params, funAbi, linkLibraries, linkReferences, callback) {
this.encodeParams(params, funAbi, (error, encodedParam) => {
if (error) return callback(error)
var bytecodeToDeploy = contract.evm.bytecode.object
if (bytecodeToDeploy.indexOf('_') >= 0) {
if (linkLibraries && linkReferences) {
for (var libFile in linkLibraries) {
for (var lib in linkLibraries[libFile]) {
var address = linkLibraries[libFile][lib]
if (!ethJSUtil.isValidAddress(address)) return callback(address + ' is not a valid address. Please check the provided address is valid.')
bytecodeToDeploy = this.linkLibraryStandardFromlinkReferences(lib, address.replace('0x', ''), bytecodeToDeploy, linkReferences)
}
}
}
}
if (bytecodeToDeploy.indexOf('_') >= 0) {
return callback('Failed to link some libraries')
}
return callback(null, { dataHex: bytecodeToDeploy + encodedParam.dataHex, funAbi, funArgs: encodedParam.funArgs, contractBytecode: contract.evm.bytecode.object })
})
},
/**
* encode constructor creation and deploy librairies if needed
*
* @param {String} contractName - current contract name
* @param {Object} contract - input paramater of the function to call
* @param {Object} contracts - map of all compiled contracts.
* @param {Object} params - input paramater of the function to call
* @param {Object} funAbi - abi definition of the function to call. null if building data for the ctor.
* @param {Function} callback - callback
* @param {Function} callbackStep - callbackStep
* @param {Function} callbackDeployLibrary - callbackDeployLibrary
* @param {Function} callback - callback
*/
encodeConstructorCallAndDeployLibraries: function (contractName, contract, contracts, params, funAbi, callback, callbackStep, callbackDeployLibrary) {
this.encodeParams(params, funAbi, (error, encodedParam) => {
if (error) return callback(error)
var dataHex = ''
var contractBytecode = contract.evm.bytecode.object
var bytecodeToDeploy = contract.evm.bytecode.object
if (bytecodeToDeploy.indexOf('_') >= 0) {
this.linkBytecode(contract, contracts, (err, bytecode) => {
if (err) {
callback('Error deploying required libraries: ' + err)
} else {
bytecodeToDeploy = bytecode + dataHex
return callback(null, {dataHex: bytecodeToDeploy, funAbi, funArgs: encodedParam.funArgs, contractBytecode, contractName: contractName})
}
}, callbackStep, callbackDeployLibrary)
return
} else {
dataHex = bytecodeToDeploy + encodedParam.dataHex
}
callback(null, {dataHex: bytecodeToDeploy, funAbi, funArgs: encodedParam.funArgs, contractBytecode, contractName: contractName})
})
},
/**
* (DEPRECATED) build the transaction data
*
* @param {String} contractName
* @param {Object} contract - abi definition of the current contract.
* @param {Object} contracts - map of all compiled contracts.
* @param {Bool} isConstructor - isConstructor.
* @param {Object} funAbi - abi definition of the function to call. null if building data for the ctor.
* @param {Object} params - input paramater of the function to call
* @param {Function} callback - callback
* @param {Function} callbackStep - callbackStep
* @param {Function} callbackDeployLibrary - callbackDeployLibrary
*/
buildData: function (contractName, contract, contracts, isConstructor, funAbi, params, callback, callbackStep, callbackDeployLibrary) {
var funArgs = ''
var data = ''

@ -5,6 +5,8 @@ var compiler = require('solc')
var compilerInput = require('../src/helpers/compilerHelper').compilerInput
var executionContext = require('../src/execution/execution-context')
/* tape *********************************************************** */
var context
tape('ContractParameters - (TxFormat.buildData) - format input parameters', function (t) {
var output = compiler.compileStandardWrapper(compilerInput(uintContract))
@ -29,11 +31,12 @@ function testWithInput (st, params, expected) {
}, () => {}, () => {})
}
/* tape *********************************************************** */
tape('ContractParameters - (TxFormat.buildData) - link Libraries', function (t) {
executionContext.setContext('vm')
var output = compiler.compileStandardWrapper(compilerInput(deploySimpleLib))
output = JSON.parse(output)
var contract = output.contracts['test.sol']['testContractLinkLibrary']
var compileData = compiler.compileStandardWrapper(compilerInput(deploySimpleLib))
var fakeDeployedContracts = {
lib1: '0xf7a10e525d4b168f45f74db1b61f63d3e7619e11',
lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2: '0xf7a10e525d4b168f45f74db1b61f63d3e7619e33',
@ -46,11 +49,22 @@ tape('ContractParameters - (TxFormat.buildData) - link Libraries', function (t)
}
})
} // fake
context = { output, contract }
t.test('(TxFormat.buildData and link library (standard way))', function (st) {
st.plan(6)
var output = JSON.parse(compileData)
var contract = output.contracts['test.sol']['testContractLinkLibrary']
context = { output, contract }
testLinkLibrary(st, fakeDeployedContracts, callbackDeployLibraries)
})
t.test('(TxFormat.encodeConstructorCallAndLinkLibraries and link library (standard way))', function (st) {
st.plan(12)
var output = JSON.parse(compileData)
var contract = output.contracts['test.sol']['testContractLinkLibrary']
context = { output, contract }
testLinkLibrary2(st, callbackDeployLibraries)
})
})
function testLinkLibrary (st, fakeDeployedContracts, callbackDeployLibraries) {
@ -73,6 +87,68 @@ function testLinkLibrary (st, fakeDeployedContracts, callbackDeployLibraries) {
}, callbackDeployLibraries)
}
function testLinkLibrary2 (st, callbackDeployLibraries) {
var librariesReference = {
'test.sol': {
'lib1': '0xf7a10e525d4b168f45f74db1b61f63d3e7619e11',
'lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2': '0xf7a10e525d4b168f45f74db1b61f63d3e7619e33'
}
}
var data = '608060405234801561001057600080fd5b5061026b806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c14610046575b600080fd5b34801561005257600080fd5b5061005b61005d565b005b73f7a10e525d4b168f45f74db1b61f63d3e7619e116344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b1580156100bd57600080fd5b505af41580156100d1573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e336344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801561013557600080fd5b505af4158015610149573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e336344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b1580156101ad57600080fd5b505af41580156101c1573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e116344733ae16040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801561022557600080fd5b505af4158015610239573d6000803e3d6000fd5b505050505600a165627a7a7230582090b0bbf59fc9b1f13331039529d287ce9a9e712ce22dc71025510293d18104bc0029'
var deployMsg = ['creation of library test.sol:lib1 pending...',
'creation of library test.sol:lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 pending...']
txFormat.encodeConstructorCallAndLinkLibraries(context.contract, '', context.contract.abi[0], librariesReference, context.contract.evm.bytecode.linkReferences, (error, result) => {
console.log(error, result)
st.equal(data, result.dataHex)
var linkedbyteCode = result.dataHex
var libReference = context.contract.evm.bytecode.linkReferences['test.sol']['lib1']
st.equal(linkedbyteCode.substr(2 * libReference[0].start, 40), librariesReference['test.sol']['lib1'].replace('0x', ''))
st.equal(linkedbyteCode.substr(2 * libReference[1].start, 40), librariesReference['test.sol']['lib1'].replace('0x', ''))
libReference = context.contract.evm.bytecode.linkReferences['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2']
st.equal(linkedbyteCode.substr(2 * libReference[0].start, 40), librariesReference['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'].replace('0x', ''))
st.equal(linkedbyteCode.substr(2 * libReference[1].start, 40), librariesReference['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'].replace('0x', ''))
})
txFormat.encodeConstructorCallAndDeployLibraries('testContractLinkLibrary', context.contract, context.output.contracts, '', context.contract.abi[0], (error, result) => {
console.log(error, result)
st.equal(data, result.dataHex)
var linkedbyteCode = result.dataHex
var libReference = context.contract.evm.bytecode.linkReferences['test.sol']['lib1']
st.equal(linkedbyteCode.substr(2 * libReference[0].start, 40), librariesReference['test.sol']['lib1'].replace('0x', ''))
st.equal(linkedbyteCode.substr(2 * libReference[1].start, 40), librariesReference['test.sol']['lib1'].replace('0x', ''))
libReference = context.contract.evm.bytecode.linkReferences['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2']
st.equal(linkedbyteCode.substr(2 * libReference[0].start, 40), librariesReference['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'].replace('0x', ''))
st.equal(linkedbyteCode.substr(2 * libReference[1].start, 40), librariesReference['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'].replace('0x', ''))
}, (msg) => {
st.equal(msg, deployMsg[0])
deployMsg.shift()
}, callbackDeployLibraries)
}
/* tape *********************************************************** */
tape('EncodeParameter', function (t) {
t.test('(TxFormat.encodeFunctionCall)', function (st) {
st.plan(1)
encodeFunctionCallTest(st)
})
})
function encodeFunctionCallTest (st) {
var output = compiler.compileStandardWrapper(compilerInput(encodeFunctionCall))
output = JSON.parse(output)
var contract = output.contracts['test.sol']['testContractLinkLibrary']
txFormat.encodeFunctionCall('123, "test string"', contract.abi[0], (error, encoded) => {
console.log(error)
st.equal(encoded.dataHex, '0x805da4ad000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000b7465737420737472696e67000000000000000000000000000000000000000000')
})
}
/* *********************************************************** */
var uintContract = `contract uintContractTest {
uint _tp;
address _ap;
@ -103,3 +179,10 @@ contract testContractLinkLibrary {
}
}`
var encodeFunctionCall = `pragma solidity ^0.4.4;
contract testContractLinkLibrary {
function get (uint _p, string _o) {
}
}`

Loading…
Cancel
Save