diff --git a/src/core/KnownTags.ts b/src/core/KnownTags.ts index 78de6b9..d980963 100644 --- a/src/core/KnownTags.ts +++ b/src/core/KnownTags.ts @@ -22,7 +22,8 @@ export const WARP_TAGS = { SEQUENCER_OWNER: 'Sequencer-Owner', SEQUENCER_MILLIS: 'Sequencer-Mills', SEQUENCER_SORT_KEY: 'Sequencer-Sort-Key', - SEQUENCER_LAST_SORT_KEY: 'Sequencer-Last-Sort-Key', + SEQUENCER_PREV_SORT_KEY: 'Sequencer-Prev-Sort-Key', + SEQUENCER_LAST_SORT_KEY: 'Sequencer-Last-Sort-Key', // deprecated SEQUENCER_TX_ID: 'Sequencer-Tx-Id', SEQUENCER_BLOCK_HEIGHT: 'Sequencer-Block-Height', SEQUENCER_BLOCK_ID: 'Sequencer-Block-Id', diff --git a/src/core/modules/impl/ArweaveGatewayBundledInteractionLoader.ts b/src/core/modules/impl/ArweaveGatewayBundledInteractionLoader.ts index c513e55..e60ba21 100644 --- a/src/core/modules/impl/ArweaveGatewayBundledInteractionLoader.ts +++ b/src/core/modules/impl/ArweaveGatewayBundledInteractionLoader.ts @@ -1,5 +1,5 @@ import Arweave from 'arweave'; -import { SMART_WEAVE_TAGS } from '../../KnownTags'; +import { SMART_WEAVE_TAGS, WARP_TAGS, WarpTags } from '../../KnownTags'; import { GQLEdgeInterface, GQLNodeInterface } from '../../../legacy/gqlResult'; import { Benchmark } from '../../../logging/Benchmark'; import { LoggerFactory } from '../../../logging/LoggerFactory'; @@ -7,11 +7,10 @@ import { ArweaveWrapper } from '../../../utils/ArweaveWrapper'; import { GW_TYPE, InteractionsLoader } from '../InteractionsLoader'; import { InteractionsSorter } from '../InteractionsSorter'; import { EvaluationOptions } from '../StateEvaluator'; -import { LexicographicalInteractionsSorter } from './LexicographicalInteractionsSorter'; +import { defaultArweaveMs, LexicographicalInteractionsSorter } from './LexicographicalInteractionsSorter'; import { Warp, WarpEnvironment } from '../../Warp'; import { Tag } from 'utils/types/arweave-types'; import { ArweaveGQLTxsFetcher } from './ArweaveGQLTxsFetcher'; -import { WarpTags, WARP_TAGS } from '../../KnownTags'; import { safeParseInt } from '../../../utils/utils'; import { VrfPluginFunctions, WarpPlugin } from '../../WarpPlugin'; import { TagsParser } from './TagsParser'; @@ -40,6 +39,9 @@ export interface GqlReqVariables { after?: string; } +// a height from which the last sort key value is being set by the sequencer +const LAST_SORT_KEY_MIN_HEIGHT = 1057409; + export class ArweaveGatewayBundledInteractionLoader implements InteractionsLoader { private readonly logger = LoggerFactory.INST.create(ArweaveGatewayBundledInteractionLoader.name); @@ -73,6 +75,10 @@ export class ArweaveGatewayBundledInteractionLoader implements InteractionsLoade { name: SMART_WEAVE_TAGS.CONTRACT_TX_ID, values: [contractId] + }, + { + name: WARP_TAGS.SEQUENCER, + values: ['RedStone'] } ], blockFilter: { @@ -131,8 +137,21 @@ export class ArweaveGatewayBundledInteractionLoader implements InteractionsLoade const prevInteraction = allInteractions[index - 1]; const nextInteraction = allInteractions[index]; - if (prevInteraction.node.sortKey !== nextInteraction.node.lastSortKey) { - throw Error( + this.logger.debug(`prev: ${prevInteraction.node.id} | current: ${nextInteraction.node.id}`); + + if (nextInteraction.node.block.height <= LAST_SORT_KEY_MIN_HEIGHT) { + return interaction; + } + if (nextInteraction.node.lastSortKey?.split(',')[1] === defaultArweaveMs) { + // cannot verify this one + return interaction; + } + + if ( + prevInteraction.node.source === 'redstone-sequencer' && + prevInteraction.node.sortKey !== nextInteraction.node.lastSortKey + ) { + this.logger.warn( `Interaction loading error: interaction ${nextInteraction.node.id} lastSortKey is not pointing on prev interaction ${prevInteraction.node.id}` ); } @@ -157,20 +176,26 @@ export class ArweaveGatewayBundledInteractionLoader implements InteractionsLoade private attachSequencerDataToInteraction(interaction: GQLEdgeInterface): GQLEdgeInterface { const extractTag = (tagName: WarpTags) => interaction.node.tags.find((tag: Tag) => tag.name === tagName)?.value; + + const sequencerTxId = extractTag(WARP_TAGS.SEQUENCER_TX_ID); + const sequencerOwner = extractTag(WARP_TAGS.SEQUENCER_OWNER); const sequencerBlockId = extractTag(WARP_TAGS.SEQUENCER_BLOCK_ID); const sequencerBlockHeight = extractTag(WARP_TAGS.SEQUENCER_BLOCK_HEIGHT); - const sequencerLastSortKey = extractTag(WARP_TAGS.SEQUENCER_LAST_SORT_KEY); + const sequencerLastSortKey = + extractTag(WARP_TAGS.SEQUENCER_PREV_SORT_KEY) || extractTag(WARP_TAGS.SEQUENCER_LAST_SORT_KEY); const sequencerSortKey = extractTag(WARP_TAGS.SEQUENCER_SORT_KEY); - const sequencerTxId = extractTag(WARP_TAGS.SEQUENCER_TX_ID); // this field was added in sequencer from 15.03.2023 const sequencerBlockTimestamp = extractTag(WARP_TAGS.SEQUENCER_BLOCK_TIMESTAMP); + const parsedBlockHeight = safeParseInt(sequencerBlockHeight); + if ( !sequencerOwner || !sequencerBlockId || !sequencerBlockHeight || - !sequencerLastSortKey || + // note: old sequencer transactions do not have last sort key set + (!sequencerLastSortKey && parsedBlockHeight > LAST_SORT_KEY_MIN_HEIGHT) || !sequencerTxId || !sequencerSortKey ) { diff --git a/src/core/modules/impl/LexicographicalInteractionsSorter.ts b/src/core/modules/impl/LexicographicalInteractionsSorter.ts index 2463be3..1ffcfae 100644 --- a/src/core/modules/impl/LexicographicalInteractionsSorter.ts +++ b/src/core/modules/impl/LexicographicalInteractionsSorter.ts @@ -7,7 +7,7 @@ import { InteractionsSorter } from '../InteractionsSorter'; // note: this (i.e. padding to 13 digits) should be safe between years ~1966 and ~2286 const firstSortKeyMs = ''.padEnd(13, '0'); const lastSortKeyMs = ''.padEnd(13, '9'); -const defaultArweaveMs = ''.padEnd(13, '0'); +export const defaultArweaveMs = ''.padEnd(13, '0'); export const sortingFirst = ''.padEnd(64, '0'); export const sortingLast = ''.padEnd(64, 'z'); diff --git a/tools/stamp_state.ts b/tools/stamp_state.ts new file mode 100644 index 0000000..7829d7d --- /dev/null +++ b/tools/stamp_state.ts @@ -0,0 +1,47 @@ +/* eslint-disable */ +import Arweave from 'arweave'; +import { + ArweaveGatewayBundledContractDefinitionLoader, + ArweaveGatewayBundledInteractionLoader, + defaultCacheOptions, + WarpFactory +} from '../src'; + +const arweave = Arweave.init({ + host: 'arweave.net', + port: 443, + protocol: 'https', + timeout: 200000 +}); + +const arContractLoader = new ArweaveGatewayBundledContractDefinitionLoader('mainnet'); +const arInteractionLoader = new ArweaveGatewayBundledInteractionLoader(arweave, 'mainnet'); +const contractId = 'TlqASNDLA1Uh8yFiH-BzR_1FDag4s735F3PoUFEv2Mo'; +const warp = WarpFactory.custom( + arweave, + { + ...defaultCacheOptions, + inMemory: true + }, + 'mainnet' +) + .useArweaveGateway() + .setInteractionsLoader(arInteractionLoader) + .setDefinitionLoader(arContractLoader) + .build(); + +const c = warp.contract(contractId).setEvaluationOptions({ + allowBigInt: true, + unsafeClient: 'skip' +}); + +async function getState() { + try { + const { sortKey, cachedValue } = await c.readState(); + console.log(sortKey, cachedValue.errorMessages, cachedValue.state, cachedValue.validity); + } catch (error) { + console.log('readState error:', error, 'contractId:', contractId); + } +} + +getState(); diff --git a/tools/wallet.js b/tools/wallet.js new file mode 100644 index 0000000..3e3d59e --- /dev/null +++ b/tools/wallet.js @@ -0,0 +1,14 @@ +const Arweave = require("arweave"); + +const arweave = Arweave.init({ + host: "arweave.net", + port: 443, + protocol: "https", +}); +const wallet = arweave.wallets.generate() + .then(w => { + arweave.wallets.jwkToAddress(w).then((address) => { + console.log(address); + //1seRanklLU_1VTGkEk7P0xAwMJfA7owA1JHW5KyZKlY + }); + });