Skip to content

Commit 644435f

Browse files
committed
Send contract code via POST body. Showing compilation errors in FE
1 parent 0c90a88 commit 644435f

File tree

10 files changed

+66
-41
lines changed

10 files changed

+66
-41
lines changed

cfg

Lines changed: 5 additions & 0 deletions
Large diffs are not rendered by default.

src/api/bytecode/EVMDisassembler.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ export class EVMDisassembler implements Disassembler {
2626
}
2727

2828
const contract = this.contractService.compileContract(contractName, source, path)
29-
30-
3129
const bytecode = contract.evm.bytecode.object
3230
const runtimeBytecode = contract.evm.deployedBytecode.object
3331
const contractAssembly = contract.evm.legacyAssembly

src/api/service/controller/ControlFlowGraphController.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Route, Controller, Get, Query } from 'tsoa'
1+
import { Route, Controller, Query, Body, Post } from 'tsoa'
22
import { provideSingleton, inject } from '../../../inversify/ioc'
33
import { TYPES } from '../../../inversify/types'
44
import { CFGService } from '../service/CFGService'
@@ -7,6 +7,8 @@ import { CFGContract } from '../bean/CFGContract'
77
import { GFCResponse } from '../response/CFGResponse'
88
import { OperationResponse } from '../response/OperationResponse'
99
import { logger } from '../../../Logger'
10+
import { StringBodyRequest } from '../request/StringBodyRequest';
11+
const fs = require('fs')
1012

1113
@Route('cfg')
1214
@provideSingleton(ControlFlowGraphController)
@@ -18,33 +20,34 @@ export class ControlFlowGraphController extends Controller {
1820
super()
1921
}
2022

21-
@Get('source')
23+
@Post('source')
2224
async getCFGFromSource(
23-
@Query('source') source: string,
25+
@Body() source: StringBodyRequest,
2426
@Query('name') name: string,
2527
@Query('path') path: string,
2628
@Query('constructor') constructor?: boolean
2729
): Promise<GFCResponse> {
2830
try {
29-
const contractBlocks: CFGContract = this.cfgService.buildCFGFromSource(name, source, path)
31+
const contractBlocks: CFGContract = this.cfgService.buildCFGFromSource(name, source.request, path)
3032
if (!contractBlocks.contractConstructor && constructor) {
3133
throw new Error('Constructor is true but no constructor found in bytecode')
3234
}
3335
const cfg = this.createCFG(contractBlocks, constructor)
36+
await fs.writeFileSync('cfg', cfg)
3437
return this.buildResponse(contractBlocks, constructor, cfg)
3538
} catch (err) {
3639
logger.error(err)
3740
throw new Error(err.message)
3841
}
3942
}
4043

41-
@Get('bytecode')
44+
@Post('bytecode')
4245
async getCFGFromBytecode(
43-
@Query('bytecode') bytecode: string,
46+
@Body() bytecode: StringBodyRequest,
4447
@Query('constructor') constructor?: boolean
4548
): Promise<GFCResponse> {
4649
try {
47-
const contractBlocks: CFGContract = this.cfgService.buildCFGFromBytecode(bytecode)
50+
const contractBlocks: CFGContract = this.cfgService.buildCFGFromBytecode(bytecode.request)
4851
if (!contractBlocks.contractConstructor && constructor) {
4952
throw new Error('Constructor is true but no constructor found in bytecode')
5053
}

src/api/service/controller/DebuggerController.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Route, Controller, Get, Query, Path } from 'tsoa'
1+
import { Route, Controller, Query, Path, Body, Post } from 'tsoa'
22
import { provideSingleton, inject } from '../../../inversify/ioc'
33
import { TYPES } from '../../../inversify/types'
44
import { CFGService } from '../service/CFGService'
@@ -10,6 +10,7 @@ import { OperationResponse } from '../response/OperationResponse'
1010
import { TraceResponse } from '../response/TraceResponse'
1111
import { logger } from '../../../Logger'
1212
import { Web3Configuration } from 'src/api/blockchain/Web3Configuration';
13+
import { StringBodyRequest } from '../request/StringBodyRequest';
1314

1415
@Route('debug')
1516
@provideSingleton(DebuggerController)
@@ -22,10 +23,10 @@ export class DebuggerController extends Controller {
2223
super()
2324
}
2425

25-
@Get('{tx}')
26+
@Post('{tx}')
2627
async debug(
2728
@Path() tx: string,
28-
@Query('source') source: string,
29+
@Body() source: StringBodyRequest,
2930
@Query('name') name: string,
3031
@Query('path') path: string,
3132
@Query('blockchainHost') blockchainHost?: string,
@@ -41,7 +42,7 @@ export class DebuggerController extends Controller {
4142
blockchainBasicAuthUsername,
4243
blockchainBasicAuthPassword
4344
} as Web3Configuration
44-
const contractBlocks: CFGContract = await this.cfgService.buildCFGFromSource(name, source, path)
45+
const contractBlocks: CFGContract = await this.cfgService.buildCFGFromSource(name, source.request, path)
4546
const runtimeRawBytecode = contractBlocks.contractRuntime.rawBytecode.startsWith('0x')? contractBlocks.contractRuntime.rawBytecode: `0x${contractBlocks.contractRuntime.rawBytecode}`
4647
const trace: DebugTrace = await this.transactionService.findTransactionTrace(tx, runtimeRawBytecode, config)
4748
const cfg = this.createCFG(contractBlocks, false, trace)

src/api/service/controller/DisassembleController.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { Controller, Route, Get, Query } from 'tsoa'
1+
import { Controller, Route, Query, Post, Body } from 'tsoa'
22
import { provideSingleton, inject } from '../../../inversify/ioc'
33
import { TYPES } from '../../../inversify/types'
44
import { Disassembler } from '../../bytecode/Disassembler'
55
import { DisassembledContract } from '../../bytecode/DisassembledContract'
66
import { DisassembledContractResponse } from '../response/DisassembledContractResponse'
77
import { logger } from '../../../Logger'
8+
import { StringBodyRequest } from '../request/StringBodyRequest';
89

910
@Route('disassemble')
1011
@provideSingleton(DisassembleController)
@@ -13,14 +14,14 @@ export class DisassembleController extends Controller {
1314
super()
1415
}
1516

16-
@Get()
17+
@Post()
1718
async disassembleSourceCode(
18-
@Query('source') source: string,
19+
@Body() source: StringBodyRequest,
1920
@Query('name') name: string,
2021
@Query('path') path: string
2122
): Promise<DisassembledContractResponse> {
2223
try {
23-
const disassembled: DisassembledContract = this.disassembler.disassembleSourceCode(name, source, path)
24+
const disassembled: DisassembledContract = this.disassembler.disassembleSourceCode(name, source.request, path)
2425
return this.contractToResponse(disassembled)
2526
} catch (err) {
2627
logger.error(err)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface StringBodyRequest {
2+
request: string
3+
}

src/api/service/service/ContractService.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { IWeb3 } from "../../blockchain/IWeb3";
44
import { TransactionBase } from "../bean/TransactionBase";
55
import { TYPES } from "../../../inversify/types";
66
import { Solc } from "./Solc";
7+
import { logger } from "../../../Logger";
78
let fs = require('fs')
89
let nodePath = require('path')
910

@@ -22,6 +23,12 @@ export class ContractService {
2223
compileContract(contractName: string, source: string, path: string): any {
2324
const compileJson = this.generateCompileObject(contractName, source, path)
2425
const compiledContract = JSON.parse(this.solc.getInstance().compileStandardWrapper(JSON.stringify(compileJson)))
26+
if (compiledContract.errors && compiledContract.errors.filter(e => e.severity === 'error').length > 0) {
27+
const errors = compiledContract.errors.filter(e => e.severity === 'error')
28+
let errorMessage = `Error compiling. ${errors[0].formattedMessage} . View console to see al errors`
29+
logger.error(errors)
30+
throw new Error(errorMessage)
31+
}
2532
const contractWithExt = `${contractName}.sol`
2633
const contract = compiledContract.contracts[contractWithExt][contractName]
2734
if (!contract) {

src/client/components/Graph/Graph.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ class ConnectedGraph extends React.Component {
2626

2727
componentDidMount() {
2828
const { cfg, graphId, graphType } = this.props;
29-
3029
const graphclass = graphId.replace('.sol', '').replace('.evm', '');
3130
const graphviz = d3.select(`.graph--${graphclass}--${graphType}`).graphviz()
32-
graphviz.totalMemory(537395200)
31+
graphviz.totalMemory(1074790400)
3332
graphviz.renderDot(cfg);
3433
// TODO make it configurable?
3534
graphviz._zoomBehavior.scaleExtent([1/10, 10000]);

src/client/components/Tab/TabPanel/TabPanel.js

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,20 @@ class TabPanel extends React.Component {
7171
return url;
7272
}
7373

74-
fetchData(url, type) {
74+
fetchData(url, type, body) {
7575
this.handleRequestPending();
76-
77-
fetch(url)
76+
fetch(url, body? {
77+
body: JSON.stringify({request: body}),
78+
method: 'POST',
79+
headers:{
80+
'Content-Type': 'application/json'
81+
}
82+
}: {})
7883
.then(res => res.json())
7984
.then(data => {
80-
data.error
81-
? this.handleRequestFail(data.message)
82-
: this.handleRequestSuccess(data, type);
85+
data.error
86+
? this.handleRequestFail(data)
87+
: this.handleRequestSuccess(data, type);
8388
})
8489
.catch(err => this.handleRequestFail(err));
8590
}
@@ -130,7 +135,8 @@ class TabPanel extends React.Component {
130135
this.props.loadingMessageOff();
131136
}
132137

133-
handleRequestFail(message) {
138+
handleRequestFail(data) {
139+
const message = data.message
134140
this.props.loadingMessageOff();
135141
this.props.errorMessageOn();
136142
this.props.getErrorMessage(message);
@@ -142,14 +148,13 @@ class TabPanel extends React.Component {
142148
const params = {
143149
name: name.replace('.sol', '').replace('.evm', ''),
144150
path: encodeURIComponent(path),
145-
source: encodeURIComponent(code),
146151
blockchainHost: localStorage.getItem('host'),
147152
blockchainProtocol: localStorage.getItem('protocol'),
148153
blockchainBasicAuthUsername: localStorage.getItem('username'),
149154
blockchainBasicAuthPassword: localStorage.getItem('password')
150155
}
151156

152-
this.fetchData(this.getUrl(`debug/${this.state.transactionHash}/`, params), 'Transaction Debugger');
157+
this.fetchData(this.getUrl(`debug/${this.state.transactionHash}/`, params), 'Transaction Debugger', code);
153158
}
154159

155160
handleFormInputChange(event) {
@@ -201,10 +206,9 @@ class TabPanel extends React.Component {
201206
const params = {
202207
name: name.replace('.sol', '').replace('.evm', ''),
203208
path: encodeURIComponent(path),
204-
source: encodeURIComponent(code),
205209
'constructor': 'false'
206210
}
207-
this.fetchData(this.getUrl('cfg/source', params), 'Control Flow Graph');
211+
this.fetchData(this.getUrl('cfg/source', params), 'Control Flow Graph', code);
208212

209213
document.removeEventListener('click', this.handleOutsideClick);
210214
}
@@ -214,10 +218,9 @@ class TabPanel extends React.Component {
214218

215219
const params = {
216220
name: name.replace('.sol', '').replace('.evm', ''),
217-
path: encodeURIComponent(path),
218-
source: encodeURIComponent(code)
221+
path: encodeURIComponent(path)
219222
}
220-
this.fetchData(this.getUrl('disassemble', params), 'Disassembler');
223+
this.fetchData(this.getUrl('disassemble', params), 'Disassembler', code);
221224

222225
document.removeEventListener('click', this.handleOutsideClick);
223226
}

src/routes.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ const models: TsoaRoute.Models = {
3434
"trace": { "dataType": "any", "required": true },
3535
},
3636
},
37+
"StringBodyRequest": {
38+
"properties": {
39+
"request": { "dataType": "string", "required": true },
40+
},
41+
},
3742
"ContractFile": {
3843
"properties": {
3944
"name": { "dataType": "string", "required": true },
@@ -108,11 +113,11 @@ const models: TsoaRoute.Models = {
108113
};
109114

110115
export function RegisterRoutes(app: any) {
111-
app.get('/debug/:tx',
116+
app.post('/debug/:tx',
112117
function(request: any, response: any, next: any) {
113118
const args = {
114119
tx: { "in": "path", "name": "tx", "required": true, "dataType": "string" },
115-
source: { "in": "query", "name": "source", "required": true, "dataType": "string" },
120+
source: { "in": "body", "name": "source", "required": true, "ref": "StringBodyRequest" },
116121
name: { "in": "query", "name": "name", "required": true, "dataType": "string" },
117122
path: { "in": "query", "name": "path", "required": true, "dataType": "string" },
118123
blockchainHost: { "in": "query", "name": "blockchainHost", "dataType": "string" },
@@ -160,10 +165,10 @@ export function RegisterRoutes(app: any) {
160165
const promise = controller.findContractsInDir.apply(controller, validatedArgs);
161166
promiseHandler(controller, promise, response, next);
162167
});
163-
app.get('/disassemble',
168+
app.post('/disassemble',
164169
function(request: any, response: any, next: any) {
165170
const args = {
166-
source: { "in": "query", "name": "source", "required": true, "dataType": "string" },
171+
source: { "in": "body", "name": "source", "required": true, "ref": "StringBodyRequest" },
167172
name: { "in": "query", "name": "name", "required": true, "dataType": "string" },
168173
path: { "in": "query", "name": "path", "required": true, "dataType": "string" },
169174
};
@@ -210,10 +215,10 @@ export function RegisterRoutes(app: any) {
210215
const promise = controller.getReceipt.apply(controller, validatedArgs);
211216
promiseHandler(controller, promise, response, next);
212217
});
213-
app.get('/cfg/source',
218+
app.post('/cfg/source',
214219
function(request: any, response: any, next: any) {
215220
const args = {
216-
source: { "in": "query", "name": "source", "required": true, "dataType": "string" },
221+
source: { "in": "body", "name": "source", "required": true, "ref": "StringBodyRequest" },
217222
name: { "in": "query", "name": "name", "required": true, "dataType": "string" },
218223
path: { "in": "query", "name": "path", "required": true, "dataType": "string" },
219224
constructor: { "in": "query", "name": "constructor", "dataType": "boolean" },
@@ -235,10 +240,10 @@ export function RegisterRoutes(app: any) {
235240
const promise = controller.getCFGFromSource.apply(controller, validatedArgs);
236241
promiseHandler(controller, promise, response, next);
237242
});
238-
app.get('/cfg/bytecode',
243+
app.post('/cfg/bytecode',
239244
function(request: any, response: any, next: any) {
240245
const args = {
241-
bytecode: { "in": "query", "name": "bytecode", "required": true, "dataType": "string" },
246+
bytecode: { "in": "body", "name": "bytecode", "required": true, "ref": "StringBodyRequest" },
242247
constructor: { "in": "query", "name": "constructor", "dataType": "boolean" },
243248
};
244249

0 commit comments

Comments
 (0)