fix: fix for a strange issue with state changing for contract YLVpmhSq5JmLltfg6R-5fL04rIRPrlSU22f6RQ6VyYE
This commit is contained in:
@@ -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
4
.gitignore
vendored
@@ -10,3 +10,7 @@ lib/
|
||||
.idea/
|
||||
|
||||
.DS_Store
|
||||
|
||||
yarn-error.log
|
||||
cache/
|
||||
_scripts/**/*.json
|
||||
|
||||
78
_scripts/after.json
Normal file
78
_scripts/after.json
Normal 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"
|
||||
}
|
||||
@@ -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();
|
||||
@@ -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) {
|
||||
|
||||
92
_scripts/output/new/____init.json
Normal file
92
_scripts/output/new/____init.json
Normal 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"
|
||||
}
|
||||
54
_scripts/single-state-comparator.ts
Normal file
54
_scripts/single-state-comparator.ts
Normal 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();
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@ export class Benchmark {
|
||||
return new Benchmark();
|
||||
}
|
||||
|
||||
private constructor() {
|
||||
// noop
|
||||
}
|
||||
|
||||
private start = Date.now();
|
||||
|
||||
public reset() {
|
||||
|
||||
@@ -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'
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user