aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Hysen <greg.hysen@gmail.com>2018-11-14 04:36:14 +0800
committerGreg Hysen <greg.hysen@gmail.com>2018-11-29 08:38:10 +0800
commit7c733662e2669ca6682920f321c81e770605b3d5 (patch)
tree9d25d3461f18459a67d65ad383d09cda214ab699
parent52474a0b8edb2f49f850069c1a79dcd9b5d77e9d (diff)
downloaddexon-sol-tools-7c733662e2669ca6682920f321c81e770605b3d5.tar
dexon-sol-tools-7c733662e2669ca6682920f321c81e770605b3d5.tar.gz
dexon-sol-tools-7c733662e2669ca6682920f321c81e770605b3d5.tar.bz2
dexon-sol-tools-7c733662e2669ca6682920f321c81e770605b3d5.tar.lz
dexon-sol-tools-7c733662e2669ca6682920f321c81e770605b3d5.tar.xz
dexon-sol-tools-7c733662e2669ca6682920f321c81e770605b3d5.tar.zst
dexon-sol-tools-7c733662e2669ca6682920f321c81e770605b3d5.zip
Annotated calldata (draft).
-rw-r--r--packages/order-utils/test/abi/calldata.ts113
-rw-r--r--packages/order-utils/test/abi/data_type.ts21
-rw-r--r--packages/order-utils/test/abi/evm_data_types.ts4
-rw-r--r--packages/order-utils/test/abi_encoder_test.ts7
4 files changed, 118 insertions, 27 deletions
diff --git a/packages/order-utils/test/abi/calldata.ts b/packages/order-utils/test/abi/calldata.ts
index 0445f68ec..1173f90cc 100644
--- a/packages/order-utils/test/abi/calldata.ts
+++ b/packages/order-utils/test/abi/calldata.ts
@@ -9,10 +9,12 @@ export abstract class CalldataBlock {
private headerSizeInBytes: number;
private bodySizeInBytes: number;
private relocatable: boolean;
+ private parentName: string;
- constructor(name: string, signature: string, /*offsetInBytes: number,*/ headerSizeInBytes: number, bodySizeInBytes: number, relocatable: boolean) {
+ constructor(name: string, signature: string, parentName: string, /*offsetInBytes: number,*/ headerSizeInBytes: number, bodySizeInBytes: number, relocatable: boolean) {
this.name = name;
this.signature = signature;
+ this.parentName = parentName;
this.offsetInBytes = 0;
this.headerSizeInBytes = headerSizeInBytes;
this.bodySizeInBytes = bodySizeInBytes;
@@ -31,6 +33,10 @@ export abstract class CalldataBlock {
return this.name;
}
+ public getParentName(): string {
+ return this.parentName;
+ }
+
public getSignature(): string {
return this.signature;
}
@@ -65,10 +71,10 @@ export abstract class CalldataBlock {
export class PayloadCalldataBlock extends CalldataBlock {
private payload: Buffer;
- constructor(name: string, signature: string, /*offsetInBytes: number,*/ relocatable: boolean, payload: Buffer) {
+ constructor(name: string, signature: string, parentName: string, /*offsetInBytes: number,*/ relocatable: boolean, payload: Buffer) {
const headerSizeInBytes = 0;
const bodySizeInBytes = payload.byteLength;
- super(name, signature, /*offsetInBytes,*/ headerSizeInBytes, bodySizeInBytes, relocatable);
+ super(name, signature, parentName, headerSizeInBytes, bodySizeInBytes, relocatable);
this.payload = payload;
}
@@ -82,10 +88,10 @@ export class DependentCalldataBlock extends CalldataBlock {
private parent: CalldataBlock;
private dependency: CalldataBlock;
- constructor(name: string, signature: string, /*offsetInBytes: number,*/ relocatable: boolean, dependency: CalldataBlock, parent: CalldataBlock) {
+ constructor(name: string, signature: string, parentName: string, relocatable: boolean, dependency: CalldataBlock, parent: CalldataBlock) {
const headerSizeInBytes = 0;
const bodySizeInBytes = DependentCalldataBlock.DEPENDENT_PAYLOAD_SIZE_IN_BYTES;
- super(name, signature, /*offsetInBytes,*/ headerSizeInBytes, bodySizeInBytes, relocatable);
+ super(name, signature, parentName, headerSizeInBytes, bodySizeInBytes, relocatable);
this.parent = parent;
this.dependency = dependency;
}
@@ -112,8 +118,8 @@ export class MemberCalldataBlock extends CalldataBlock {
private members: CalldataBlock[];
private contiguous: boolean;
- constructor(name: string, signature: string, /*offsetInBytes: number,*/ relocatable: boolean, contiguous: boolean) {
- super(name, signature, /*offsetInBytes,*/ 0, 0, relocatable);
+ constructor(name: string, signature: string, parentName: string, relocatable: boolean, contiguous: boolean) {
+ super(name, signature, parentName, 0, 0, relocatable);
this.members = [];
this.header = undefined;
this.contiguous = contiguous;
@@ -231,33 +237,110 @@ export class Calldata {
})
}*/
- public toHexString(optimize: boolean = false): string {
- let selectorBuffer = ethUtil.toBuffer(this.selector);
+ private generateAnnotatedHexString(): string {
+ let hexValue = `${this.selector}`;
if (this.root === undefined) {
throw new Error('expected root');
}
- const offsetQueue = this.createQueue(this.root);
+ const valueQueue = this.createQueue(this.root);
+
let block: CalldataBlock | undefined;
let offset = 0;
- while ((block = offsetQueue.pop()) !== undefined) {
- block.setOffset(offset);
- offset += block.getSizeInBytes();
+ const functionBlock = valueQueue.peek();
+ let functionName: string = functionBlock === undefined ? '' : functionBlock.getName();
+ while ((block = valueQueue.pop()) !== undefined) {
+ // Set f
+
+ // Process each block 1 word at a time
+ const size = block.getSizeInBytes();
+ const name = block.getName();
+ const parentName = block.getParentName();
+ console.log('*'.repeat(50), parentName, ' vs ', name);
+
+ //const ancestrialNamesOffset = name.startsWith('ptr<') ? 4 : 0;
+ //const parentOffset = name.lastIndexOf(parentName);
+ const prettyName = name.replace(`${parentName}.`, '').replace(`${functionName}.`, '');//.replace(`${parentName}[`, '[');
+ const signature = block.getSignature();
+
+ // Current offset
+ let offsetStr = '';
+
+ // If this block is empty then it's a newline
+ let value = '';
+ let nameStr = '';
+ let line = '';
+ if (size === 0) {
+ offsetStr = ' '.repeat(10);
+ value = ' '.repeat(74);
+ nameStr = `### ${prettyName.padEnd(80)}`;
+ line = `\n${offsetStr}${value}${nameStr}`;
+ } else {
+ offsetStr = `0x${offset.toString(16)}`.padEnd(10, ' ');
+ value = ethUtil.stripHexPrefix(ethUtil.bufferToHex(block.toBuffer().slice(0, 32))).padEnd(74);
+ if (block instanceof MemberCalldataBlock) {
+ nameStr = `### ${prettyName.padEnd(80)}`;
+ line = `\n${offsetStr}${value}${nameStr}`;
+ } else {
+ nameStr = ` ${prettyName.padEnd(80)}`;
+ line = `${offsetStr}${value}${nameStr}`;
+ }
+ }
+
+ for (let j = 32; j < size; j += 32) {
+ offsetStr = `0x${(offset + j).toString(16)}`.padEnd(10, ' ');
+ value = ethUtil.stripHexPrefix(ethUtil.bufferToHex(block.toBuffer().slice(j, j + 32))).padEnd(74);
+ nameStr = ' '.repeat(40);
+
+ line = `${line}\n${offsetStr}${value}${nameStr}`;
+ }
+
+ // Append to hex value
+ hexValue = `${hexValue}\n${line}`;
+ offset += size;
+ }
+
+ return hexValue;
+ }
+
+ private generateCondensedHexString(): string {
+ let selectorBuffer = ethUtil.toBuffer(this.selector);
+ if (this.root === undefined) {
+ throw new Error('expected root');
}
const valueQueue = this.createQueue(this.root);
const valueBufs: Buffer[] = [selectorBuffer];
+ let block: CalldataBlock | undefined;
while ((block = valueQueue.pop()) !== undefined) {
valueBufs.push(block.toBuffer());
}
- // if (optimize) this.optimize(valueQueue.getStore());
-
const combinedBuffers = Buffer.concat(valueBufs);
const hexValue = ethUtil.bufferToHex(combinedBuffers);
return hexValue;
}
+ public toHexString(optimize: boolean = false, annotate: boolean = false): string {
+ if (this.root === undefined) {
+ throw new Error('expected root');
+ }
+
+ const offsetQueue = this.createQueue(this.root);
+ let block: CalldataBlock | undefined;
+ let offset = 0;
+ while ((block = offsetQueue.pop()) !== undefined) {
+ block.setOffset(offset);
+ offset += block.getSizeInBytes();
+ }
+
+
+ // if (optimize) this.optimize(valueQueue.getStore());
+
+ const hexValue = annotate ? this.generateAnnotatedHexString() : this.generateCondensedHexString();
+ return hexValue;
+ }
+
public getSelectorHex(): string {
return this.selector;
}
diff --git a/packages/order-utils/test/abi/data_type.ts b/packages/order-utils/test/abi/data_type.ts
index 725d314f3..25f792c7a 100644
--- a/packages/order-utils/test/abi/data_type.ts
+++ b/packages/order-utils/test/abi/data_type.ts
@@ -38,9 +38,9 @@ export abstract class PayloadDataType extends DataType {
const encodedValue = this.encodeValue(value);
const name = this.getDataItem().name;
const signature = this.getSignature();
- // const offsetInBytes = calldata.getSizeInBytes();
+ const parentName = parentBlock === undefined ? '' : parentBlock.getName();
const relocatable = false;
- const block = new PayloadCalldataBlock(name, signature, /*offsetInBytes,*/ relocatable, encodedValue);
+ const block = new PayloadCalldataBlock(name, signature, parentName, /*offsetInBytes,*/ relocatable, encodedValue);
return block;
}
@@ -77,11 +77,12 @@ export abstract class DependentDataType extends DataType {
if (parentBlock === undefined) {
throw new Error(`DependentDataType requires a parent block to generate its block`);
}
- const dependencyBlock = this.dependency.generateCalldataBlock(value);
+ const dependencyBlock = this.dependency.generateCalldataBlock(value, parentBlock);
const name = this.getDataItem().name;
const signature = this.getSignature();
+ const parentName = parentBlock === undefined ? '' : parentBlock.getName();
const relocatable = false;
- const block = new DependentCalldataBlock(name, signature, /*offsetInBytes,*/ relocatable, dependencyBlock, parentBlock);
+ const block = new DependentCalldataBlock(name, signature, parentName, relocatable, dependencyBlock, parentBlock);
return block;
}
@@ -179,7 +180,7 @@ export abstract class MemberDataType extends DataType {
return [members, memberMap];
}
- protected generateCalldataBlockFromArray(value: any[]): MemberCalldataBlock {
+ protected generateCalldataBlockFromArray(value: any[], parentBlock?: CalldataBlock): MemberCalldataBlock {
// Sanity check length
if (this.arrayLength !== undefined && value.length !== this.arrayLength) {
throw new Error(
@@ -189,7 +190,8 @@ export abstract class MemberDataType extends DataType {
);
}
- const methodBlock: MemberCalldataBlock = new MemberCalldataBlock(this.getDataItem().name, this.getSignature(), this.isStatic(), false);
+ const parentName = parentBlock === undefined ? '' : parentBlock.getName();
+ const methodBlock: MemberCalldataBlock = new MemberCalldataBlock(this.getDataItem().name, this.getSignature(), parentName, this.isStatic(), false);
let members = this.members;
if (this.isArray && this.arrayLength === undefined) {
@@ -208,8 +210,9 @@ export abstract class MemberDataType extends DataType {
return methodBlock;
}
- protected generateCalldataBlockFromObject(obj: object): MemberCalldataBlock {
- const methodBlock: MemberCalldataBlock = new MemberCalldataBlock(this.getDataItem().name, this.getSignature(), this.isStatic(), false);
+ protected generateCalldataBlockFromObject(obj: object, parentBlock?: CalldataBlock): MemberCalldataBlock {
+ const parentName = parentBlock === undefined ? '' : parentBlock.getName();
+ const methodBlock: MemberCalldataBlock = new MemberCalldataBlock(this.getDataItem().name, this.getSignature(), parentName, this.isStatic(), false);
const memberBlocks: CalldataBlock[] = [];
let childMap = _.cloneDeep(this.memberMap);
_.forOwn(obj, (value: any, key: string) => {
@@ -230,7 +233,7 @@ export abstract class MemberDataType extends DataType {
}
public generateCalldataBlock(value: any[] | object, parentBlock?: CalldataBlock): MemberCalldataBlock {
- const block = (value instanceof Array) ? this.generateCalldataBlockFromArray(value) : this.generateCalldataBlockFromObject(value);
+ const block = (value instanceof Array) ? this.generateCalldataBlockFromArray(value, parentBlock) : this.generateCalldataBlockFromObject(value, parentBlock);
return block;
}
diff --git a/packages/order-utils/test/abi/evm_data_types.ts b/packages/order-utils/test/abi/evm_data_types.ts
index 7b366a985..ea401247b 100644
--- a/packages/order-utils/test/abi/evm_data_types.ts
+++ b/packages/order-utils/test/abi/evm_data_types.ts
@@ -489,10 +489,10 @@ export class Method extends MemberDataType {
return selector;
}
- public encode(value: any[] | object, calldata = new Calldata()): string {
+ public encode(value: any[] | object, calldata = new Calldata(), annotate: boolean = false): string {
calldata.setSelector(this.methodSelector);
super.encode(value, calldata);
- return calldata.toHexString();
+ return calldata.toHexString(false, annotate);
}
public decode(calldata: string, decodeStructsAsObjects: boolean = false): any[] | object {
diff --git a/packages/order-utils/test/abi_encoder_test.ts b/packages/order-utils/test/abi_encoder_test.ts
index 137850b35..8b836f77f 100644
--- a/packages/order-utils/test/abi_encoder_test.ts
+++ b/packages/order-utils/test/abi_encoder_test.ts
@@ -17,6 +17,7 @@ import { assert } from '@0x/order-utils/src/assert';
import * as AbiEncoder from './abi/abi_encoder';
import * as AbiSamples from './abi_samples';
+import { Calldata } from './abi/calldata';
AbiEncoder.DataTypeFactory.setImpl(new AbiEncoder.EvmDataTypeFactoryImpl());
@@ -88,8 +89,12 @@ describe.only('ABI Encoder', () => {
someArrayOfTuplesWithDynamicTypes: someArrayOfTuplesWithDynamicTypes
};
- const calldata = method.encode(args);
+ const calldata = method.encode(args, new Calldata(), true);
console.log(calldata);
+
+
+ throw new Error(`done`);
+
console.log('*'.repeat(40));
console.log(JSON.stringify(args));
console.log(method.getSignature());