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 { cwait, readOp, storeOp, TypedClaim } from 'cwait';
import { cwait, lock, readOp, storeOp, TypedClaim } from 'cwait';
import { createWordKey, WordClaimBody } from '../offchain';
import { extraLogic2 } from './extraLogic2';
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));
console.log('extraLogic storeOp + ', i);
await storeOp(
constructClaim(
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);
return extraLogic2(id, i);
});

View File

@ -12,7 +12,6 @@ import { getCallParameters, getContractIssuer } from 'lib/onchain';
import { ExecutorMethodArgs, ResolvedOp } from '../../types';
import { pushAwaitedTask } from '../promisifiedFeatures';
import { uuid } from '../utils';
import { extractOps } from './extractOps';
@ -65,7 +64,9 @@ export const handleContext = (ctx: Context) => {
] = getMethodArgs();
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.methodName = methodName;
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 { resultKey } from '../claims';
import { mutexBlockLockKey, mutexBlockUnlockKey, mutexExecOpsKey, MutexExecOpsResult } from '../mutex';
import {
mutexBlockLockKey,
mutexBlockUnlockKey,
mutexExecOpsKey,
MutexExecOpsResult,
MutexNotifyLockState,
} from '../mutex';
import { isResolvedBlockOp, isResolvedReadOp, isResolvedTakeOp } from '../utils';
const extractFunds = (fundsOp: GRead<ResolvedRead>, takenFundsIds: string[]) => {
@ -92,7 +98,9 @@ export const extractOps = ({
throw new Error('Wrong mutex lock result');
}
extractedOps.push({ SlotOp: { ok: true } });
extractedOps.push({
LockOp: nextAfterBlock.TakeOp.result.body as MutexNotifyLockState,
});
i += 2;
continue;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@ import { constructMutexBlockLockClaimStore } from '../claims/mutexBlockLock';
import { MutexNotifyLockArgs } from '../types';
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 { getContractIssuer, getMethodArguments } from 'lib/onchain';
import { getCallParameters, getContractIssuer, getMethodArguments } from 'lib/onchain';
import { waitSteps } from '../settings';
import { MutexNotifyLockArgs, MutexWaitNotifyArgs } from '../types';
import { notifyLockMethodName } from './names';
import { notifyLockMethodName, waitMethodName } from './names';
export const wait = (context: 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
if (step + 1 < waitSteps) {
@ -21,11 +22,11 @@ export const wait = (context: Context) => {
callInfo: {
ref: constructContractRef(issuer, []),
methodInfo: {
methodName: notifyLockMethodName,
methodArgs: [step + 1, lockId] satisfies MutexWaitNotifyArgs,
methodName: waitMethodName,
methodArgs: [step + 1, lockInfo] satisfies MutexWaitNotifyArgs,
},
contractInfo: {
providedCweb: 200n,
providedCweb: availableCweb - 800n,
authenticated: null,
},
contractArgs: [],
@ -46,10 +47,10 @@ export const wait = (context: Context) => {
ref: constructContractRef(issuer, []),
methodInfo: {
methodName: notifyLockMethodName,
methodArgs: [lockId] satisfies MutexNotifyLockArgs,
methodArgs: [lockInfo] satisfies MutexNotifyLockArgs,
},
contractInfo: {
providedCweb: 200n,
providedCweb: availableCweb - 800n,
authenticated: null,
},
contractArgs: [],

View File

@ -9,6 +9,11 @@ export type MutexLockState = {
processId: string;
};
export type MutexNotifyLockState = {
timestamp: number;
lockId: string;
};
export type MutexExecOpsResult = (
| {
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 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[]];

View File

@ -79,6 +79,8 @@ export const prepareInThreadTxs = ({
//Info for separate child call
const childCalls: FullCallInfo[] = [];
const outThreadOps: PreparedOperation[] = [];
ops.forEach((op, i) => {
switch (true) {
case isPreparedExecOp(op): {
@ -136,12 +138,25 @@ export const prepareInThreadTxs = ({
break;
}
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 });
callArgs.push(...ops);
callArgs.push(...inThreadOps);
txFee += fee;
outThreadOps.push(...outThreadOpsFromLockCall);
break;
}
case isPreparedUnlockOp(op): {
@ -252,8 +267,8 @@ export const prepareInThreadTxs = ({
)
);
if (childCalls.length) {
returnTxs.push(constructContinueTx(getRawContext(), [], childCalls));
if (childCalls.length || outThreadOps.length) {
returnTxs.push(constructContinueTx(getRawContext(), outThreadOps, childCalls));
}
}
}

View File

@ -79,11 +79,19 @@ export const prepareOutThreadTxs = ({
break;
}
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 });
txFee += fee;
preparedOps.push(...outThreadOps);
break;
}
case isPreparedUnlockOp(op): {

View File

@ -3,9 +3,8 @@ import { context } from '../context';
let next = 0n;
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;
return id;

View File

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