
Research
Malicious npm Packages Impersonate Flashbots SDKs, Targeting Ethereum Wallet Credentials
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
motoko-benchmarking-ts
Advanced tools
A set of functions to run benchmarking of any complexity for Motoko canisters in TypeScript, designed to be used in conjunction with module 'dfx-terminal-commands'.
rts_stable_memory_size: bigint; //Stable memory pages used
rts_memory_size: bigint; //Total memory used by canister
rts_total_allocation: bigint; //Total allocated memory of all time
rts_reclaimed: bigint; //Total reclaimed memory of all time
rts_heap_size: bigint; //Used Heap memory size of canister in bytes
instruction_count: bigint; //Instruction cost of performing operations without costs for calling the function and returning values
rts_collector_instructions: bigint; //Instructions that are used for garbage collection;
rts_mutator_instructions: biging; //Total Wasm instructions used by the last called update function, except for garbage collection
Note: if you want to measure GC instructions per function call, use flag "--force-gc" with the type if gc you want to use in dfx.json:
"--generational-gc" - use generational GC,
"--incremental-gc" - use incremental GC,
"--compacting-gc" - use compacting GC,
"--copying-gc" - use copying GC (default)
For example, if you want to measure the function resource usage with --incremental-gc:
"defaults": {
"build": {
"args": "--force-gc --incremental-gc",
...
}
},
actor {
type RtsData = {
rts_stable_memory_size: Nat;
rts_memory_size: Nat;
rts_total_allocation: Nat;
rts_reclaimed: Nat;
rts_heap_size: Nat;
rts_collector_instructions: Nat;
rts_mutator_instructions: Nat;
};
//Function for getting the values of Heap and Stable memory and Garbage Collector instructions
public composite query func getRtsData() : async RtsData {
return {
rts_stable_memory_size = Prim.rts_stable_memory_size();
rts_memory_size = Prim.rts_memory_size();
rts_total_allocation = Prim.rts_total_allocation();
rts_reclaimed = Prim.rts_reclaimed();
rts_heap_size = Prim.rts_heap_size();
rts_collector_instructions = Prim.rts_collector_instructions();
rts_mutator_instructions = Prim.rts_mutator_instructions();
};
};
}
import IC "mo:base/ExperimentalInternetComputer";
...
public func example_function() : Nat {
let count = IC.countInstructions(
func () {
//Some operations, whose cost you want to measure, for example:
//var test = 0;
//for (i in Iter.range(start_index, end_index)) {
// test := test + i;
//}
}
}
);
return count;
}
dfx generate
so that their declaration is generated for use in TypeScript....
import Map "mo:map/Map";
actor {
stable var t = Map.new<Nat, Nat>();
public func for_loop(start_index: Nat, total_elements: Nat) : async(Nat64) {
let end_index = start_index + total_elements;
let count = IC.countInstructions(
func () {
for (i in Iter.range(start_index, end_index)) {}
}
);
return count;
};
public func add_batch(start_index: Nat, total_elements: Nat) : async (Nat64) {
let end_index = start_index + total_elements;
let count = IC.countInstructions(
func () {
for (i in Iter.range(start_index, end_index)) {
Map.set(t, nhash, i, 1);
}
}
);
return count;
};
public func delete_all() {
Map.clear(t);
};
}
import * from 'motoko-benchmarking-ts';
import * from 'dfx-terminal-commands';
//Importing interface and idlFactory from canister declaration
import { idlFactory, map } from "../../../src/declarations/map";
async function main() {
//Starting dfx for testing
await startDfx();
//Setting a name that will be used later
const canisterName = "map";
//Generating random secp256k1 identity
const identity = makeIdentity();
//Creating agent
const agent = await makeAgent(identity);
//Deploying canister and getting id
await deployCanister(canisterName);
const canisterId = await getCanisterId(canisterName);
//Creating actor for calling canister
const actor: typeof memory_hashtable = makeActor(agent, idlFactory, canisterId);
//Topping the canister up (fabricating ICP and transfering it's cycles value to canister)
await fabricateIcpToCycles(canisterName, 1000000);
...
...
//======================================
//TESTING
//======================================
const testValues: bigint[] = [1n, 10n, 100n, 1000n, 10000n, 100000n, 1000000n, 10000000n];
//Making arrays for each function that we want to test, the more function you want to test, the more empty arrays of MeasurementData you should make
let testResults: MeasurementData[][] = [[], []];
console.log(`+++++++++`);
console.log(`Beginning testing of canister: "${canisterName}"`);
//Measurements
for (let value of testValues) {
console.log(`==============`);
console.log(`Testing with ${value} elements`);
console.log(`==============`);
console.log(`Measuring for loop usage..`);
//We pass in (actor, {function that we want to measure}, {arguments for function})
let forLoopUsage = await measureFunction(actor, actor.for_loop, [0n, value]);
console.log(`Measuring adding elements..`);
let addData = await measureFunction(actor, actor.add_batch, [0n, value]);
//Saving the for loop usage to subarray 0
testResults[0].push(forLoopUsage);
//When we call add_batch function, the resources used by for loop are also taken into account so if we want to know the exact cost of adding elements we can measure the cost of for loop without any other operations and then substract the obtained values from measurement results
//Getting the usage of only Map.set(t, nhash, i, 1) operation, without for loop
let purifiedAddData = purifyMeasurementData(addData, forLoopUsage);
//Saving the purified data to subarray 1
testResults[1].push(purifiedAddData);
//Resetting the data structure
await actor.delete_all();
}
//======================================
//WRITING TEST DATA TO TABLES
//======================================
console.log(`==============`);
console.log(`Saving the data to excel table: "${canisterName}.xlsx"..`);
console.log(`==============`);
//Generating headers for Excel table from test values
const headers = ['', ...testValues.map(value => value.toString())];
saveToExcel(`./results/${canisterName}.xlsx`, ["For loop", "Batch adding"], headers, testResults);
//Stopping the dfx service
await stopDfx();
console.log(`+++++++++++++`);
console.log(`All done!`);
}; //end of main()
main();
//A function to get current rts data from an actor (if it complies with the needed interface)
async function getRtsData(actor: ActorSubclass<any>) : Promise<RtsData>
//A function to measure the difference between the MeasurementData before and after update function call.
function measureDifference(new_values: RtsData, prev_values: RtsData, instruction_count: bigint) : MeasurementData
//A function to measure the difference between the RtsData before and after update function call.
export function measureDifferenceRts(new_values: RtsData, prev_values: RtsData) : RtsData
//A function for when you need to know the pure resource usage of operation by substracting resource usage of needed utils
function purifyMeasurementData(data: MeasurementData, base: MeasurementData) : MeasurementData
//A function for getting a sum of all properties of 2 MeasurementData objects.
function addMeasurementData(data_1: MeasurementData, data_2: MeasurementData) : MeasurementData
//A function for getting a sum of all properties of 2 RtsData objects.
function addRtsData(data_1: RtsData, data_2: RtsData) : RtsData
//A function to substract two MeasurementData objects.
function substractMeasurementData(data_1: MeasurementData, data_2: MeasurementData) : MeasurementData
//A function to substract two RtsData objects.
function substractRtsData(data: RtsData, base: RtsData) : RtsData
//A function to save 2D array of RtsData to the Excel file.
async function saveToExcelRts(file_path: string, sheet_names: string[], headers: string[], data: RtsData[][])
//A function to save your custom data type to excel table. Useful if you want to conduct your own tests with different properties.
async function saveToExcelCustom<T extends Record<string, unknown>>(file_path: string, rows:string[], sheet_names: string[], headers: string[], data: T[][])
...
let totalUsage: MeasurementData = {
rts_stable_memory_size: 0n,
rts_memory_size: 0n,
rts_total_allocation: 0n,
rts_reclaimed: 0n,
rts_heap_size: 0n,
instruction_count: 0n,
rts_collector_instructions: 0n,
rts_mutator_instructions: 0n
};
let numberOfCalls = 100;
for (let i = 0; i < numberOfCalls; i++) {
let usage = await measureFunction(actor, actor.add_batch, [0n, 1n]);
totalUsage = addMeasurementData(totalUsage, usage);
}
console.log(totalUsage);
...
let rtsDataPrev = await getRtsData(actor);
await actor.add_batch([0n, 1n]);
let rtsDataNew = await getRtsData(actor);
let rtsUsage = measureDifferenceRts(rtsDataNew, rtsDataPrev);
console.log(rtsUsage);
FAQs
A set of functions to run benchmarking of any complexity for Motoko canisters in TypeScript, designed to be used in conjunction with module 'dfx-terminal-commands'.
We found that motoko-benchmarking-ts demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.