Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

The wire decoder (in-house transaction and event decoding) #2158

Merged
merged 114 commits into from
Aug 21, 2019
Merged
Show file tree
Hide file tree
Changes from 95 commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
07d663d
Add event and transaction decoding (initial commit, don't use)
haltman-at Jun 4, 2019
1540474
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 5, 2019
995fade
Account for further merge changes
haltman-at Jun 5, 2019
dd51ee1
Add "unknown" type to decoded transactions & events
haltman-at Jun 5, 2019
e54d8a9
Account for possibility of anonymous calldata parameters
haltman-at Jun 5, 2019
cd0e9fc
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 6, 2019
9d01456
Update errors for new type system
haltman-at Jun 6, 2019
3992f40
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 7, 2019
d50b0b1
Add class field to decoding; have contract decoder check address
haltman-at Jun 7, 2019
51e8ad7
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 7, 2019
a637570
Update types
haltman-at Jun 7, 2019
769ef1c
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 12, 2019
d2845d3
Make use of functionKind shim (+ correction to name check)
haltman-at Jun 12, 2019
cda1056
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 13, 2019
d039eef
Fix default constructor allocation; regularize calldata allocation fo…
haltman-at Jun 13, 2019
e586eaa
Handle the possibility of library events
haltman-at Jun 13, 2019
ba1b5af
Store event allocations by selector only; update contract.ts
haltman-at Jun 13, 2019
c797ff1
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 14, 2019
98075b0
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 15, 2019
06e5ad6
Pass along compiler info in wire decoder
haltman-at Jun 15, 2019
fc908ec
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 18, 2019
65afedd
Remove redundancy in calldata interface
haltman-at Jun 18, 2019
c686278
Fix lots of compile errors!
haltman-at Jun 18, 2019
6185c2a
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 18, 2019
65a4ebd
Add a bit that went missing in a merge somewhere
haltman-at Jun 18, 2019
c95ad3f
Redo calldata/event allocation interface
haltman-at Jun 18, 2019
ac1a2a5
Add an abi encoder!
haltman-at Jun 19, 2019
a267db7
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 19, 2019
b6115b8
Update yarn.lock
haltman-at Jun 19, 2019
cd630d7
Rename truffle-decoder-core to truffle-codec
haltman-at Jun 19, 2019
4fb1d84
Fix outdated function names in data sagas
haltman-at Jun 19, 2019
e2d0e24
Rename truffle-decode-utils to truffle-codec-utils
haltman-at Jun 19, 2019
4f933cb
Remove dependence on web3-eth-abi; handle all ABI operations ourself
haltman-at Jun 19, 2019
66c4eda
Rename debug modules
haltman-at Jun 19, 2019
ca15926
Further reduce reliance on schema abi type
haltman-at Jun 20, 2019
3ae90b8
Make new event allocation format; feed decoded events back through th…
haltman-at Jun 20, 2019
819b615
Add error handling
haltman-at Jun 20, 2019
f5decf2
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 20, 2019
0ffb9c1
Further fixes to package.json
haltman-at Jun 20, 2019
ae55bb6
Fix uses in debugger (or tests) of outdated pointer and allocation fo…
haltman-at Jun 21, 2019
6611635
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 21, 2019
cb35427
Fix various other errors
haltman-at Jun 21, 2019
45c87f8
Clean up some typing
haltman-at Jun 21, 2019
be3a8d9
Account for libraries in event allocation in contract.ts
haltman-at Jun 21, 2019
1297710
Make mode parameter consistent
haltman-at Jun 21, 2019
acd63da
Allow decodeEvent to take a target name
haltman-at Jun 21, 2019
7b82811
Some minor fixes
haltman-at Jun 24, 2019
0bde61f
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 25, 2019
a34dab9
Update encoder for revised output format, and fix error in address en…
haltman-at Jun 25, 2019
803cd47
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 25, 2019
d84ca3f
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 25, 2019
fee9356
Update Solidity version in truffle-decoder tests
haltman-at Jun 25, 2019
509638d
Add some initial tests of the wire decoder
haltman-at Jun 25, 2019
b8a80ac
Fix typo preventing constructor contexts from being added
haltman-at Jun 25, 2019
8c1c7e0
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 26, 2019
8bb910f
Fix a wire decoder test
haltman-at Jun 26, 2019
a774445
Merge branch 'separate-contract-decoder' into wire-decoder
haltman-at Jun 26, 2019
252b2bd
Add further tests, fix minor errors
haltman-at Jun 26, 2019
4b8b010
Correct logic for finding possible contract allocations for events
haltman-at Jun 26, 2019
dbe6e33
Fix incorrect encoding of dynamic arrays
haltman-at Jun 27, 2019
9b41d4e
Remove commented-out test
haltman-at Jun 27, 2019
e1da2c5
Add test of indexed parameters
haltman-at Jun 27, 2019
e31273a
Revert "Remove commented-out test" and uncomment the test!
haltman-at Jun 27, 2019
038f3a4
Add test of library event
haltman-at Jun 27, 2019
4c79362
Add tests of maybe-but-not-really unambiguous events
haltman-at Jun 27, 2019
24270e9
Remove needless variable
haltman-at Jun 27, 2019
fb0fade
Add indexedness to event decoder output; remove need to explicitly ca…
haltman-at Jun 27, 2019
e262c47
Merge branch 'next' into wire-decoder
haltman-at Jul 3, 2019
fe5be58
Further update for type-and-value changes
haltman-at Jul 3, 2019
e059048
Handle anonymous events
haltman-at Jul 4, 2019
e3b3219
Fix undefinedness error; add test of anonymous events
haltman-at Jul 4, 2019
a24601e
Put more info in StopDecodingErrors; fix other error typing problems
haltman-at Jul 4, 2019
8b9555e
Change events() to take options object
haltman-at Jul 4, 2019
b9a0054
Fix decoding of events with no topics
haltman-at Jul 5, 2019
a8eeb87
Add some more tests
haltman-at Jul 5, 2019
ba6f6c0
Get rid of confusing id-allocation pairs in event decoder
haltman-at Jul 5, 2019
5391cb3
Update function types with more information
haltman-at Jul 9, 2019
c6c0451
Add address parameter to events(); simplify handling of other options
haltman-at Jul 9, 2019
50c023e
Account for absent "function" type in abi entries
haltman-at Jul 9, 2019
beeb90f
Account for getters in calldata allocation
haltman-at Jul 9, 2019
d859252
Fix various errors and add tests
haltman-at Jul 9, 2019
89fc176
Simplify process of getting getter inputs
haltman-at Jul 9, 2019
f7e3dbc
Further simplify definition-to-abi logic and fix possible bugs
haltman-at Jul 10, 2019
2750b05
Pre-wash names so that definitions will have names washed too
haltman-at Jul 10, 2019
e4a0890
Add test of name-washing
haltman-at Jul 10, 2019
1874484
Replace classes with interfaces and move methods elsewhere!
haltman-at Jul 12, 2019
a6a718a
Fix bugs related to compiler location
haltman-at Jul 12, 2019
e2dfe4e
Add files I forgot to commit (oops!)
haltman-at Jul 12, 2019
2e9fdd5
Add decodingMode; add tuples (sort of); add optional hints; shrink tr…
haltman-at Jul 12, 2019
f68962d
DecodeLog takes options rather than name, unknown includes data, fix …
haltman-at Jul 15, 2019
a6c0d53
Merge branch 'wire-decoder' into declassify
haltman-at Jul 15, 2019
c75dabc
Use replacement characters in nativize & viewer; add strict-mode erro…
haltman-at Jul 15, 2019
a01ae97
Fix incorrect use of Buffer.from()
haltman-at Jul 15, 2019
63d732f
Add missing return; add infinite loop comments
haltman-at Jul 16, 2019
93cb78b
Merge pull request #2180 from trufflesuite/declassify
haltman-at Jul 16, 2019
a49a63a
Make type hints and type IDs just strings
haltman-at Jul 17, 2019
d246e1d
Fix error in previous commit (sorry!)
haltman-at Jul 17, 2019
0afcbdf
Factor out wire decoder from contract decoder
haltman-at Jul 18, 2019
9503dac
Avoid including a duplicate of contract in contracts passed to wire d…
haltman-at Jul 18, 2019
f3d74b5
Add extra context so self-pointers can be recognized even w/o bytecode
haltman-at Jul 19, 2019
bbf6c39
Merge pull request #2232 from trufflesuite/factor-decoders
haltman-at Jul 25, 2019
4c7b96b
Rename balance, nonce to balanceAsBN, nonceAsBN
haltman-at Jul 25, 2019
784cd78
Get rid of separate padding errors for bool, enum
haltman-at Jul 25, 2019
63ada12
Replace name in decodings with abi
haltman-at Jul 25, 2019
781b86b
Fix out of date package name!
haltman-at Jul 25, 2019
bb6438f
Fix error with watch expression display
haltman-at Jul 25, 2019
ee56bc7
Merge branch 'next' into wire-decoder
haltman-at Jul 30, 2019
9b78765
Remove no-longer-used lodash.isequal
haltman-at Jul 30, 2019
2751d6d
Clean out-of-range bools used as mapping keys
haltman-at Jul 31, 2019
2181dc0
Merge branch 'next' into wire-decoder
haltman-at Aug 13, 2019
210f9e6
Merge branch 'next' into wire-decoder
haltman-at Aug 15, 2019
3fb9352
Address PR comments
haltman-at Aug 16, 2019
d5c833c
Rename fallback decoding case to message
haltman-at Aug 16, 2019
1d329e9
Add test of debugger's boolean-key-cleaning
haltman-at Aug 16, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
{
"name": "truffle-decode-utils",
"name": "truffle-codec-utils",
"version": "1.0.14",
"description": "Utilities for decoding data from the EVM",
"description": "Utilities for decoding data from the EVM or encoding it for the EVM",
"dependencies": {
"bn.js": "^4.11.8",
"lodash.clonedeep": "^4.5.0",
"lodash.escaperegexp": "^4.1.2",
"semver": "^6.1.1",
"web3": "1.0.0-beta.37",
"web3-eth-abi": "1.0.0-beta.52"
"web3": "1.0.0-beta.37"
},
"main": "dist/index.js",
"types": "src/index.ts",
Expand All @@ -18,13 +17,13 @@
"start": "node_modules/.bin/tsc --watch",
"test": "echo \"No test specified\" && exit 0;"
},
"repository": "https://github.com/trufflesuite/truffle/tree/master/packages/truffle-decode-utils",
"repository": "https://github.com/trufflesuite/truffle/tree/master/packages/truffle-codec-utils",
"author": "Truffle Suite <[email protected]>",
"license": "MIT",
"bugs": {
"url": "https://github.com/trufflesuite/truffle-decode-utils/issues"
"url": "https://github.com/trufflesuite/truffle-codec-utils/issues"
},
"homepage": "https://github.com/trufflesuite/truffle-decode-utils#readme",
"homepage": "https://github.com/trufflesuite/truffle-codec-utils#readme",
gnidan marked this conversation as resolved.
Show resolved Hide resolved
"publishConfig": {
"access": "public"
},
Expand All @@ -33,7 +32,9 @@
"@types/lodash.clonedeep": "^4.5.4",
"@types/lodash.escaperegexp": "^4.1.6",
"@types/semver": "^6.0.0",
"@types/web3": "^1.0.5",
"@types/web3": "^1.0.19",
"truffle-contract-schema": "^3.0.11",
"json-schema-to-typescript": "^6.1.3",
"typescript": "^3.5.1"
},
"gitHead": "b207efb3c1409746537293b3e0fc27350029188e"
Expand Down
174 changes: 174 additions & 0 deletions packages/truffle-codec-utils/src/abi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import debugModule from "debug";
const debug = debugModule("codec-utils:abi");

import { Abi as SchemaAbi } from "truffle-contract-schema/spec";
import { EVM as EVMUtils } from "./evm";
import { AstDefinition, AstReferences, Mutability } from "./ast";
import { Definition as DefinitionUtils } from "./definition";
import Web3 from "web3";

//NOTE: SchemaAbi is kind of loose and a pain to use.
//So we'll generally coerce things to Abi before use.
//(we combine this with adding a "function" tag for
//entries that lack it)

export namespace AbiUtils {

export type Abi = AbiEntry[];

export type AbiEntry = FunctionAbiEntry | ConstructorAbiEntry | FallbackAbiEntry | EventAbiEntry;

export interface FunctionAbiEntry {
type: "function";
name: string;
inputs: AbiParameter[];
outputs: AbiParameter[];
stateMutability?: Mutability; //only in newer ones
constant?: boolean; //only in older ones
payable?: boolean; //only in older ones
haltman-at marked this conversation as resolved.
Show resolved Hide resolved
}

export interface ConstructorAbiEntry {
type: "constructor";
inputs: AbiParameter[];
stateMutability?: "payable" | "nonpayable"; //only in newer ones
payable?: boolean; //only in older ones
}

export interface FallbackAbiEntry {
type: "fallback";
stateMutability?: "payable" | "nonpayable"; //only in newer ones
payable?: boolean; //only in older ones
}

export interface EventAbiEntry {
type: "event";
name: string;
inputs: AbiParameter[];
anonymous: boolean;
}

export interface AbiParameter {
name: string;
type: string;
indexed?: boolean; //only present for inputs
components?: AbiParameter[]; //only preset for tuples (structs)
}

export interface FunctionAbiBySelectors {
[selector: string]: FunctionAbiEntry
}

export function schemaAbiToAbi(abiLoose: SchemaAbi): Abi {
return abiLoose.map(
entry => entry.type
? <AbiEntry> entry
: <AbiEntry> {type: "function", ...entry}
);
}

//note the return value only includes functions!
export function computeSelectors(abi: Abi | undefined): FunctionAbiBySelectors | undefined {
if(abi === undefined) {
return undefined;
}
return Object.assign({},
...abi.filter(
(abiEntry: AbiEntry) => abiEntry.type === "function"
).map(
(abiEntry: FunctionAbiEntry) => ({ [abiSelector(abiEntry)]: abiEntry })
)
)
}

//does this ABI have a payable fallback function?
export function abiHasPayableFallback(abi: Abi | undefined): boolean | undefined {
if(abi === undefined) {
return undefined;
}
return abi.some(
(abiEntry: AbiEntry) =>
abiEntry.type === "fallback" && abiMutability(abiEntry) === "payable"
);
}

//shim for old abi versions
function abiMutability(abiEntry: FunctionAbiEntry | ConstructorAbiEntry | FallbackAbiEntry): Mutability {
if(abiEntry.stateMutability !== undefined) {
return abiEntry.stateMutability;
}
if(abiEntry.payable) {
return "payable";
}
if(abiEntry.type === "function" && abiEntry.constant) {
return "view";
}
return "nonpayable";
}

//NOTE: this function returns the written out SIGNATURE, not the SELECTOR
export function abiSignature(abiEntry: FunctionAbiEntry | EventAbiEntry): string {
return abiEntry.name + abiTupleSignature(abiEntry.inputs);
}

export function abiTupleSignature(parameters: AbiParameter[]): string {
let components = parameters.map(abiTypeSignature);
return "(" + components.join(",") + ")";
}

function abiTypeSignature(parameter: AbiParameter): string {
let tupleMatch = parameter.type.match(/tuple(.*)/);
if(tupleMatch === null) { //does not start with "tuple"
return parameter.type;
}
else {
let tail = tupleMatch[1]; //everything after "tuple"
let tupleSignature = abiTupleSignature(parameter.components);
return tupleSignature + tail;
}
}

export function abiSelector(abiEntry: FunctionAbiEntry | EventAbiEntry): string {
let signature = abiSignature(abiEntry);
//NOTE: web3's soliditySha3 has a problem if the empty
//string is passed in. Fortunately, that should never happen here.
let hash = Web3.utils.soliditySha3({type: "string", value: signature});
switch(abiEntry.type) {
case "event":
return hash;
case "function":
return hash.slice(0, 2 + 2 * EVMUtils.SELECTOR_SIZE); //arithmetic to account for hex string
}
}

//note: undefined does not match itself :P
export function abisMatch(entry1: AbiEntry | undefined, entry2: AbiEntry | undefined): boolean {
//we'll consider two abi entries to match if they have the same
//type, name (if applicable), and inputs (if applicable).
//since there's already a signature function, we can just use that.
if(!entry1 || !entry2) {
return false;
}
if(entry1.type !== entry2.type) {
return false;
}
switch(entry1.type) {
case "function":
case "event":
return abiSignature(entry1) === abiSignature(<FunctionAbiEntry|EventAbiEntry>entry2);
case "constructor":
return abiTupleSignature(entry1.inputs) === abiTupleSignature((<ConstructorAbiEntry>entry2).inputs);
case "fallback":
return true;
}
}

export function definitionMatchesAbi(abiEntry: AbiEntry, definition: AstDefinition, referenceDeclarations: AstReferences): boolean {
return abisMatch(abiEntry, DefinitionUtils.definitionToAbi(definition, referenceDeclarations));
}

export function topicsCount(abiEntry: EventAbiEntry): number {
let selectorCount = abiEntry.anonymous ? 0 : 1; //if the event is not anonymous, we must account for the selector
return abiEntry.inputs.filter(({ indexed }) => indexed).length + selectorCount;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ export interface AstDefinition {
//things
stateMutability?: Mutability;
referencedDeclaration?: any;
parameters?: {
parameters: AstDefinition[];
};
returnParameters?: {
parameters: AstDefinition[];
};
parameterTypes?: {
parameters: AstDefinition[];
};
Expand All @@ -39,6 +45,8 @@ export interface AstDefinition {
};
keyType?: AstDefinition;
valueType?: AstDefinition;
indexed?: boolean;
anonymous?: boolean;
contractKind?: ContractKind;
isConstructor?: boolean;
[k: string]: any;
Expand Down
6 changes: 6 additions & 0 deletions packages/truffle-codec-utils/src/compiler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface CompilerVersion {
name?: string;
version?: string;
//NOTE: both these should really be present,
//but they need to be optional for compilation reasons
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import BN from "bn.js";
export namespace Constants {
export const WORD_SIZE = 0x20;
export const ADDRESS_SIZE = 20;
export const SELECTOR_SIZE = 4;
export const SELECTOR_SIZE = 4; //function selectors, not event selectors
export const PC_SIZE = 4;
export const MAX_WORD = new BN(-1).toTwos(WORD_SIZE * 8);
export const ZERO_ADDRESS = "0x" + "00".repeat(ADDRESS_SIZE);
Expand Down
Loading