fix: reading owner of tx in strict mode (#306)

This commit is contained in:
koonopek
2023-01-02 11:35:13 +01:00
committed by GitHub
parent d2f90771e5
commit 14a786bd07
9 changed files with 78 additions and 53 deletions

View File

@@ -155,4 +155,22 @@ describe('Testing the Profit Sharing Token', () => {
expect(result.state.balances['uhE-QeYS8i4pmUtnxQyHD7dzXFNaJ9oMK-IM-QPNY6M']).toEqual(10000000 + 555 + 333);
expect(result.state.balances[overwrittenCaller]).toEqual(1000 - 333);
});
describe('when in strict mode', () => {
it('should properly extract owner from signature, using arweave wallet', async () => {
const startBalance = (await pst.currentBalance(walletAddress)).balance;
await pst.writeInteraction(
{
function: 'transfer',
target: 'uhE-QeYS8i4pmUtnxQyHD7dzXFNaJ9oMK-IM-QPNY6M',
qty: 100
},
{ strict: true }
)
expect((await pst.currentBalance(walletAddress)).balance).toEqual(startBalance - 100);
});
})
});

View File

@@ -4,7 +4,7 @@ import { InteractionResult } from '../core/modules/impl/HandlerExecutorFactory';
import { EvaluationOptions, EvalStateResult } from '../core/modules/StateEvaluator';
import { GQLNodeInterface } from '../legacy/gqlResult';
import { ArTransfer, Tags, ArWallet } from './deploy/CreateContract';
import { SignatureType } from './Signature';
import { CustomSignature } from './Signature';
import { EvaluationOptionsEvaluator } from './EvaluationOptionsEvaluator';
export type CurrentTx = { interactionTxId: string; contractTxId: string };
@@ -76,7 +76,7 @@ export interface Contract<State = unknown> {
*
* @param signer - either {@link ArWallet} that will be connected to this contract or custom {@link SigningFunction}
*/
connect(signature: ArWallet | SignatureType): Contract<State>;
connect(signature: ArWallet | CustomSignature): Contract<State>;
/**
* Allows to set ({@link EvaluationOptions})

View File

@@ -33,7 +33,7 @@ import {
import { ArTransfer, ArWallet, emptyTransfer, Tags } from './deploy/CreateContract';
import { InnerWritesEvaluator } from './InnerWritesEvaluator';
import { generateMockVrf } from '../utils/vrf';
import { Signature, SignatureType } from './Signature';
import { Signature, CustomSignature } from './Signature';
import { ContractDefinition } from '../core/ContractDefinition';
import { EvaluationOptionsEvaluator } from './EvaluationOptionsEvaluator';
import { WarpFetchWrapper } from '../core/WarpFetchWrapper';
@@ -366,13 +366,6 @@ export class HandlerBasedContract<State> implements Contract<State> {
});
this.logger.debug('Tags with inner calls', tags);
} else {
if (strict) {
const handlerResult = await this.callContract(input, undefined, undefined, tags, transfer, strict, vrf);
if (handlerResult.type !== 'ok') {
throw Error(`Cannot create interaction: ${handlerResult.errorMessage}`);
}
}
}
if (vrf) {
@@ -394,6 +387,14 @@ export class HandlerBasedContract<State> implements Contract<State> {
this.warp.environment === 'testnet',
reward
);
if (!this._evaluationOptions.internalWrites && strict) {
const handlerResult = await this.callContract(input, interactionTx.owner, undefined, tags, transfer, strict, vrf);
if (handlerResult.type !== 'ok') {
throw Error(`Cannot create interaction: ${handlerResult.errorMessage}`);
}
}
return interactionTx;
}
@@ -405,7 +406,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
return this._callStack;
}
connect(signature: ArWallet | SignatureType): Contract<State> {
connect(signature: ArWallet | CustomSignature): Contract<State> {
this.signature = new Signature(this.warp, signature);
return this;
}
@@ -467,14 +468,14 @@ export class HandlerBasedContract<State> implements Contract<State> {
interactions
? Promise.resolve(interactions)
: await interactionsLoader.load(
contractTxId,
cachedState?.sortKey,
// (1) we want to eagerly load dependant contract interactions and put them
// in the interactions' loader cache
// see: https://github.com/warp-contracts/warp/issues/198
this.getToSortKey(upToSortKey),
this._evaluationOptions
)
contractTxId,
cachedState?.sortKey,
// (1) we want to eagerly load dependant contract interactions and put them
// in the interactions' loader cache
// see: https://github.com/warp-contracts/warp/issues/198
this.getToSortKey(upToSortKey),
this._evaluationOptions
)
]);
// (2) ...but we still need to return only interactions up to original "upToSortKey"
if (cachedState?.sortKey) {

View File

@@ -2,34 +2,24 @@ import Transaction from 'arweave/node/lib/transaction';
import { Warp } from '../core/Warp';
import { ArWallet } from './deploy/CreateContract';
export type SignatureType = 'arweave' | 'ethereum';
export type SigningFunction = (tx: Transaction) => Promise<void>;
export type SignatureType = { signer: SigningFunction; type: 'arweave' | 'ethereum' };
export type CustomSignature = { signer: SigningFunction; type: SignatureType };
export class Signature {
readonly signer: SigningFunction;
readonly type: 'arweave' | 'ethereum';
signer: SigningFunction;
type: SignatureType;
readonly warp: Warp;
constructor(warp: Warp, walletOrSignature: ArWallet | SignatureType) {
constructor(warp: Warp, walletOrSignature: ArWallet | CustomSignature) {
this.warp = warp;
if (this.isSignatureType(walletOrSignature)) {
if (
walletOrSignature.type !== 'arweave' &&
(!(this.warp.environment == 'mainnet') || !(this.warp.interactionsLoader.type() == 'warp'))
) {
throw new Error(
`Unable to use signing function of type: ${walletOrSignature.type} when not in mainnet environment or bundling is disabled.`
);
} else {
this.signer = walletOrSignature.signer;
this.type = walletOrSignature.type;
}
if (this.isCustomSignature(walletOrSignature)) {
this.assertEnvForCustomSigner(walletOrSignature);
this.signer = walletOrSignature.signer;
this.type = walletOrSignature.type;
} else {
this.signer = async (tx: Transaction) => {
await this.warp.arweave.transactions.sign(tx, walletOrSignature);
};
this.type = 'arweave';
this.assignDefaultSigner(walletOrSignature);
}
}
@@ -39,7 +29,23 @@ export class Signature {
}
}
private isSignatureType(signature: ArWallet | SignatureType): signature is SignatureType {
return (signature as SignatureType).signer !== undefined;
private assignDefaultSigner(walletOrSignature) {
this.signer = async (tx: Transaction) => {
await this.warp.arweave.transactions.sign(tx, walletOrSignature);
};
this.type = 'arweave';
}
private assertEnvForCustomSigner(walletOrSignature: CustomSignature) {
if (walletOrSignature.type !== 'arweave' &&
(!(this.warp.environment == 'mainnet') || !(this.warp.interactionsLoader.type() == 'warp'))) {
throw new Error(
`Unable to use signing function of type: ${walletOrSignature.type} when not in mainnet environment or bundling is disabled.`
);
}
}
private isCustomSignature(signature: ArWallet | CustomSignature): signature is CustomSignature {
return (signature as CustomSignature).signer !== undefined;
}
}

View File

@@ -1,5 +1,5 @@
import { JWKInterface } from 'arweave/node/lib/wallet';
import { SignatureType } from '../../contract/Signature';
import { CustomSignature } from '../../contract/Signature';
import { Source } from './Source';
import { EvaluationOptions } from '../../core/modules/StateEvaluator';
import { WarpPluginType } from '../../core/WarpPlugin';
@@ -29,7 +29,7 @@ export const BUNDLR_NODES = ['node1', 'node2'] as const;
export type BundlrNodeType = typeof BUNDLR_NODES[number];
export interface CommonContractData {
wallet: ArWallet | SignatureType;
wallet: ArWallet | CustomSignature;
initState: string;
tags?: Tags;
transfer?: ArTransfer;

View File

@@ -1,6 +1,6 @@
import { ArWallet } from './CreateContract';
import { SourceData } from './impl/SourceImpl';
import { SignatureType } from '../../contract/Signature';
import { CustomSignature } from '../../contract/Signature';
import Transaction from 'arweave/node/lib/transaction';
export interface Source {
/**
@@ -8,7 +8,7 @@ export interface Source {
* @param sourceData - contract source data
* @param wallet - either Arweave wallet or custom signature type
*/
createSourceTx(sourceData: SourceData, wallet: ArWallet | SignatureType): Promise<Transaction>;
createSourceTx(sourceData: SourceData, wallet: ArWallet | CustomSignature): Promise<Transaction>;
/**
* allows to save contract source

View File

@@ -1,8 +1,8 @@
/* eslint-disable */
import Arweave from 'arweave';
import Transaction from 'arweave/node/lib/transaction';
import { Signature, SignatureType } from '../../../contract/Signature';
import { WarpFetchWrapper } from '../../../core/WarpFetchWrapper';
import { Signature, CustomSignature } from '../../../contract/Signature';
import { SmartWeaveTags } from '../../../core/SmartWeaveTags';
import { Warp } from '../../../core/Warp';
import { WARP_GW_URL } from '../../../core/WarpFactory';
@@ -182,7 +182,7 @@ export class DefaultCreateContract implements CreateContract {
}
}
async createSourceTx(sourceData: SourceData, wallet: ArWallet | SignatureType): Promise<Transaction> {
async createSourceTx(sourceData: SourceData, wallet: ArWallet | CustomSignature): Promise<Transaction> {
return this.source.createSourceTx(sourceData, wallet);
}

View File

@@ -9,7 +9,7 @@ import { LoggerFactory } from '../../../logging/LoggerFactory';
import { Source } from '../Source';
import { Buffer } from 'redstone-isomorphic';
import { Warp } from '../../../core/Warp';
import { Signature, SignatureType } from '../../../contract/Signature';
import { Signature, CustomSignature } from '../../../contract/Signature';
import Transaction from 'arweave/node/lib/transaction';
import { WARP_GW_URL } from '../../../core/WarpFactory';
import { TagsParser } from '../../../core/modules/impl/TagsParser';
@@ -32,9 +32,9 @@ export class SourceImpl implements Source {
private readonly logger = LoggerFactory.INST.create('Source');
private signature: Signature;
constructor(private readonly warp: Warp) {}
constructor(private readonly warp: Warp) { }
async createSourceTx(sourceData: SourceData, wallet: ArWallet | SignatureType): Promise<Transaction> {
async createSourceTx(sourceData: SourceData, wallet: ArWallet | CustomSignature): Promise<Transaction> {
this.logger.debug('Creating new contract source');
const { src, wasmSrcCodeDir, wasmGlueCode } = sourceData;
@@ -235,7 +235,7 @@ function dummyImports(moduleImports: WebAssembly.ModuleImportDescriptor[]) {
if (!Object.prototype.hasOwnProperty.call(imports, moduleImport.module)) {
imports[moduleImport.module] = {};
}
imports[moduleImport.module][moduleImport.name] = function () {};
imports[moduleImport.module][moduleImport.name] = function () { };
});
return imports;

View File

@@ -28,7 +28,7 @@ import {
} from './WarpPlugin';
import { SortKeyCache } from '../cache/SortKeyCache';
import { ContractDefinition, SrcCache } from './ContractDefinition';
import { SignatureType } from '../contract/Signature';
import { CustomSignature } from '../contract/Signature';
import { SourceData } from '../contract/deploy/impl/SourceImpl';
import Transaction from 'arweave/node/lib/transaction';
@@ -97,7 +97,7 @@ export class Warp {
return await this.createContract.register(id, bundlrNode);
}
async createSourceTx(sourceData: SourceData, wallet: ArWallet | SignatureType): Promise<Transaction> {
async createSourceTx(sourceData: SourceData, wallet: ArWallet | CustomSignature): Promise<Transaction> {
return await this.createContract.createSourceTx(sourceData, wallet);
}