fix: fix for a strange issue with state changing for contract YLVpmhSq5JmLltfg6R-5fL04rIRPrlSU22f6RQ6VyYE

This commit is contained in:
ppedziwiatr
2021-08-26 15:37:00 +02:00
parent c1bfc38cf2
commit 354bc2e7db
17 changed files with 316 additions and 114 deletions

View File

@@ -13,6 +13,9 @@
],
"rules": {
"no-console": 1, // warning
"multiline-ternary": "off",
"no-nested-ternary": "error",
"no-multiple-empty-lines": "off",
"prettier/prettier": 2 // error
}
}

4
.gitignore vendored
View File

@@ -10,3 +10,7 @@ lib/
.idea/
.DS_Store
yarn-error.log
cache/
_scripts/**/*.json

78
_scripts/after.json Normal file
View File

@@ -0,0 +1,78 @@
{
"accounts": {
"regulator": {
"balance": 999.999,
"vaults": []
},
"Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs": {
"balance": 69.0005,
"vaults": [
{
"amount": 0.005,
"start": 649390,
"end": 650390
}
],
"stake": 69
},
"DfCXDjdxcTIg1-FQDZ5jDclk1shKIpMlshe0IXodApc": {
"balance": 69.0005,
"vaults": [],
"stake": 69
}
},
"executables": {
"Ms6RRl0eh96F_lcKYyiJhWRdRIiB6z0VaThCvBZDOAc": {
"_discriminator": "validated",
"bids": [
{
"bidder": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"quantity": 0.01
}
],
"caller": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"executable": {
"birth_height": 649382,
"executable_address": "is9cDN3ZKPun0F2KmEHnhiRuUcYOO3Dzfef-B5ZAQeQ",
"executable_kind": "wasm"
},
"accepted_bid": {
"bidder": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"quantity": 0.01
},
"validation_linked_list": {
"value": [
{
"_discriminator": "release",
"validator": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"encrypted_hash": "af8e9c76fc012934cd3009c0cb7cac697da634350aa7dd6a063ccc3fdbc533f815799ed08d72d06a84961e468cd2af3fec5549350ce582c74eea7c29e020acf052c3e619cc69aa98e6e5b43bd10574dce88bb204289891c97a535d1da69f32e0e42dd906159b47acb3d435679b9c61dc",
"symm_key": "sokka"
},
{
"_discriminator": "release",
"validator": "DfCXDjdxcTIg1-FQDZ5jDclk1shKIpMlshe0IXodApc",
"encrypted_hash": "af8e9c76fc012934cd3009c0cb7cac697da634350aa7dd6a063ccc3fdbc533f815799ed08d72d06a84961e468cd2af3fec5549350ce582c74eea7c29e020acf052c3e619cc69aa98e6e5b43bd10574dce88bb204289891c97a535d1da69f32e0e42dd906159b47acb3d435679b9c61dc",
"symm_key": "sokka"
}
]
},
"result": {
"address": "OTWNmd9aSARYg1X4ds8CwSVmx_dNYHb_ka-W2VAJ7NQ",
"giver": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"height": 649390
},
"is_correct": true
},
"Xstw2Ss9TMCkV92ozHTsvIDPsPXnMDZVzfKPTPxgAq0": {
"_discriminator": "proposed",
"bids": [],
"caller": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"executable": {
"birth_height": 649387,
"executable_address": "is9cDN3ZKPun0F2KmEHnhiRuUcYOO3Dzfef-B5ZAQeQ",
"executable_kind": "wasm"
}
}
},
"ticker": "FEA"
}

View File

@@ -1,60 +0,0 @@
/* eslint-disable */
import { LoggerFactory, SmartWeaveNodeFactory } from '@smartweave';
import Arweave from 'arweave';
import fs from 'fs';
import path from 'path';
async function main() {
const arweave = Arweave.init({
host: 'dh48zl0solow5.cloudfront.net', // Hostname or IP address for a Arweave host
port: 443, // Port
protocol: 'https', // Network protocol http or https
timeout: 60000, // Network request timeouts in milliseconds
logging: false // Enable network request logging
});
const logger = LoggerFactory.INST.create(__filename);
LoggerFactory.INST.logLevel('silly', 'benchmark');
const swcClient = SmartWeaveNodeFactory.fileCacheClient(arweave);
const contractTxId = 'OrO8n453N6bx921wtsEs-0OCImBLCItNU5oSbFKlFuU';
// Kyve:
// C_1uo08qRuQAeDi9Y1I8fkaWYUC9IWkOrKDNe9EphJo
// OFD4GqQcqp-Y_Iqh8DN_0s3a_68oMvvnekeOEu_a45I
// 8cq1wbjWHNiPg7GwYpoDT2m9HX99LY7tklRQWfh1L6c
const resultDiffs = [];
try {
/* console.log('readContract');
const result = await readContract(arweave, contractTxId);
const resultString = JSON.stringify(result);
console.log(resultString);
*/
const result2 = await swcClient.readState(contractTxId);
const result2String = JSON.stringify(result2.state);
logger.silly(result2String);
/* if (resultString.localeCompare(result2String) !== 0) {
console.error('\n\n ====== States differ ======\n\n');
resultDiffs.push(contractTxId);
const targetPath = path.join(__dirname, 'tests', contractTxId);
if (!fs.existsSync(targetPath)) {
fs.mkdirSync(targetPath);
}
fs.writeFileSync(path.join(targetPath, 'new.json'), result2String);
fs.writeFileSync(path.join(targetPath, 'old.json'), resultString);
}*/
const targetPath = path.join(__dirname, '../', 'tests', contractTxId);
if (!fs.existsSync(targetPath)) {
fs.mkdirSync(targetPath);
}
fs.writeFileSync(path.join(targetPath, 'new.json'), result2String);
logger.silly('Contracts with diff state:', resultDiffs);
} catch (e) {
logger.error(e);
logger.log('skipping ', contractTxId);
}
}
main();

View File

@@ -2,6 +2,7 @@
import Arweave from 'arweave';
import { SmartWeaveNodeFactory, LoggerFactory } from '@smartweave';
import fs from 'fs';
import { readContract } from 'smartweave';
const contracts = [
'gepLlre8wG8K3C15rNjpdKZZv_9pWsurRoEB6ir_EC4',
@@ -24,30 +25,13 @@ async function main() {
logging: false // Enable network request logging
});
LoggerFactory.INST.logLevel('debug');
const smartWeave = SmartWeaveNodeFactory.memCached(arweave);
const contract1 = smartWeave.contract('W_njBtwDRyltjVU1RizJtZfF0S_4X3aSrrrA0HUEhUs');
const contract2 = smartWeave.contract('TMkCZKYO3GwcTLEKGgWSJegIlYCHi_UArtG0unCi2xA');
await contract1.readState();
await contract2.readState();
const jwk = readJSON('../../redstone-node/.secrets/redstone-dev-jwk.json');
contract1.connect(jwk);
type Contract1Input = {
function: string;
};
type Contract1View = {
foo: string;
bar: number;
};
const { type, result } = await contract1.viewState<Contract1Input, Contract1View>({
function: 'currentManifest'
});
if (type === 'ok') {
console.log((result as Contract1View).foo);
}
const contract1 = smartWeave.contract('YLVpmhSq5JmLltfg6R-5fL04rIRPrlSU22f6RQ6VyYE');
//const contract2 = smartWeave.contract('TMkCZKYO3GwcTLEKGgWSJegIlYCHi_UArtG0unCi2xA');
const { state } = await contract1.readState();
//await contract2.readState();
const state2 = await readContract(arweave, 'YLVpmhSq5JmLltfg6R-5fL04rIRPrlSU22f6RQ6VyYE');
console.log;
}
function readJSON(path) {

View File

@@ -0,0 +1,92 @@
{
"accounts": {
"regulator": {
"balance": 1000,
"vaults": [
{
"amount": 0.0005,
"end": 650390,
"start": 649390
},
{
"amount": 0.0005,
"end": 650390,
"start": 649390
}
]
},
"Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs": {
"balance": 69,
"vaults": [
{
"amount": 0.01,
"start": 649388,
"end": 650388
},
{
"amount": 0.005,
"start": 649390,
"end": 650390
}
],
"stake": 69
},
"DfCXDjdxcTIg1-FQDZ5jDclk1shKIpMlshe0IXodApc": {
"balance": 69,
"vaults": [],
"stake": 69
}
},
"executables": {
"Ms6RRl0eh96F_lcKYyiJhWRdRIiB6z0VaThCvBZDOAc": {
"_discriminator": "result",
"bids": [
{
"bidder": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"quantity": 0.01
}
],
"caller": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"executable": {
"birth_height": 649382,
"executable_address": "is9cDN3ZKPun0F2KmEHnhiRuUcYOO3Dzfef-B5ZAQeQ",
"executable_kind": "wasm"
},
"accepted_bid": {
"bidder": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"quantity": 0.01
},
"validation_linked_list": {
"value": [
{
"_discriminator": "release",
"validator": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"encrypted_hash": "af8e9c76fc012934cd3009c0cb7cac697da634350aa7dd6a063ccc3fdbc533f815799ed08d72d06a84961e468cd2af3fec5549350ce582c74eea7c29e020acf052c3e619cc69aa98e6e5b43bd10574dce88bb204289891c97a535d1da69f32e0e42dd906159b47acb3d435679b9c61dc",
"symm_key": "sokka"
},
{
"_discriminator": "lock",
"validator": "DfCXDjdxcTIg1-FQDZ5jDclk1shKIpMlshe0IXodApc",
"encrypted_hash": "af8e9c76fc012934cd3009c0cb7cac697da634350aa7dd6a063ccc3fdbc533f815799ed08d72d06a84961e468cd2af3fec5549350ce582c74eea7c29e020acf052c3e619cc69aa98e6e5b43bd10574dce88bb204289891c97a535d1da69f32e0e42dd906159b47acb3d435679b9c61dc"
}
]
},
"result": {
"address": "OTWNmd9aSARYg1X4ds8CwSVmx_dNYHb_ka-W2VAJ7NQ",
"giver": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"height": 649390
}
},
"Xstw2Ss9TMCkV92ozHTsvIDPsPXnMDZVzfKPTPxgAq0": {
"_discriminator": "proposed",
"bids": [],
"caller": "Pq6OBljxlpypNuE0O1eL92Kr9U1Ok4USfcc0aJcUAzs",
"executable": {
"birth_height": 649387,
"executable_address": "is9cDN3ZKPun0F2KmEHnhiRuUcYOO3Dzfef-B5ZAQeQ",
"executable_kind": "wasm"
}
}
},
"ticker": "FEA"
}

View File

@@ -0,0 +1,54 @@
/* eslint-disable */
import { LoggerFactory, SmartWeaveNodeFactory } from '@smartweave';
import Arweave from 'arweave';
import fs from 'fs';
import path from 'path';
import { readContract } from 'smartweave';
async function main() {
const arweave = Arweave.init({
host: 'arweave.net', // Hostname or IP address for a Arweave host
port: 443, // Port
protocol: 'https', // Network protocol http or https
timeout: 60000, // Network request timeouts in milliseconds
logging: false // Enable network request logging
});
const logger = LoggerFactory.INST.create(__filename);
const smartWeave = SmartWeaveNodeFactory.memCached(arweave);
const contractTxId = 'YLVpmhSq5JmLltfg6R-5fL04rIRPrlSU22f6RQ6VyYE';
// Kyve:
// C_1uo08qRuQAeDi9Y1I8fkaWYUC9IWkOrKDNe9EphJo
// OFD4GqQcqp-Y_Iqh8DN_0s3a_68oMvvnekeOEu_a45I
// 8cq1wbjWHNiPg7GwYpoDT2m9HX99LY7tklRQWfh1L6c
const resultDiffs = [];
try {
logger.info('readContract');
const { state, validity } = await readContract(arweave, contractTxId, undefined, true);
logger.debug('readContract validity', validity);
const resultString = JSON.stringify(state);
logger.info('readState');
const result2 = await smartWeave.contract(contractTxId).readState();
logger.debug('readState validity', result2.validity);
const result2String = JSON.stringify(result2.state);
if (resultString.localeCompare(result2String) !== 0) {
console.error('\n\n ====== States differ ======\n\n');
resultDiffs.push(contractTxId);
const targetPath = path.join(__dirname, 'diffs', contractTxId);
if (!fs.existsSync(targetPath)) {
fs.mkdirSync(targetPath);
}
fs.writeFileSync(path.join(targetPath, 'new.json'), result2String);
fs.writeFileSync(path.join(targetPath, 'old.json'), resultString);
}
} catch (e) {
logger.error(e);
logger.info('skipping ', contractTxId);
}
}
main();

View File

@@ -32,7 +32,8 @@ query Transactions($tags: [TagFilter!]!, $after: String) {
}`;
const logger = LoggerFactory.INST.create(__filename);
LoggerFactory.INST.logLevel('silly', 'state-comparator');
// LoggerFactory.INST.logLevel('debug');
async function main() {
const arweave = Arweave.init({
@@ -45,13 +46,16 @@ async function main() {
const txs = loadTxFromFile();
logger.silly(`Checking ${txs.length} contracts`);
const resumeFromContractTxId = 'YLVpmhSq5JmLltfg6R-5fL04rIRPrlSU22f6RQ6VyYE';
let resumeFrom = true;
logger.info(`Checking ${txs.length} contracts`);
const differentStatesContractTxIds = [];
const errorContractTxIds = [];
const swcClient = SmartWeaveNodeFactory.fileCacheClient(arweave, 'cache');
const smartWeave = SmartWeaveNodeFactory.memCached(arweave);
const contractsBlacklist = [
'jFInOjLc_FFt802OmUObIIOlY1xNKvomzUTkoUpyP9U', // readContract very long evaluation
@@ -162,15 +166,13 @@ async function main() {
let counter = 0;
const resumeFromContractTxId = 'jFInOjLc_FFt802OmUObIIOlY1xNKvomzUTkoUpyP9U';
let resumeFrom = false;
for (const contractTxId of txs) {
const tx: Transaction = await arweave.transactions.get(contractTxId);
counter++;
logger.silly(`\n${contractTxId}: [${counter}/${txs.length}]`);
logger.info(`\n${contractTxId}: [${counter}/${txs.length}]`);
if (resumeFrom && contractTxId.localeCompare(resumeFromContractTxId) !== 0) {
console.info('Skipping...');
continue;
} else {
resumeFrom = false;
@@ -200,14 +202,14 @@ async function main() {
// console.log(resultString);
logger.info('readState');
const result2 = await swcClient.readState(contractTxId, null, null, {
ignoreExceptions: true
});
const result2 = await smartWeave.contract(contractTxId).readState();
const result2String = JSON.stringify(result2.state);
// console.log(result2String);
if (resultString.localeCompare(result2String) !== 0) {
logger.error('States differ!');
fs.writeFileSync(path.join(__dirname, 'diffs', `${contractTxId}_old.json`), resultString);
fs.writeFileSync(path.join(__dirname, 'diffs', `${contractTxId}_new.json`), result2String);
differentStatesContractTxIds.push(contractTxId);
}
} catch (e) {
@@ -215,7 +217,7 @@ async function main() {
logger.info('skipping ', contractTxId);
errorContractTxIds.push(contractTxId);
} finally {
logger.trace('Contracts with different states:', differentStatesContractTxIds);
logger.debug('Contracts with different states:', differentStatesContractTxIds);
logger.info('\n\n ==== END');
}
}
@@ -224,7 +226,7 @@ async function main() {
main().catch();
function loadTxFromFile(): string[] {
const transactions = JSON.parse(fs.readFileSync(path.join(__dirname, 'swc-sorted-stats.json'), 'utf-8'));
const transactions = JSON.parse(fs.readFileSync(path.join(__dirname, 'test-cases.json'), 'utf-8'));
return Object.keys(transactions);
}

View File

@@ -1,5 +1,6 @@
import { JWKInterface } from 'arweave/node/lib/wallet';
import {
Benchmark,
Contract,
ContractInteraction,
DefaultEvaluationOptions,
@@ -28,7 +29,9 @@ export class HandlerBasedContract<State> implements Contract<State> {
constructor(
private readonly contractTxId: string,
private readonly smartweave: SmartWeave,
private readonly parentContract: Contract = null
// note: this will be probably used for creating contract's
// call hierarchy and generating some sort of "stack trace"
private readonly callingContract: Contract = null
) {}
async readState(
@@ -36,11 +39,11 @@ export class HandlerBasedContract<State> implements Contract<State> {
currentTx?: { interactionTxId: string; contractTxId: string }[],
evaluationOptions?: EvaluationOptions
): Promise<EvalStateResult<State>> {
logger.info('Read state for %s', this.contractTxId);
logger.info('Read state for', this.contractTxId);
const { stateEvaluator } = this.smartweave;
const executionContext = await this.createExecutionContext(this.contractTxId, blockHeight, evaluationOptions);
const result = await stateEvaluator.eval(executionContext, currentTx || []);
const result = await stateEvaluator.eval(executionContext, currentTx || []);
return result as EvalStateResult<State>;
}
@@ -53,7 +56,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
throw new Error("Wallet not connected. Use 'connect' method first.");
}
logger.info('View state for %s', this.contractTxId);
logger.info('View state for', this.contractTxId);
const { arweave, stateEvaluator } = this.smartweave;
let executionContext = await this.createExecutionContext(this.contractTxId, blockHeight, evaluationOptions);
@@ -111,7 +114,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
transaction: InteractionTx,
evaluationOptions?: EvaluationOptions
): Promise<InteractionResult<State, View>> {
logger.info('Vies state for %s %o', this.contractTxId, transaction);
logger.info(`Vies state for ${this.contractTxId}`, transaction);
const { stateEvaluator } = this.smartweave;
const executionContext = await this.createExecutionContextFromTx(this.contractTxId, transaction);
@@ -139,6 +142,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
blockHeight?: number,
evaluationOptions?: EvaluationOptions
): Promise<ExecutionContext<State>> {
const benchmark = Benchmark.measure();
const { arweave, definitionLoader, interactionsLoader, interactionsSorter } = this.smartweave;
let currentNetworkInfo;
@@ -158,6 +162,8 @@ export class HandlerBasedContract<State> implements Contract<State> {
const interactions = await interactionsLoader.load(contractTxId, blockHeight);
const sortedInteractions = await interactionsSorter.sort(interactions);
logger.debug('Creating execution context:', benchmark.elapsed());
return {
contractDefinition,
blockHeight,
@@ -175,7 +181,8 @@ export class HandlerBasedContract<State> implements Contract<State> {
transaction: InteractionTx,
evaluationOptions?: EvaluationOptions
): Promise<ExecutionContext<State>> {
const { definitionLoader, executorFactory, interactionsLoader, interactionsSorter } = this.smartweave;
const benchmark = Benchmark.measure();
const { definitionLoader, interactionsLoader, interactionsSorter } = this.smartweave;
const blockHeight = transaction.block.height;
const caller = transaction.owner.address;
const contractDefinition = await definitionLoader.load<State>(contractTxId);
@@ -185,6 +192,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
if (evaluationOptions == null) {
evaluationOptions = new DefaultEvaluationOptions();
}
logger.debug('Creating execution context from tx:', benchmark.elapsed());
return {
contractDefinition,

View File

@@ -10,7 +10,12 @@ import Arweave from 'arweave';
import { Contract, HandlerBasedContract, SmartWeaveBuilder } from '@smartweave/contract';
/**
* The "motherboard" ;-)
* The SmartWeave "motherboard" ;-).
* This is the base class that supplies the implementation of the SmartWeave SDK.
* Allows to plug-in different implementation of all parts defined in its constructors.
*
* After being fully configured, it allows to "connect" to
* contract and perform operations on them (see {@link Contract})
*/
export class SmartWeave {
constructor(
@@ -18,7 +23,7 @@ export class SmartWeave {
readonly definitionLoader: DefinitionLoader,
readonly interactionsLoader: InteractionsLoader,
readonly interactionsSorter: InteractionsSorter,
readonly executorFactory: ExecutorFactory<HandlerApi<unknown>>,
readonly executorFactory: ExecutorFactory<HandlerApi<unknown>>, // TODO: really struggling with TS generics here...
readonly stateEvaluator: StateEvaluator
) {}
@@ -26,7 +31,7 @@ export class SmartWeave {
return new SmartWeaveBuilder(arweave);
}
contract<State>(contractTxId: string, parent?: Contract): Contract<State> {
return new HandlerBasedContract<State>(contractTxId, this, parent);
contract<State>(contractTxId: string, callingContract?: Contract): Contract<State> {
return new HandlerBasedContract<State>(contractTxId, this, callingContract);
}
}

View File

@@ -1,4 +1,12 @@
import { ContractDefinition, DefinitionLoader, getTag, LoggerFactory, SmartWeaveTags, SwCache } from '@smartweave';
import {
Benchmark,
ContractDefinition,
DefinitionLoader,
getTag,
LoggerFactory,
SmartWeaveTags,
SwCache
} from '@smartweave';
import Arweave from 'arweave';
import Transaction from 'arweave/web/lib/transaction';
@@ -32,7 +40,6 @@ export class ContractDefinitionLoader implements DefinitionLoader {
const minFee = getTag(contractTx, SmartWeaveTags.MIN_FEE);
const contractSrcTx = await this.arweave.transactions.get(contractSrcTxId);
const src = contractSrcTx.get('data', { decode: true, string: true });
const initState = JSON.parse(await this.evalInitialState(contractTx));
return {

View File

@@ -15,6 +15,8 @@ import {
StateEvaluator
} from '@smartweave';
import Arweave from 'arweave';
import fs from 'fs';
import path from 'path';
const logger = LoggerFactory.INST.create(__filename);
@@ -43,6 +45,7 @@ export class DefaultStateEvaluator implements StateEvaluator {
executionContext: ExecutionContext<State>,
currentTx: { interactionTxId: string; contractTxId: string }[]
): Promise<EvalStateResult<State>> {
const stateEvaluationBenchmark = Benchmark.measure();
const evaluationOptions = executionContext.evaluationOptions;
let currentState = baseState.state;
@@ -56,13 +59,22 @@ export class DefaultStateEvaluator implements StateEvaluator {
executionContext.contractDefinition
)) as HandlerApi<State>;
logger.debug(
'missingInteractions',
missingInteractions.map((int) => {
return int.node.id;
})
);
logger.debug('Init state', JSON.stringify(baseState.state));
for (const missingInteraction of missingInteractions) {
logger.debug(
`${missingInteraction.node.id}: ${missingInteractions.indexOf(missingInteraction) + 1}/${
missingInteractions.length
} [of all:${executionContext.sortedInteractions.length}]`
);
const benchmark = Benchmark.measure();
const singleInteractionBenchmark = Benchmark.measure();
const currentInteraction: GQLNodeInterface = missingInteraction.node;
const inputTag = this.findInputTag(missingInteraction, executionContext);
@@ -91,18 +103,23 @@ export class DefaultStateEvaluator implements StateEvaluator {
}
validity[currentInteraction.id] = result.type === 'ok';
currentState = result.state;
logger.debug(`${missingInteraction.node.id} evaluation`, benchmark.elapsed());
// I'm really NOT a fan of this "modify" feature, but I don't have idea how to better
// implement the "evolve" feature
for (const { modify } of this.executionContextModifiers) {
// strangely - state is for some reason modified for some contracts (eg. YLVpmhSq5JmLltfg6R-5fL04rIRPrlSU22f6RQ6VyYE)
// when calling any async (even simple timeout) function here...
// that's a dumb workaround for this issue
const stateCopy = JSON.parse(JSON.stringify(currentState));
executionContext = await modify(currentState, executionContext);
currentState = stateCopy;
}
this.onStateUpdate<State>(currentInteraction, executionContext, new EvalStateResult(currentState, validity));
}
console.debug('State evaluation total:', stateEvaluationBenchmark.elapsed());
return new EvalStateResult<State>(currentState, validity);
}

View File

@@ -28,6 +28,8 @@ const logger = LoggerFactory.INST.create(__filename);
/**
* A factory that produces handlers that are compatible with the "current" style of
* writing SW contracts (ie. using "handle" function).
* Note: this code is mostly ported from the previous version of the SDK and is somewhat messy...
* First candidate for the refactor!
*/
export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknown>> {
constructor(private readonly arweave: Arweave) {}
@@ -105,7 +107,7 @@ export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknow
to: contractTxId,
input
});
const childContract = executionContext.smartweave.contract(contractTxId);
const childContract = executionContext.smartweave.contract(contractTxId, executionContext.contract);
return await childContract.viewStateForTx(input, swGlobal._activeTx);
};
@@ -123,7 +125,7 @@ export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknow
to: contractTxId
});
const requestedHeight = height || swGlobal.block.height;
const childContract = executionContext.smartweave.contract(contractTxId);
const childContract = executionContext.smartweave.contract(contractTxId, executionContext.contract);
const stateWithValidity = await childContract.readState(requestedHeight, [
...(currentTx || []),
@@ -137,6 +139,7 @@ export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknow
// (by simply using destructuring operator)...
// but this (i.e. returning always stateWithValidity from here) would break backwards compatibility
// in current contract's source code..:/
return returnValidity ? stateWithValidity : stateWithValidity.state;
};
}

View File

@@ -3,6 +3,10 @@ export class Benchmark {
return new Benchmark();
}
private constructor() {
// noop
}
private start = Date.now();
public reset() {

View File

@@ -6,7 +6,8 @@ export const defaultLoggerOptions: ISettingsParam = {
displayFunctionName: false,
displayFilePath: 'hideNodeModulesOnly',
displayLoggerName: false,
dateTimeTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone
dateTimeTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
minLevel: 'debug'
};
/**

View File

@@ -54,7 +54,7 @@ export class Evolve implements ExecutionContextModifier {
const contractTxId = executionContext.contractDefinition.txId;
logger.debug(`trying to evolve for: ${contractTxId}`);
if (!isEvolveCompatible(state)) {
logger.verbose('State is not evolve compatible');
logger.debug('State is not evolve compatible');
return executionContext;
}
const currentSrcTxId = executionContext.contractDefinition.srcTxId;