diff options
author | Amir Bandeali <abandeali1@gmail.com> | 2019-01-24 02:49:10 +0800 |
---|---|---|
committer | Amir Bandeali <abandeali1@gmail.com> | 2019-01-24 02:49:10 +0800 |
commit | 09cb3b7d5060bc8821cdbcab9639bb0a3b27d651 (patch) | |
tree | 63821d6126f9e8ca9ea866fa3ba36169d1b0f0e2 | |
parent | 8566bb551b2399f5b966b2ac81c89ba96f272aaf (diff) | |
parent | ef928aff31f09b368307548bd5a512b4212a0c95 (diff) | |
download | dexon-0x-contracts-09cb3b7d5060bc8821cdbcab9639bb0a3b27d651.tar dexon-0x-contracts-09cb3b7d5060bc8821cdbcab9639bb0a3b27d651.tar.gz dexon-0x-contracts-09cb3b7d5060bc8821cdbcab9639bb0a3b27d651.tar.bz2 dexon-0x-contracts-09cb3b7d5060bc8821cdbcab9639bb0a3b27d651.tar.lz dexon-0x-contracts-09cb3b7d5060bc8821cdbcab9639bb0a3b27d651.tar.xz dexon-0x-contracts-09cb3b7d5060bc8821cdbcab9639bb0a3b27d651.tar.zst dexon-0x-contracts-09cb3b7d5060bc8821cdbcab9639bb0a3b27d651.zip |
Merge branch 'development' into feat/contracts/split-packages
-rw-r--r-- | contracts/utils/CHANGELOG.json | 9 | ||||
-rw-r--r-- | packages/devnet/docker-compose.yml | 8 | ||||
-rwxr-xr-x | packages/devnet/run.sh | 1 | ||||
-rw-r--r-- | packages/sol-coverage/src/coverage_subprovider.ts | 4 | ||||
-rw-r--r-- | packages/sol-profiler/CHANGELOG.json | 9 | ||||
-rw-r--r-- | packages/sol-tracing-utils/CHANGELOG.json | 21 | ||||
-rw-r--r-- | packages/sol-tracing-utils/package.json | 1 | ||||
-rw-r--r-- | packages/sol-tracing-utils/src/artifact_adapters/sol_compiler_artifact_adapter.ts | 19 | ||||
-rw-r--r-- | packages/sol-tracing-utils/src/collect_coverage_entries.ts | 14 | ||||
-rw-r--r-- | packages/sol-tracing-utils/src/utils.ts | 34 | ||||
-rw-r--r-- | packages/sol-tracing-utils/test/collect_coverage_entries_test.ts | 3 | ||||
-rw-r--r-- | yarn.lock | 4 |
12 files changed, 98 insertions, 29 deletions
diff --git a/contracts/utils/CHANGELOG.json b/contracts/utils/CHANGELOG.json index e33c3c7fc..94434b803 100644 --- a/contracts/utils/CHANGELOG.json +++ b/contracts/utils/CHANGELOG.json @@ -17,6 +17,15 @@ ] }, { + "version": "2.0.1", + "changes": [ + { + "note": "Fix imports in `TestConstants` and `TestLibBytes` to be relative. This way they show up correctly in coverage reports", + "pr": 1535 + } + ] + }, + { "version": "2.0.0", "changes": [ { diff --git a/packages/devnet/docker-compose.yml b/packages/devnet/docker-compose.yml new file mode 100644 index 000000000..1c1e7ca75 --- /dev/null +++ b/packages/devnet/docker-compose.yml @@ -0,0 +1,8 @@ +version: '3' +services: + devnet: + image: 0x-devnet:latest + build: + context: . + ports: + - 8501:8501 diff --git a/packages/devnet/run.sh b/packages/devnet/run.sh index dea243396..6000813f0 100755 --- a/packages/devnet/run.sh +++ b/packages/devnet/run.sh @@ -15,6 +15,7 @@ mkdir -p /var/log --rpc \ --rpcaddr '0.0.0.0' \ --rpcport 8501 \ + --rpcvhosts '*' \ --rpcapi 'personal,db,eth,net,web3,txpool,miner,debug' \ --networkid 50 \ --gasprice '2000000000' \ diff --git a/packages/sol-coverage/src/coverage_subprovider.ts b/packages/sol-coverage/src/coverage_subprovider.ts index d03963ed6..2d92b25ca 100644 --- a/packages/sol-coverage/src/coverage_subprovider.ts +++ b/packages/sol-coverage/src/coverage_subprovider.ts @@ -50,6 +50,8 @@ export class CoverageSubprovider extends TraceInfoSubprovider { } } +const IGNORE_REGEXP = /\/\*\s*solcov\s+ignore\s+next\s*\*\/\s*/gm; + /** * Computed partial coverage for a single file & subtrace. * @param contractData Contract metadata (source, srcMap, bytecode) @@ -65,7 +67,7 @@ export const coverageHandler: SingleFileSubtraceHandler = ( fileIndex: number, ): Coverage => { const absoluteFileName = contractData.sources[fileIndex]; - const coverageEntriesDescription = collectCoverageEntries(contractData.sourceCodes[fileIndex]); + const coverageEntriesDescription = collectCoverageEntries(contractData.sourceCodes[fileIndex], IGNORE_REGEXP); // if the source wasn't provided for the fileIndex, we can't cover the file if (_.isUndefined(coverageEntriesDescription)) { diff --git a/packages/sol-profiler/CHANGELOG.json b/packages/sol-profiler/CHANGELOG.json index 550ca2feb..fc928b516 100644 --- a/packages/sol-profiler/CHANGELOG.json +++ b/packages/sol-profiler/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "2.0.1", + "changes": [ + { + "note": "Fix a bug when some parts of the profiling report were missing because of the coverage ignore lines", + "pr": 1535 + } + ] + }, + { "version": "2.0.0", "changes": [ { diff --git a/packages/sol-tracing-utils/CHANGELOG.json b/packages/sol-tracing-utils/CHANGELOG.json index ef96dc69b..16a12ca63 100644 --- a/packages/sol-tracing-utils/CHANGELOG.json +++ b/packages/sol-tracing-utils/CHANGELOG.json @@ -1,5 +1,26 @@ [ { + "version": "6.0.0", + "changes": [ + { + "note": "`SolCompilerArtifactAdapter` now uses `SolResolver` under the hood which allows to resolve `NPM` dependencies properly", + "pr": 1535 + }, + { + "note": "Cache the `utils.getContractDataIfExists` leading to faster execution", + "pr": 1535 + }, + { + "note": "`SolCompilerArtifactAdapter` now doesn't return the `ContractData` for interfaces", + "pr": 1535 + }, + { + "note": "Print resasonable error message on bytecode collision", + "pr": 1535 + } + ] + }, + { "version": "5.0.0", "changes": [ { diff --git a/packages/sol-tracing-utils/package.json b/packages/sol-tracing-utils/package.json index cabb752d2..4b0fff222 100644 --- a/packages/sol-tracing-utils/package.json +++ b/packages/sol-tracing-utils/package.json @@ -44,6 +44,7 @@ "dependencies": { "@0x/dev-utils": "^1.0.24", "@0x/sol-compiler": "^2.0.2", + "@0x/sol-resolver": "^1.2.3", "@0x/subproviders": "^2.1.11", "@0x/typescript-typings": "^3.0.8", "@0x/utils": "^3.0.1", diff --git a/packages/sol-tracing-utils/src/artifact_adapters/sol_compiler_artifact_adapter.ts b/packages/sol-tracing-utils/src/artifact_adapters/sol_compiler_artifact_adapter.ts index d52587f2c..bfd3a504a 100644 --- a/packages/sol-tracing-utils/src/artifact_adapters/sol_compiler_artifact_adapter.ts +++ b/packages/sol-tracing-utils/src/artifact_adapters/sol_compiler_artifact_adapter.ts @@ -1,3 +1,4 @@ +import { FallthroughResolver, FSResolver, NPMResolver, RelativeFSResolver, URLResolver } from '@0x/sol-resolver'; import { logUtils } from '@0x/utils'; import { CompilerOptions, ContractArtifact } from 'ethereum-types'; import * as fs from 'fs'; @@ -14,6 +15,7 @@ const CONFIG_FILE = 'compiler.json'; export class SolCompilerArtifactAdapter extends AbstractArtifactAdapter { private readonly _artifactsPath: string; private readonly _sourcesPath: string; + private readonly _resolver: FallthroughResolver; /** * Instantiates a SolCompilerArtifactAdapter * @param artifactsPath Path to your artifacts directory @@ -32,6 +34,12 @@ export class SolCompilerArtifactAdapter extends AbstractArtifactAdapter { throw new Error(`contractsDir not found in ${CONFIG_FILE}`); } this._sourcesPath = (sourcesPath || config.contractsDir) as string; + this._resolver = new FallthroughResolver(); + this._resolver.appendResolver(new URLResolver()); + const packagePath = path.resolve(''); + this._resolver.appendResolver(new NPMResolver(packagePath)); + this._resolver.appendResolver(new RelativeFSResolver(this._sourcesPath)); + this._resolver.appendResolver(new FSResolver()); } public async collectContractsDataAsync(): Promise<ContractData[]> { const artifactsGlob = `${this._artifactsPath}/**/*.json`; @@ -46,10 +54,9 @@ export class SolCompilerArtifactAdapter extends AbstractArtifactAdapter { const sources: Sources = {}; const sourceCodes: SourceCodes = {}; _.map(artifact.sources, (value: { id: number }, relativeFilePath: string) => { - const filePath = path.resolve(this._sourcesPath, relativeFilePath); - const fileContent = fs.readFileSync(filePath).toString(); - sources[value.id] = filePath; - sourceCodes[value.id] = fileContent; + const source = this._resolver.resolve(relativeFilePath); + sources[value.id] = source.absolutePath; + sourceCodes[value.id] = source.source; }); const contractData = { sourceCodes, @@ -59,6 +66,10 @@ export class SolCompilerArtifactAdapter extends AbstractArtifactAdapter { runtimeBytecode: artifact.compilerOutput.evm.deployedBytecode.object, sourceMapRuntime: artifact.compilerOutput.evm.deployedBytecode.sourceMap, }; + const isInterfaceContract = contractData.bytecode === '0x' && contractData.runtimeBytecode === '0x'; + if (isInterfaceContract) { + continue; + } contractsData.push(contractData); } return contractsData; diff --git a/packages/sol-tracing-utils/src/collect_coverage_entries.ts b/packages/sol-tracing-utils/src/collect_coverage_entries.ts index 9e3591d74..d5045b106 100644 --- a/packages/sol-tracing-utils/src/collect_coverage_entries.ts +++ b/packages/sol-tracing-utils/src/collect_coverage_entries.ts @@ -5,18 +5,18 @@ import * as parser from 'solidity-parser-antlr'; import { ASTVisitor, CoverageEntriesDescription } from './ast_visitor'; import { getOffsetToLocation } from './source_maps'; -const IGNORE_RE = /\/\*\s*solcov\s+ignore\s+next\s*\*\/\s*/gm; - // Parsing source code for each transaction/code is slow and therefore we cache it const sourceHashToCoverageEntries: { [sourceHash: string]: CoverageEntriesDescription } = {}; -export const collectCoverageEntries = (contractSource: string) => { +export const collectCoverageEntries = (contractSource: string, ignoreRegexp?: RegExp) => { const sourceHash = ethUtil.sha3(contractSource).toString('hex'); if (_.isUndefined(sourceHashToCoverageEntries[sourceHash]) && !_.isUndefined(contractSource)) { const ast = parser.parse(contractSource, { range: true }); const offsetToLocation = getOffsetToLocation(contractSource); - const ignoreRangesBegingingAt = gatherRangesToIgnore(contractSource); - const visitor = new ASTVisitor(offsetToLocation, ignoreRangesBegingingAt); + const ignoreRangesBeginningAt = _.isUndefined(ignoreRegexp) + ? [] + : gatherRangesToIgnore(contractSource, ignoreRegexp); + const visitor = new ASTVisitor(offsetToLocation, ignoreRangesBeginningAt); parser.visit(ast, visitor); sourceHashToCoverageEntries[sourceHash] = visitor.getCollectedCoverageEntries(); } @@ -25,12 +25,12 @@ export const collectCoverageEntries = (contractSource: string) => { }; // Gather the start index of all code blocks preceeded by "/* solcov ignore next */" -function gatherRangesToIgnore(contractSource: string): number[] { +function gatherRangesToIgnore(contractSource: string, ignoreRegexp: RegExp): number[] { const ignoreRangesStart = []; let match; do { - match = IGNORE_RE.exec(contractSource); + match = ignoreRegexp.exec(contractSource); if (match) { const matchLen = match[0].length; ignoreRangesStart.push(match.index + matchLen); diff --git a/packages/sol-tracing-utils/src/utils.ts b/packages/sol-tracing-utils/src/utils.ts index 89c158ee7..7dc1844a5 100644 --- a/packages/sol-tracing-utils/src/utils.ts +++ b/packages/sol-tracing-utils/src/utils.ts @@ -1,15 +1,14 @@ -import { addressUtils, BigNumber } from '@0x/utils'; +import { addressUtils, BigNumber, logUtils } from '@0x/utils'; import { OpCode, StructLog } from 'ethereum-types'; import { addHexPrefix } from 'ethereumjs-util'; import * as _ from 'lodash'; import { ContractData, LineColumn, SingleFileSourceRange } from './types'; -// This is the minimum length of valid contract bytecode. The Solidity compiler -// metadata is 86 bytes. If you add the '0x' prefix, we get 88. -const MIN_CONTRACT_BYTECODE_LENGTH = 88; const STATICCALL_GAS_COST = 40; +const bytecodeToContractDataIfExists: { [bytecode: string]: ContractData | undefined } = {}; + export const utils = { compareLineColumn(lhs: LineColumn, rhs: LineColumn): number { return lhs.line !== rhs.line ? lhs.line - rhs.line : lhs.column - rhs.column; @@ -47,22 +46,29 @@ export const utils = { if (!bytecode.startsWith('0x')) { throw new Error(`0x hex prefix missing: ${bytecode}`); } - const contractData = _.find(contractsData, contractDataCandidate => { + // HACK(leo): We want to cache the values that are possibly undefined. + // That's why we can't check for undefined as we usually do, but need to use `hasOwnProperty`. + if (bytecodeToContractDataIfExists.hasOwnProperty(bytecode)) { + return bytecodeToContractDataIfExists[bytecode]; + } + const contractDataCandidates = _.filter(contractsData, contractDataCandidate => { const bytecodeRegex = utils.bytecodeToBytecodeRegex(contractDataCandidate.bytecode); - // If the bytecode is less than the minimum length, we are probably - // dealing with an interface. This isn't what we're looking for. - if (bytecodeRegex.length < MIN_CONTRACT_BYTECODE_LENGTH) { - return false; - } const runtimeBytecodeRegex = utils.bytecodeToBytecodeRegex(contractDataCandidate.runtimeBytecode); - if (runtimeBytecodeRegex.length < MIN_CONTRACT_BYTECODE_LENGTH) { - return false; - } // We use that function to find by bytecode or runtimeBytecode. Those are quasi-random strings so // collisions are practically impossible and it allows us to reuse that code return !_.isNull(bytecode.match(bytecodeRegex)) || !_.isNull(bytecode.match(runtimeBytecodeRegex)); }); - return contractData; + if (contractDataCandidates.length > 1) { + const candidates = contractDataCandidates.map( + contractDataCandidate => _.values(contractDataCandidate.sources)[0], + ); + const errMsg = + "We've found more than one artifact that contains the exact same bytecode and therefore are unable to detect which contract was executed. " + + "We'll be assigning all traces to the first one."; + logUtils.warn(errMsg); + logUtils.warn(candidates); + } + return (bytecodeToContractDataIfExists[bytecode] = contractDataCandidates[0]); }, isCallLike(op: OpCode): boolean { return _.includes([OpCode.CallCode, OpCode.StaticCall, OpCode.Call, OpCode.DelegateCall], op); diff --git a/packages/sol-tracing-utils/test/collect_coverage_entries_test.ts b/packages/sol-tracing-utils/test/collect_coverage_entries_test.ts index 7832ec316..d3ca8930c 100644 --- a/packages/sol-tracing-utils/test/collect_coverage_entries_test.ts +++ b/packages/sol-tracing-utils/test/collect_coverage_entries_test.ts @@ -130,7 +130,8 @@ describe('Collect coverage entries', () => { solcovIgnoreContractBaseName, ); const solcovIgnoreContract = fs.readFileSync(solcovIgnoreContractFileName).toString(); - const coverageEntries = collectCoverageEntries(solcovIgnoreContract); + const IGNORE_REGEXP = /\/\*\s*solcov\s+ignore\s+next\s*\*\/\s*/gm; + const coverageEntries = collectCoverageEntries(solcovIgnoreContract, IGNORE_REGEXP); const fnIds = _.keys(coverageEntries.fnMap); expect(fnIds.length).to.be.equal(1); @@ -13462,8 +13462,8 @@ react-highlight@0xproject/react-highlight#fix/react-version: dependencies: highlight.js "^9.11.0" highlightjs-solidity "^1.0.5" - react "^16.4.2" - react-dom "^16.4.2" + react "^16.5.2" + react-dom "^16.5.2" react-hot-loader@^4.3.3: version "4.3.4" |