feat: internal writes for Rust

This commit is contained in:
ppedziwiatr
2022-04-03 14:12:54 +02:00
committed by just_ppe
parent 33d779ad69
commit 096d66ec9f
6 changed files with 443 additions and 405 deletions

View File

@@ -111,6 +111,7 @@ export class ContractHandlerApi<State> implements HandlerApi<State> {
input input
}); });
// The contract that we want to call and modify its state
const calleeContract = executionContext.smartweave.contract( const calleeContract = executionContext.smartweave.contract(
contractTxId, contractTxId,
executionContext.contract, executionContext.contract,

View File

@@ -54,7 +54,6 @@ export abstract class DefaultStateEvaluator implements StateEvaluator {
executionContext: ExecutionContext<State, HandlerApi<State>>, executionContext: ExecutionContext<State, HandlerApi<State>>,
currentTx: CurrentTx[] currentTx: CurrentTx[]
): Promise<EvalStateResult<State>> { ): Promise<EvalStateResult<State>> {
const stateEvaluationBenchmark = Benchmark.measure();
const { ignoreExceptions, stackTrace, internalWrites } = executionContext.evaluationOptions; const { ignoreExceptions, stackTrace, internalWrites } = executionContext.evaluationOptions;
const { contract, contractDefinition, sortedInteractions } = executionContext; const { contract, contractDefinition, sortedInteractions } = executionContext;
@@ -129,6 +128,8 @@ export abstract class DefaultStateEvaluator implements StateEvaluator {
if (newState !== null) { if (newState !== null) {
currentState = newState.cachedValue.state; currentState = newState.cachedValue.state;
// we need to update the state in the wasm module
executionContext?.handler.initState(currentState);
validity[interactionTx.id] = newState.cachedValue.validity[interactionTx.id]; validity[interactionTx.id] = newState.cachedValue.validity[interactionTx.id];
const toCache = new EvalStateResult(currentState, validity); const toCache = new EvalStateResult(currentState, validity);

View File

@@ -42,6 +42,8 @@ export class WasmContractHandlerApi<State> implements HandlerApi<State> {
this.swGlobal.gasUsed = 0; this.swGlobal.gasUsed = 0;
this.assignReadContractState<Input>(executionContext, currentTx, currentResult, interactionTx); this.assignReadContractState<Input>(executionContext, currentTx, currentResult, interactionTx);
this.assignWrite(executionContext, currentTx);
const handlerResult = await this.doHandle(interaction); const handlerResult = await this.doHandle(interaction);
return { return {
@@ -210,4 +212,47 @@ export class WasmContractHandlerApi<State> implements HandlerApi<State> {
return returnValidity ? deepCopy(stateWithValidity) : deepCopy(stateWithValidity.state); return returnValidity ? deepCopy(stateWithValidity) : deepCopy(stateWithValidity.state);
}; };
} }
private assignWrite(executionContext: ExecutionContext<State>, currentTx: CurrentTx[]) {
this.swGlobal.contracts.write = async <Input = unknown>(
contractTxId: string,
input: Input
): Promise<InteractionResult<unknown, unknown>> => {
if (!executionContext.evaluationOptions.internalWrites) {
throw new Error("Internal writes feature switched off. Change EvaluationOptions.internalWrites flag to 'true'");
}
this.logger.debug('swGlobal.write call:', {
from: this.contractDefinition.txId,
to: contractTxId,
input
});
const calleeContract = executionContext.smartweave.contract(
contractTxId,
executionContext.contract,
this.swGlobal._activeTx
);
const result = await calleeContract.dryWriteFromTx<Input>(input, this.swGlobal._activeTx, [
...(currentTx || []),
{
contractTxId: this.contractDefinition.txId,
interactionTxId: this.swGlobal.transaction.id
}
]);
this.logger.debug('Cache result?:', !this.swGlobal._activeTx.dry);
await executionContext.smartweave.stateEvaluator.onInternalWriteStateUpdate(
this.swGlobal._activeTx,
contractTxId,
{
state: result.state as State,
validity: {}
}
);
return result;
};
}
} }

View File

@@ -50,8 +50,11 @@ export const rustWasmImports = (swGlobal, wbindgenImports, wasmInstance, dtorVal
} }
}, },
SmartWeave: { SmartWeave: {
readContractState: async function (contractTxId) { readContractState: async function (contractTxId): Promise<any> {
return await swGlobal.contracts.readContractState(contractTxId); return await swGlobal.contracts.readContractState(contractTxId);
},
write: async function(contractId: string, input: any) {
return await swGlobal.contracts.write(contractId, input);
} }
} }
}; };
@@ -98,8 +101,9 @@ export const rustWasmImports = (swGlobal, wbindgenImports, wasmInstance, dtorVal
__wbg_viewContractState: function (arg0, arg1) { __wbg_viewContractState: function (arg0, arg1) {
// TODO // TODO
}, },
__wbg_write: function (arg0, arg1) { __wbg_write: function(arg0, arg1, arg2) {
// TODO var ret = rawImports.SmartWeave.write(getStringFromWasm0(arg0, arg1), takeObject(arg2));
return addHeapObject(ret);
}, },
__wbg_refreshState: function (arg0, arg1) { __wbg_refreshState: function (arg0, arg1) {
// TODO // TODO

View File

@@ -13,7 +13,7 @@ import { TsLogFactory } from '../src/logging/node/TsLogFactory';
const logger = LoggerFactory.INST.create('Contract'); const logger = LoggerFactory.INST.create('Contract');
//LoggerFactory.use(new TsLogFactory()); //LoggerFactory.use(new TsLogFactory());
//LoggerFactory.INST.logLevel('error'); LoggerFactory.INST.logLevel('error');
LoggerFactory.INST.logLevel('info', 'Contract'); LoggerFactory.INST.logLevel('info', 'Contract');
LoggerFactory.INST.logLevel('error', 'RedstoneGatewayInteractionsLoader'); LoggerFactory.INST.logLevel('error', 'RedstoneGatewayInteractionsLoader');
LoggerFactory.INST.logLevel('error', 'DefaultStateEvaluator'); LoggerFactory.INST.logLevel('error', 'DefaultStateEvaluator');
@@ -40,9 +40,8 @@ async function main() {
const jwk = readJSON('../redstone-node/.secrets/redstone-jwk.json'); const jwk = readJSON('../redstone-node/.secrets/redstone-jwk.json');
// connecting to a given contract // connecting to a given contract
const token = smartweave const token = smartweave
.contract("-8A6RexFkpfWwuyVO98wzSFZh0d6VJuI-buTJvlwOJQ") .contract("_IHQHkZrZfB3lN69Hw3xTRcHv2cBiNgh1HG1WENydP4")
.setEvaluationOptions({ .setEvaluationOptions({
useVM2: true,
sequencerAddress: "https://gateway.redstone.finance/" sequencerAddress: "https://gateway.redstone.finance/"
}) })
// connecting wallet to a contract. It is required before performing any "writeInteraction" // connecting wallet to a contract. It is required before performing any "writeInteraction"
@@ -51,16 +50,23 @@ async function main() {
const result1 = await token.readState(); const result1 = await token.readState();
console.log(result1.state);
console.log(token.lastReadStateStats()); console.log(token.lastReadStateStats());
//logger.info("Amount of computed interactions before 'bundleInteraction':", Object.keys(result1.validity).length); //logger.info("Amount of computed interactions before 'bundleInteraction':", Object.keys(result1.validity).length);
/*for (let i = 0 ; i < 100 ; i++) { /*for (let i = 0 ; i < 1100 ; i++) {
console.log(`mint ${i + 1}`); console.log(`mint ${i + 1}`);
const result = await token.bundleInteraction<any>({ try {
function: "mint" const result = await token.bundleInteraction<any>({
}); function: "transfer",
await sleep(1000); target: "33F0QHcb22W7LwWR1iRC8Az1ntZG09XQ03YWuw2ABqA",
qty: 10
});
} catch(e:any) {
}
//await sleep(1);
}*/ }*/

767
yarn.lock

File diff suppressed because it is too large Load Diff