This commit is contained in:
Alex 2025-05-07 08:02:55 +03:00
parent 84ff2837eb
commit e9025efa22
15 changed files with 113 additions and 54 deletions

View File

@ -1,14 +1,20 @@
import { constructClaim } from '@coinweb/contract-kit'; import { constructClaim } from '@coinweb/contract-kit';
import { cwait, readOp, storeOp, TypedClaim } from 'cwait'; import { cwait, lock, readOp, storeOp, TypedClaim } from 'cwait';
import { createWordKey, WordClaimBody } from '../offchain'; import { createWordKey, WordClaimBody } from '../offchain';
import { extraLogic2 } from './extraLogic2'; import { extraLogic2 } from './extraLogic2';
export const extraLogic = cwait(async (id: string, i: number) => { export const extraLogic = cwait(async (id: string, i: number) => {
console.log('extraLogic START + ', i); console.log('extraLogic START ++ ', i);
console.log('extraLogic lock + ', i);
const unlock = await lock(createWordKey(id));
console.log('extraLogic readOp + ', i);
const result = await readOp<TypedClaim<WordClaimBody>>(createWordKey(id)); const result = await readOp<TypedClaim<WordClaimBody>>(createWordKey(id));
console.log('extraLogic storeOp + ', i);
await storeOp( await storeOp(
constructClaim( constructClaim(
createWordKey(id), createWordKey(id),
@ -17,6 +23,9 @@ export const extraLogic = cwait(async (id: string, i: number) => {
) )
); );
console.log('extraLogic unlock + ', i);
await unlock();
console.log('extraLogic return extraLogic2 + ', i); console.log('extraLogic return extraLogic2 + ', i);
return extraLogic2(id, i); return extraLogic2(id, i);
}); });

View File

@ -12,7 +12,6 @@ import { getCallParameters, getContractIssuer } from 'lib/onchain';
import { ExecutorMethodArgs, ResolvedOp } from '../../types'; import { ExecutorMethodArgs, ResolvedOp } from '../../types';
import { pushAwaitedTask } from '../promisifiedFeatures'; import { pushAwaitedTask } from '../promisifiedFeatures';
import { uuid } from '../utils';
import { extractOps } from './extractOps'; import { extractOps } from './extractOps';
@ -65,7 +64,9 @@ export const handleContext = (ctx: Context) => {
] = getMethodArgs(); ] = getMethodArgs();
initialContext.isChild = !!parentId; initialContext.isChild = !!parentId;
initialContext.thisId = thisId ?? uuid(); initialContext.thisId =
thisId ??
(BigInt(`0x${parentId ?? '0'}`) * 3n + BigInt(`0x${getRawContext().call.txid}`)).toString(16).slice(0, 32);
initialContext.parentId = parentId; initialContext.parentId = parentId;
initialContext.methodName = methodName; initialContext.methodName = methodName;
initialContext.initialArgs = initialArgs ?? []; initialContext.initialArgs = initialArgs ?? [];

View File

@ -3,7 +3,13 @@ import { CwebTake } from '@coinweb/contract-kit/dist/types/operations/take';
import { ResolvedOp, TypedClaim } from '../../types'; import { ResolvedOp, TypedClaim } from '../../types';
import { resultKey } from '../claims'; import { resultKey } from '../claims';
import { mutexBlockLockKey, mutexBlockUnlockKey, mutexExecOpsKey, MutexExecOpsResult } from '../mutex'; import {
mutexBlockLockKey,
mutexBlockUnlockKey,
mutexExecOpsKey,
MutexExecOpsResult,
MutexNotifyLockState,
} from '../mutex';
import { isResolvedBlockOp, isResolvedReadOp, isResolvedTakeOp } from '../utils'; import { isResolvedBlockOp, isResolvedReadOp, isResolvedTakeOp } from '../utils';
const extractFunds = (fundsOp: GRead<ResolvedRead>, takenFundsIds: string[]) => { const extractFunds = (fundsOp: GRead<ResolvedRead>, takenFundsIds: string[]) => {
@ -92,7 +98,9 @@ export const extractOps = ({
throw new Error('Wrong mutex lock result'); throw new Error('Wrong mutex lock result');
} }
extractedOps.push({ SlotOp: { ok: true } }); extractedOps.push({
LockOp: nextAfterBlock.TakeOp.result.body as MutexNotifyLockState,
});
i += 2; i += 2;
continue; continue;

View File

@ -1,10 +1,23 @@
import { ContractIssuer, constructContractRef } from '@coinweb/contract-kit'; import { ContractIssuer, constructContractRef } from '@coinweb/contract-kit';
import { constructMutexBlockLockClaimTake, constructMutexLockBlock } from '../claims'; import { constructMutexBlockLockClaimTake, constructMutexLockBlock, constructMutexLockClaimStore } from '../claims';
import { lockMethodName } from '../methods'; import { lockMethodName } from '../methods';
import { lockFee } from '../settings'; import { lockFee } from '../settings';
import { LockedKey } from '../types';
export const constructLockCall = (issuer: ContractIssuer, lockId: string) => { export const constructLockCall = ({
issuer,
keys,
lockId,
timestamp,
processId,
}: {
issuer: ContractIssuer;
lockId: string;
timestamp: number;
keys: LockedKey[];
processId: string;
}) => {
return { return {
callInfo: { callInfo: {
ref: constructContractRef(issuer, []), ref: constructContractRef(issuer, []),
@ -18,7 +31,10 @@ export const constructLockCall = (issuer: ContractIssuer, lockId: string) => {
}, },
contractArgs: [], contractArgs: [],
}, },
ops: [constructMutexLockBlock(lockId, issuer), constructMutexBlockLockClaimTake(lockId)] as const, inThreadOps: [constructMutexLockBlock(lockId, issuer), constructMutexBlockLockClaimTake(lockId)] as const,
fee: lockFee + 200n, outThreadOps: [
constructMutexLockClaimStore({ fee: lockFee, keys, lockId, timestamp, processId, locked: false }),
] as const,
fee: lockFee * 2n + 200n,
}; };
}; };

View File

@ -8,15 +8,17 @@ import {
ContractIssuer, ContractIssuer,
} from '@coinweb/contract-kit'; } from '@coinweb/contract-kit';
import { MutexNotifyLockState } from '../types';
export const mutexBlockLockKey = '_mutex_block_lock'; export const mutexBlockLockKey = '_mutex_block_lock';
export const constructMutexBlockLockClaimKey = (lockId: string) => constructClaimKey([mutexBlockLockKey], [lockId]); export const constructMutexBlockLockClaimKey = (lockId: string) => constructClaimKey([mutexBlockLockKey], [lockId]);
export const constructMutexBlockLockClaim = ({ lockId }: { lockId: string }) => export const constructMutexBlockLockClaim = ({ lockId, timestamp }: MutexNotifyLockState) =>
constructClaim(constructMutexBlockLockClaimKey(lockId), {}, '0x0'); constructClaim(constructMutexBlockLockClaimKey(lockId), { lockId, timestamp } satisfies MutexNotifyLockState, '0x0');
export const constructMutexBlockLockClaimStore = ({ lockId }: { lockId: string }) => export const constructMutexBlockLockClaimStore = ({ lockId, timestamp }: MutexNotifyLockState) =>
constructStore(constructMutexBlockLockClaim({ lockId })); constructStore(constructMutexBlockLockClaim({ lockId, timestamp }));
export const constructMutexBlockLockClaimTake = (lockId: string) => export const constructMutexBlockLockClaimTake = (lockId: string) =>
constructTake(constructMutexBlockLockClaimKey(lockId)); constructTake(constructMutexBlockLockClaimKey(lockId));

View File

@ -43,17 +43,17 @@ export const constructMutexLockClaim = ({
export const constructMutexLockClaimStore = ({ export const constructMutexLockClaimStore = ({
fee, fee,
keys, keys,
locked,
lockId, lockId,
timestamp, timestamp,
processId, processId,
locked,
}: { }: {
fee: bigint; fee: bigint;
keys: LockedKey[]; keys: LockedKey[];
locked: boolean;
lockId: string; lockId: string;
timestamp: number; timestamp: number;
processId: string; processId: string;
locked: boolean;
}) => constructStore(constructMutexLockClaim({ fee, keys, locked, lockId, timestamp, processId })); }) => constructStore(constructMutexLockClaim({ fee, keys, locked, lockId, timestamp, processId }));
export const constructMutexLockClaimRangeRead = (issuer: ContractIssuer): GRead<CwebRead> => export const constructMutexLockClaimRangeRead = (issuer: ContractIssuer): GRead<CwebRead> =>

View File

@ -6,6 +6,8 @@ import {
mutexExecLock, mutexExecLock,
mutexLock, mutexLock,
mutexUnlock, mutexUnlock,
notifyLock,
notifyLockMethodName,
preReadExecTakeOpsMethodName, preReadExecTakeOpsMethodName,
saveExecOpResult, saveExecOpResult,
saveExecOpResultMethodName, saveExecOpResultMethodName,
@ -27,4 +29,5 @@ export const mutexMethods = {
[preReadExecTakeOpsMethodName]: preReadExecTakeOps, [preReadExecTakeOpsMethodName]: preReadExecTakeOps,
[saveExecOpResultMethodName]: saveExecOpResult, [saveExecOpResultMethodName]: saveExecOpResult,
[waitMethodName]: wait, [waitMethodName]: wait,
[notifyLockMethodName]: notifyLock,
}; };

View File

@ -16,7 +16,7 @@ import { lockFee } from '../settings';
import { MutexLockState, MutexWaitNotifyArgs } from '../types'; import { MutexLockState, MutexWaitNotifyArgs } from '../types';
import { isMatchLockKeys } from '../utils'; import { isMatchLockKeys } from '../utils';
import { lockMethodName, notifyLockMethodName } from './names'; import { waitMethodName } from './names';
export const mutexExecLock = (context: Context) => { export const mutexExecLock = (context: Context) => {
const { availableCweb } = getCallParameters(context); const { availableCweb } = getCallParameters(context);
@ -59,25 +59,17 @@ export const mutexExecLock = (context: Context) => {
callInfo: { callInfo: {
ref: constructContractRef(issuer, []), ref: constructContractRef(issuer, []),
methodInfo: { methodInfo: {
methodName: lockMethodName, methodName: waitMethodName,
methodArgs: [], methodArgs: [
}, 0,
contractInfo: {
providedCweb: lockFee,
authenticated: null,
},
contractArgs: [],
},
},
{ {
callInfo: { timestamp: (lockCandidate.key.second_part as [number, string])[0],
ref: constructContractRef(issuer, []), lockId: (lockCandidate.key.second_part as [number, string])[1],
methodInfo: { },
methodName: notifyLockMethodName, ] satisfies MutexWaitNotifyArgs,
methodArgs: [0, (lockCandidate.key.second_part as [number, string])[1]] satisfies MutexWaitNotifyArgs,
}, },
contractInfo: { contractInfo: {
providedCweb: 200n, providedCweb: availableCweb + BigInt(lockCandidate.fees_stored) - 1000n,
authenticated: null, authenticated: null,
}, },
contractArgs: [], contractArgs: [],

View File

@ -5,7 +5,7 @@ import { constructMutexBlockLockClaimStore } from '../claims/mutexBlockLock';
import { MutexNotifyLockArgs } from '../types'; import { MutexNotifyLockArgs } from '../types';
export const notifyLock = (context: Context) => { export const notifyLock = (context: Context) => {
const [lockId] = getMethodArguments<MutexNotifyLockArgs>(context); const [lockInfo] = getMethodArguments<MutexNotifyLockArgs>(context);
return [constructContinueTx(context, [constructMutexBlockLockClaimStore({ lockId })])]; return [constructContinueTx(context, [constructMutexBlockLockClaimStore(lockInfo)])];
}; };

View File

@ -1,14 +1,15 @@
import { constructContinueTx, constructContractRef, Context } from '@coinweb/contract-kit'; import { constructContinueTx, constructContractRef, Context } from '@coinweb/contract-kit';
import { getContractIssuer, getMethodArguments } from 'lib/onchain'; import { getCallParameters, getContractIssuer, getMethodArguments } from 'lib/onchain';
import { waitSteps } from '../settings'; import { waitSteps } from '../settings';
import { MutexNotifyLockArgs, MutexWaitNotifyArgs } from '../types'; import { MutexNotifyLockArgs, MutexWaitNotifyArgs } from '../types';
import { notifyLockMethodName } from './names'; import { notifyLockMethodName, waitMethodName } from './names';
export const wait = (context: Context) => { export const wait = (context: Context) => {
const issuer = getContractIssuer(context); const issuer = getContractIssuer(context);
const [step, lockId] = getMethodArguments<MutexWaitNotifyArgs>(context); const [step, lockInfo] = getMethodArguments<MutexWaitNotifyArgs>(context);
const { availableCweb } = getCallParameters(context);
//Including the notifyLock method as step //Including the notifyLock method as step
if (step + 1 < waitSteps) { if (step + 1 < waitSteps) {
@ -21,11 +22,11 @@ export const wait = (context: Context) => {
callInfo: { callInfo: {
ref: constructContractRef(issuer, []), ref: constructContractRef(issuer, []),
methodInfo: { methodInfo: {
methodName: notifyLockMethodName, methodName: waitMethodName,
methodArgs: [step + 1, lockId] satisfies MutexWaitNotifyArgs, methodArgs: [step + 1, lockInfo] satisfies MutexWaitNotifyArgs,
}, },
contractInfo: { contractInfo: {
providedCweb: 200n, providedCweb: availableCweb - 800n,
authenticated: null, authenticated: null,
}, },
contractArgs: [], contractArgs: [],
@ -46,10 +47,10 @@ export const wait = (context: Context) => {
ref: constructContractRef(issuer, []), ref: constructContractRef(issuer, []),
methodInfo: { methodInfo: {
methodName: notifyLockMethodName, methodName: notifyLockMethodName,
methodArgs: [lockId] satisfies MutexNotifyLockArgs, methodArgs: [lockInfo] satisfies MutexNotifyLockArgs,
}, },
contractInfo: { contractInfo: {
providedCweb: 200n, providedCweb: availableCweb - 800n,
authenticated: null, authenticated: null,
}, },
contractArgs: [], contractArgs: [],

View File

@ -9,6 +9,11 @@ export type MutexLockState = {
processId: string; processId: string;
}; };
export type MutexNotifyLockState = {
timestamp: number;
lockId: string;
};
export type MutexExecOpsResult = ( export type MutexExecOpsResult = (
| { | {
ok: true; ok: true;
@ -24,9 +29,9 @@ export type MutexUnlockArgs = [lockId: string, timestamp: number, notify?: boole
export type MutexExecOpArgs = [ops: (GTake<CwebTake> | GStore<CwebStore>)[], processId: string, execId?: string]; export type MutexExecOpArgs = [ops: (GTake<CwebTake> | GStore<CwebStore>)[], processId: string, execId?: string];
export type MutexWaitNotifyArgs = [step: number, lockId: string]; export type MutexWaitNotifyArgs = [step: number, lockInfo: MutexNotifyLockState];
export type MutexNotifyLockArgs = [lockId: string]; export type MutexNotifyLockArgs = [lockInfo: MutexNotifyLockState];
export type MutexPreReadTakeOpsArgs = [execId: string, unavailableIndexes: number[], ops: PreparedOperation[]]; export type MutexPreReadTakeOpsArgs = [execId: string, unavailableIndexes: number[], ops: PreparedOperation[]];

View File

@ -79,6 +79,8 @@ export const prepareInThreadTxs = ({
//Info for separate child call //Info for separate child call
const childCalls: FullCallInfo[] = []; const childCalls: FullCallInfo[] = [];
const outThreadOps: PreparedOperation[] = [];
ops.forEach((op, i) => { ops.forEach((op, i) => {
switch (true) { switch (true) {
case isPreparedExecOp(op): { case isPreparedExecOp(op): {
@ -136,12 +138,25 @@ export const prepareInThreadTxs = ({
break; break;
} }
case isPreparedLockOp(op): { case isPreparedLockOp(op): {
const { callInfo, fee, ops } = constructLockCall(context.issuer, op.LockOp.lockId); const {
callInfo,
fee,
inThreadOps,
outThreadOps: outThreadOpsFromLockCall,
} = constructLockCall({
issuer: context.issuer,
lockId: op.LockOp.lockId,
timestamp: op.LockOp.timestamp,
keys: op.LockOp.keys,
processId: context.thisId,
});
childCalls.push({ callInfo }); childCalls.push({ callInfo });
callArgs.push(...ops); callArgs.push(...inThreadOps);
txFee += fee; txFee += fee;
outThreadOps.push(...outThreadOpsFromLockCall);
break; break;
} }
case isPreparedUnlockOp(op): { case isPreparedUnlockOp(op): {
@ -252,8 +267,8 @@ export const prepareInThreadTxs = ({
) )
); );
if (childCalls.length) { if (childCalls.length || outThreadOps.length) {
returnTxs.push(constructContinueTx(getRawContext(), [], childCalls)); returnTxs.push(constructContinueTx(getRawContext(), outThreadOps, childCalls));
} }
} }
} }

View File

@ -79,11 +79,19 @@ export const prepareOutThreadTxs = ({
break; break;
} }
case isPreparedLockOp(op): { case isPreparedLockOp(op): {
const { callInfo, fee } = constructLockCall(context.issuer, op.LockOp.lockId); const { callInfo, fee, outThreadOps } = constructLockCall({
issuer: context.issuer,
lockId: op.LockOp.lockId,
timestamp: op.LockOp.timestamp,
keys: op.LockOp.keys,
processId: context.thisId,
});
preparedCalls.push({ callInfo }); preparedCalls.push({ callInfo });
txFee += fee; txFee += fee;
preparedOps.push(...outThreadOps);
break; break;
} }
case isPreparedUnlockOp(op): { case isPreparedUnlockOp(op): {

View File

@ -3,9 +3,8 @@ import { context } from '../context';
let next = 0n; let next = 0n;
export const uuid = () => { export const uuid = () => {
const parentTxId = context.parentTxId; const id = (BigInt(`0x${context.thisId}`) * 3n + BigInt(`0x${context.parentTxId}`) + next).toString(16).slice(-32);
const id = `${parentTxId}${next.toString(16)}`;
next += 1n; next += 1n;
return id; return id;

View File

@ -1,4 +1,4 @@
VITE_API_URL='https://api-cloud.coinweb.io/wallet' VITE_API_URL='https://api-cloud.coinweb.io/wallet'
VITE_EXPLORER_URL='https://explorer.coinweb.io' VITE_EXPLORER_URL='https://explorer.coinweb.io'
VITE_CONTRACT_ADDRESS="0x5b7c1e53461f5497d467cb9d5c772be5e8c1a61b60e7f2f4ce71c7249d8e768a" VITE_CONTRACT_ADDRESS="0xedca91a29553fa2466e89eef02ac06dc49ab68be5e81fa91d05765cab79ec02a"