feat: storing info about contract type and contract lang in tags
This commit is contained in:
committed by
Piotr Pędziwiatr
parent
0e4d896d8e
commit
a679c04ebe
Binary file not shown.
@@ -3,7 +3,7 @@ import fs from 'fs';
|
||||
import ArLocal from 'arlocal';
|
||||
import Arweave from 'arweave';
|
||||
import { JWKInterface } from 'arweave/node/lib/wallet';
|
||||
import { Contract, LoggerFactory, SmartWeave, SmartWeaveNodeFactory } from '@smartweave';
|
||||
import {Contract, getTag, LoggerFactory, SmartWeave, SmartWeaveNodeFactory, SmartWeaveTags} from '@smartweave';
|
||||
import path from 'path';
|
||||
import { addFunds, mineBlock } from './_helpers';
|
||||
|
||||
@@ -68,7 +68,14 @@ describe('Testing the SmartWeave client for WASM contract', () => {
|
||||
|
||||
it('should properly deploy contract', async () => {
|
||||
const contractTx = await arweave.transactions.get(contractTxId);
|
||||
|
||||
expect(contractTx).not.toBeNull();
|
||||
expect(getTag(contractTx, SmartWeaveTags.CONTRACT_TYPE)).toEqual('wasm');
|
||||
expect(getTag(contractTx, SmartWeaveTags.WASM_LANG)).toEqual('assemblyscript');
|
||||
|
||||
const contractSrcTx = await arweave.transactions.get(getTag(contractTx, SmartWeaveTags.CONTRACT_SRC_TX_ID));
|
||||
expect(getTag(contractSrcTx, SmartWeaveTags.CONTENT_TYPE)).toEqual('application/wasm');
|
||||
expect(getTag(contractSrcTx, SmartWeaveTags.WASM_LANG)).toEqual('assemblyscript');
|
||||
});
|
||||
|
||||
it('should properly read initial state', async () => {
|
||||
@@ -122,8 +129,8 @@ describe('Testing the SmartWeave client for WASM contract', () => {
|
||||
function: 'infLoop'
|
||||
});
|
||||
|
||||
expect(result.type).toEqual("exception");
|
||||
expect(result.errorMessage.startsWith("[RE:OOG")).toBeTruthy();
|
||||
expect(result.type).toEqual('exception');
|
||||
expect(result.errorMessage.startsWith('[RE:OOG')).toBeTruthy();
|
||||
});
|
||||
|
||||
/*it('should skip interaction during contract state read if gas limit exceeded', async () => {
|
||||
@@ -139,6 +146,4 @@ describe('Testing the SmartWeave client for WASM contract', () => {
|
||||
|
||||
expect(callStack.getInteraction(txId)).toEqual({});
|
||||
});*/
|
||||
|
||||
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* This type contains all data and meta-data of the given contact.
|
||||
*/
|
||||
import {ContractType} from "./modules/CreateContract";
|
||||
import { ContractType } from './modules/CreateContract';
|
||||
|
||||
export type ContractDefinition<State> = {
|
||||
txId: string;
|
||||
|
||||
@@ -12,5 +12,7 @@ export enum SmartWeaveTags {
|
||||
MIN_FEE = 'Min-Fee',
|
||||
INIT_STATE = 'Init-State',
|
||||
INIT_STATE_TX = 'Init-State-TX',
|
||||
INTERACT_WRITE = 'Interact-Write'
|
||||
INTERACT_WRITE = 'Interact-Write',
|
||||
WASM_LANG = 'Wasm-Lang',
|
||||
CONTRACT_TYPE = 'Contract-Type'
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ export interface ContractData extends CommonContractData {
|
||||
|
||||
export interface FromSrcTxContractData extends CommonContractData {
|
||||
srcTxId: string;
|
||||
contractType: ContractType;
|
||||
wasmLang: string | null;
|
||||
}
|
||||
|
||||
export interface CreateContract {
|
||||
|
||||
@@ -12,9 +12,7 @@ import {
|
||||
import Arweave from 'arweave';
|
||||
import Transaction from 'arweave/web/lib/transaction';
|
||||
|
||||
const supportedSrcContentTypes = [
|
||||
'application/javascript', 'application/wasm'
|
||||
];
|
||||
const supportedSrcContentTypes = ['application/javascript', 'application/wasm'];
|
||||
|
||||
export class ContractDefinitionLoader implements DefinitionLoader {
|
||||
private readonly logger = LoggerFactory.INST.create('ContractDefinitionLoader');
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import {ContractData, ContractType, CreateContract, FromSrcTxContractData, SmartWeaveTags} from '@smartweave/core';
|
||||
import { ContractData, ContractType, CreateContract, FromSrcTxContractData, SmartWeaveTags } from '@smartweave/core';
|
||||
import Arweave from 'arweave';
|
||||
import { LoggerFactory } from '@smartweave/logging';
|
||||
import { imports } from './wasmImports';
|
||||
|
||||
const wasmTypeMapping: Map<number, string> = new Map([
|
||||
[1, 'assemblyscript'],
|
||||
[2, 'rust'],
|
||||
[3, 'go'],
|
||||
[4, 'swift'],
|
||||
[5, 'c']
|
||||
]);
|
||||
|
||||
export class DefaultCreateContract implements CreateContract {
|
||||
private readonly logger = LoggerFactory.INST.create('DefaultCreateContract');
|
||||
@@ -24,6 +33,27 @@ export class DefaultCreateContract implements CreateContract {
|
||||
srcTx.addTag(SmartWeaveTags.SDK, 'RedStone');
|
||||
srcTx.addTag(SmartWeaveTags.CONTENT_TYPE, contractType == 'js' ? 'application/javascript' : 'application/wasm');
|
||||
|
||||
let wasmLang = null;
|
||||
|
||||
if (contractType == 'wasm') {
|
||||
// note: instantiating wasm module for a while just to check
|
||||
// the exported "type" value - which holds info about source lang.
|
||||
const module = await WebAssembly.instantiate(src, dummyImports());
|
||||
// @ts-ignore
|
||||
if (!module.instance.exports.type) {
|
||||
throw new Error(`No info about source type in wasm binary. Did you forget to export global "type" value`);
|
||||
}
|
||||
// @ts-ignore
|
||||
const type = module.instance.exports.type.value;
|
||||
if (!wasmTypeMapping.has(type)) {
|
||||
throw new Error(`Unknown wasm source type ${type}`);
|
||||
}
|
||||
|
||||
wasmLang = wasmTypeMapping.get(type);
|
||||
|
||||
srcTx.addTag(SmartWeaveTags.WASM_LANG, wasmLang);
|
||||
}
|
||||
|
||||
await this.arweave.transactions.sign(srcTx, wallet);
|
||||
|
||||
this.logger.debug('Posting transaction with source');
|
||||
@@ -34,6 +64,8 @@ export class DefaultCreateContract implements CreateContract {
|
||||
srcTxId: srcTx.id,
|
||||
wallet,
|
||||
initState,
|
||||
contractType,
|
||||
wasmLang,
|
||||
tags,
|
||||
transfer
|
||||
});
|
||||
@@ -71,6 +103,10 @@ export class DefaultCreateContract implements CreateContract {
|
||||
contractTX.addTag(SmartWeaveTags.CONTRACT_SRC_TX_ID, srcTxId);
|
||||
contractTX.addTag(SmartWeaveTags.SDK, 'RedStone');
|
||||
contractTX.addTag(SmartWeaveTags.CONTENT_TYPE, 'application/json');
|
||||
contractTX.addTag(SmartWeaveTags.CONTRACT_TYPE, contractData.contractType);
|
||||
if (contractData.contractType == 'wasm') {
|
||||
contractTX.addTag(SmartWeaveTags.WASM_LANG, contractData.wasmLang);
|
||||
}
|
||||
|
||||
await this.arweave.transactions.sign(contractTX, wallet);
|
||||
|
||||
@@ -82,3 +118,12 @@ export class DefaultCreateContract implements CreateContract {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function dummyImports() {
|
||||
return imports(
|
||||
{
|
||||
useGas: function () {}
|
||||
} as any,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import { ContractHandlerApi } from './ContractHandlerApi';
|
||||
import loader from '@assemblyscript/loader';
|
||||
import { imports } from './wasmImports';
|
||||
import { WasmContractHandlerApi } from './WasmContractHandlerApi';
|
||||
import metering from 'wasm-metering';
|
||||
|
||||
const metering = require('wasm-metering');
|
||||
/**
|
||||
* A factory that produces handlers that are compatible with the "current" style of
|
||||
* writing SW contracts (ie. using "handle" function).
|
||||
@@ -32,7 +32,7 @@ export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknow
|
||||
|
||||
if (contractDefinition.contractType == 'js') {
|
||||
this.logger.info('Creating handler for js contract', contractDefinition.txId);
|
||||
let normalizedSource =
|
||||
const normalizedSource =
|
||||
contractDefinition.src instanceof Buffer
|
||||
? normalizeContractSource(this.arweave.utils.bufferToString(contractDefinition.src))
|
||||
: normalizeContractSource(contractDefinition.src);
|
||||
@@ -43,7 +43,7 @@ export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknow
|
||||
} else {
|
||||
this.logger.info('Creating handler for wasm contract', contractDefinition.txId);
|
||||
|
||||
let wasmModuleData = {
|
||||
const wasmModuleData = {
|
||||
exports: null
|
||||
};
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ export class RedstoneGatewayContractDefinitionLoader extends ContractDefinitionL
|
||||
}
|
||||
throw new Error(`Unable to retrieve contract data. Redstone gateway responded with status ${error.status}.`);
|
||||
});
|
||||
result.contractType = "js"; // TODO: Add support in redstone gateway
|
||||
result.contractType = 'js'; // TODO: Add support in redstone gateway
|
||||
return result;
|
||||
} catch (e) {
|
||||
this.rLogger.warn('Falling back to default contracts loader');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {LoggerFactory, SmartWeaveGlobal} from "@smartweave";
|
||||
import { LoggerFactory, SmartWeaveGlobal } from '@smartweave';
|
||||
|
||||
export const imports = (swGlobal: SmartWeaveGlobal, wasmModule: any): any => {
|
||||
const wasmLogger = LoggerFactory.INST.create('WASM');
|
||||
@@ -8,69 +8,74 @@ export const imports = (swGlobal: SmartWeaveGlobal, wasmModule: any): any => {
|
||||
usegas: swGlobal.useGas
|
||||
},
|
||||
console: {
|
||||
"console.log": function (msgPtr) {
|
||||
'console.log': function (msgPtr) {
|
||||
wasmLogger.debug(`${swGlobal.contract.id}: ${wasmModule.exports.__getString(msgPtr)}`);
|
||||
},
|
||||
"console.logO": function (msgPtr, objPtr) {
|
||||
wasmLogger.debug(`${swGlobal.contract.id}: ${wasmModule.exports.__getString(msgPtr)}`, JSON.parse(wasmModule.exports.__getString(objPtr)));
|
||||
},
|
||||
'console.logO': function (msgPtr, objPtr) {
|
||||
wasmLogger.debug(
|
||||
`${swGlobal.contract.id}: ${wasmModule.exports.__getString(msgPtr)}`,
|
||||
JSON.parse(wasmModule.exports.__getString(objPtr))
|
||||
);
|
||||
}
|
||||
},
|
||||
block: {
|
||||
"Block.height": function () {
|
||||
'Block.height': function () {
|
||||
return swGlobal.block.height;
|
||||
},
|
||||
"Block.indep_hash": function () {
|
||||
'Block.indep_hash': function () {
|
||||
return wasmModule.exports.__newString(swGlobal.block.indep_hash);
|
||||
},
|
||||
"Block.timestamp": function () {
|
||||
'Block.timestamp': function () {
|
||||
return swGlobal.block.timestamp;
|
||||
},
|
||||
}
|
||||
},
|
||||
transaction: {
|
||||
"Transaction.id": function () {
|
||||
'Transaction.id': function () {
|
||||
return wasmModule.exports.__newString(swGlobal.transaction.id);
|
||||
},
|
||||
"Transaction.owner": function () {
|
||||
'Transaction.owner': function () {
|
||||
return wasmModule.exports.__newString(swGlobal.transaction.owner);
|
||||
},
|
||||
"Transaction.target": function () {
|
||||
'Transaction.target': function () {
|
||||
return wasmModule.exports.__newString(swGlobal.transaction.target);
|
||||
},
|
||||
}
|
||||
},
|
||||
contract: {
|
||||
"Contract.id": function () {
|
||||
'Contract.id': function () {
|
||||
return wasmModule.exports.__newString(swGlobal.contract.id);
|
||||
},
|
||||
"Contract.owner": function () {
|
||||
'Contract.owner': function () {
|
||||
return wasmModule.exports.__newString(swGlobal.contract.owner);
|
||||
},
|
||||
}
|
||||
},
|
||||
api: {
|
||||
_readContractState: (fnIndex, contractTxIdPtr) => {
|
||||
const contractTxId = wasmModule.exports.__getString(contractTxIdPtr);
|
||||
const callbackFn = getFn(fnIndex);
|
||||
console.log("Simulating read state of", contractTxId);
|
||||
console.log('Simulating read state of', contractTxId);
|
||||
return setTimeout(() => {
|
||||
console.log('calling callback');
|
||||
callbackFn(wasmModule.exports.__newString(JSON.stringify({
|
||||
contractTxId
|
||||
})));
|
||||
callbackFn(
|
||||
wasmModule.exports.__newString(
|
||||
JSON.stringify({
|
||||
contractTxId
|
||||
})
|
||||
)
|
||||
);
|
||||
}, 1000);
|
||||
},
|
||||
clearTimeout,
|
||||
clearTimeout
|
||||
},
|
||||
env: {
|
||||
abort(messagePtr, fileNamePtr, line, column) {
|
||||
console.error("--------------------- Error message from AssemblyScript ----------------------");
|
||||
console.error(" " + wasmModule.exports.__getString(messagePtr));
|
||||
console.error(
|
||||
' In file "' + wasmModule.exports.__getString(fileNamePtr) + '"'
|
||||
);
|
||||
console.error('--------------------- Error message from AssemblyScript ----------------------');
|
||||
console.error(' ' + wasmModule.exports.__getString(messagePtr));
|
||||
console.error(' In file "' + wasmModule.exports.__getString(fileNamePtr) + '"');
|
||||
console.error(` on line ${line}, column ${column}.`);
|
||||
console.error("------------------------------------------------------------------------------\n");
|
||||
},
|
||||
console.error('------------------------------------------------------------------------------\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function getFn(idx) {
|
||||
return wasmModule.exports.table.get(idx);
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user