From 6abe3d6448244100d15b63d7da2aab37715c6c79 Mon Sep 17 00:00:00 2001 From: kiruse <26940742+Kiruse@users.noreply.github.com> Date: Tue, 10 Jan 2023 21:42:41 +0100 Subject: [PATCH] add missing error traces on instantiate & execute --- src/modules/wasm.spec.ts | 55 ++++++++++++- src/modules/wasm/module.ts | 161 ++++++++++++++++++------------------- 2 files changed, 131 insertions(+), 85 deletions(-) diff --git a/src/modules/wasm.spec.ts b/src/modules/wasm.spec.ts index 50a9c57..175164f 100644 --- a/src/modules/wasm.spec.ts +++ b/src/modules/wasm.spec.ts @@ -1,6 +1,6 @@ import { Coin } from '@cosmjs/amino'; import { toAscii, toBase64 } from '@cosmjs/encoding'; -import { Result } from 'ts-results'; +import { Err, Result } from 'ts-results'; import { cmd, exec, TestContract, TestContractInstance } from '../../testing/wasm-util'; import { CWSimulateApp } from '../CWSimulateApp'; import { AppResponse, Event, ReplyOn, TraceLog } from '../types'; @@ -486,6 +486,59 @@ describe('TraceLog', () => { }, ]); }); + + it('traces errors', async () => { + const trace: TraceLog[] = []; + + const executeMsg1 = { + run: { failure: true } + }; + await testContract.execute( + info.sender, + executeMsg1, + [], + trace, + ); + + const err1 = { ok: false, err: true }; + const ref1 = { + type: 'execute', + contractAddress: testContract.address, + msg: executeMsg1, + info: { + sender: info.sender, + funds: [], + }, + response: err1, + result: err1, + }; + expect(trace).toMatchObject([ ref1 ]); + + const funds = [{ denom: 'uluna', amount: '99999999999999999999' }]; + const executeMsg2 = { + debug: { msg: 'foobar' } + }; + await testContract.execute( + info.sender, + executeMsg2, + funds, + trace, + ); + + const err2 = { ok: false, err: true }; + const ref2 = { + type: 'execute', + contractAddress: testContract.address, + msg: executeMsg2, + info: { + sender: info.sender, + funds, + }, + response: err2, + result: err2, + }; + expect(trace).toMatchObject([ ref1, ref2 ]); + }); }); describe('Query', () => { diff --git a/src/modules/wasm/module.ts b/src/modules/wasm/module.ts index 8d0a163..30e4cf6 100644 --- a/src/modules/wasm/module.ts +++ b/src/modules/wasm/module.ts @@ -1,6 +1,8 @@ import { toBech32 } from '@cosmjs/encoding'; +import { Map } from 'immutable'; +import { Err, Ok, Result } from 'ts-results'; import type { CWSimulateApp } from '../../CWSimulateApp'; - +import { NEVER_IMMUTIFY, Transactional, TransactionalLens } from '../../store/transactional'; import { AppResponse, Binary, @@ -11,19 +13,18 @@ import { ContractResponse, Event, ExecuteEnv, + ExecuteTraceLog, ReplyMsg, ReplyOn, + ReplyTraceLog, SubMsg, TraceLog, DebugLog, Snapshot, } from '../../types'; -import { Map } from 'immutable'; -import { Err, Ok, Result } from 'ts-results'; import { fromBinary, toBinary } from '../../util'; -import { NEVER_IMMUTIFY, Transactional, TransactionalLens } from '../../store/transactional'; -import { buildAppResponse, buildContractAddress } from './wasm-util'; import Contract from './contract'; +import { buildAppResponse, buildContractAddress } from './wasm-util'; type WasmData = { lastCodeId: number; @@ -209,16 +210,31 @@ export class WasmModule { trace: TraceLog[] = [] ): Promise> { return await this.chain.pushBlock(async () => { - const snapshot = this.store.db.data; - // first register the contract instance const contractAddress = this.registerContractInstance(sender, codeId, label).unwrap(); let logs = [] as DebugLog[]; const contract = await this.getContract(contractAddress).init(); + const tracebase: Omit = { + [NEVER_IMMUTIFY]: true, + type: 'instantiate', + contractAddress, + msg: instantiateMsg, + info: { sender, funds }, + logs, + env: contract.getExecutionEnv(), + storeSnapshot: this.store.db.data, + } const send = this.chain.bank.send(sender, contract.address, funds); - if (send.err) return send; + if (send.err) { + trace.push({ + ...tracebase, + response: send, + result: send, + }); + return send; + } // then call instantiate let response = contract.instantiate( @@ -229,23 +245,12 @@ export class WasmModule { ); if (response.err) { - let result = Err(response.val); trace.push({ - [NEVER_IMMUTIFY]: true, - type: 'instantiate' as 'instantiate', - contractAddress, - msg: instantiateMsg, + ...tracebase, response, - info: { - sender, - funds, - }, - env: this.getExecutionEnv(contractAddress), - logs, - storeSnapshot: snapshot, - result, + result: response, }); - return result; + return response; } else { let customEvent: Event = { @@ -271,20 +276,11 @@ export class WasmModule { ); trace.push({ - [NEVER_IMMUTIFY]: true, - type: 'instantiate' as 'instantiate', - contractAddress, - msg: instantiateMsg, + ...tracebase, response, - info: { - sender, - funds, - }, - env: this.getExecutionEnv(contractAddress), - logs, + result, trace: subtrace, storeSnapshot: this.store.db.data, - result, }); return result; @@ -301,13 +297,29 @@ export class WasmModule { trace: TraceLog[] = [] ): Promise> { return await this.chain.pushBlock(async () => { - const snapshot = this.store.db.data; const contract = await this.getContract(contractAddress).init(); - const env = contract.getExecutionEnv(); const logs: DebugLog[] = []; + + const tracebase: Omit = { + [NEVER_IMMUTIFY]: true, + type: 'execute', + contractAddress, + msg: executeMsg, + logs, + env: contract.getExecutionEnv(), + info: { sender, funds }, + storeSnapshot: this.store.db.data, + } const send = this.chain.bank.send(sender, contractAddress, funds); - if (send.err) return send; + if (send.err) { + trace.push({ + ...tracebase, + response: send, + result: send, + }); + return send; + } const response = contract.execute( sender, @@ -317,25 +329,12 @@ export class WasmModule { ); if (response.err) { - const result = Err(response.val); - trace.push({ - [NEVER_IMMUTIFY]: true, - type: 'execute' as 'execute', - contractAddress, - msg: executeMsg, + ...tracebase, response, - env, - info: { - sender, - funds, - }, - logs, - storeSnapshot: snapshot, - result, + result: response, }); - - return result; + return response; } else { let customEvent = { @@ -363,20 +362,11 @@ export class WasmModule { ); trace.push({ - [NEVER_IMMUTIFY]: true, - type: 'execute' as 'execute', - contractAddress, - msg: executeMsg, + ...tracebase, response, - info: { - sender, - funds, - }, - env, + result, trace: subtrace, - logs, storeSnapshot: this.store.db.data, - result, }); return result; @@ -490,25 +480,25 @@ export class WasmModule { ): Promise> { const logs: DebugLog[] = []; const contract = this.getContract(contractAddress); - const env = contract.getExecutionEnv(); const response = contract.reply(replyMsg, logs); + const tracebase: Omit = { + [NEVER_IMMUTIFY]: true, + type: 'reply', + contractAddress, + msg: replyMsg, + env: contract.getExecutionEnv(), + logs, + storeSnapshot: this.store.db.data, + } + if (response.err) { - const result = Err(response.val); - trace.push({ - [NEVER_IMMUTIFY]: true, - type: 'reply' as 'reply', - contractAddress, - env, - msg: replyMsg, + ...tracebase, response, - logs, - storeSnapshot: this.store.db.data, - result, + result: response, }); - - return result; + return response; } else { const customEvent = { @@ -541,16 +531,10 @@ export class WasmModule { ); trace.push({ - [NEVER_IMMUTIFY]: true, - type: 'reply' as 'reply', - contractAddress, - msg: replyMsg, - env, + ...tracebase, response, - trace: subtrace, - logs, - storeSnapshot: this.store.db.data, result, + storeSnapshot: this.store.db.data, }); return result; @@ -659,6 +643,15 @@ export class WasmModule { return storage ? lensFromSnapshot(storage) : this.store; } + protected pushTrace(traces: TraceLog[], details: Omit) { + //@ts-ignore + traces.push({ + [NEVER_IMMUTIFY]: true, + ...details, + env: this.getExecutionEnv(details.contractAddress), + }); + } + get lastCodeId() { return this.store.get('lastCodeId') } get lastInstanceId() { return this.store.get('lastInstanceId') } }