Rc/evm signature (#249)

* feat: allow signing function only for bundled txs

* fix: after ppe review

* feat: add transaction verification

* feat: warp plugins system

* chore: removing lodash dep

* feat: isEvmSigned verification

* chore: useFastCopy fix in tests

* feat: evm signature - minor fixes

* fix: try-catch for evm sig verification

* v1.2.14-beta.5

* fix: await for sig verification

* v1.2.14-beta.6

* chore: restore original package version

Co-authored-by: asiaziola <ziola.jm@gmail.com>
This commit is contained in:
just_ppe
2022-11-07 15:16:33 +01:00
committed by GitHub
parent 9335023824
commit ef6a445a2e
20 changed files with 3194 additions and 169 deletions

View File

@@ -26,11 +26,11 @@ import { sleep } from '../utils/utils';
import {
Contract,
BenchmarkStats,
SigningFunction,
CurrentTx,
WriteInteractionOptions,
WriteInteractionResponse,
InnerCallData
InnerCallData,
Signature
} from './Contract';
import { Tags, ArTransfer, emptyTransfer, ArWallet } from './deploy/CreateContract';
import { SourceData, SourceImpl } from './deploy/impl/SourceImpl';
@@ -58,7 +58,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
/**
* wallet connected to this contract
*/
protected signer?: SigningFunction;
protected signature?: Signature;
constructor(
private readonly _contractTxId: string,
@@ -207,7 +207,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
options?: WriteInteractionOptions
): Promise<WriteInteractionResponse | null> {
this.logger.info('Write interaction', { input, options });
if (!this.signer) {
if (!this.signature) {
throw new Error("Wallet not connected. Use 'connect' method first.");
}
const { arweave, interactionsLoader, environment } = this.warp;
@@ -221,6 +221,12 @@ export class HandlerBasedContract<State> implements Contract<State> {
const bundleInteraction = interactionsLoader.type() == 'warp' && !effectiveDisableBundling;
if (this.signature.signatureType !== 'arweave' && !bundleInteraction) {
throw new Error(
`Unable to use signing function of type: ${this.signature.signatureType} when not in mainnet environment or bundling is disabled.`
);
}
if (
bundleInteraction &&
effectiveTransfer.target != emptyTransfer.target &&
@@ -369,7 +375,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
const interactionTx = await createInteractionTx(
this.warp.arweave,
this.signer,
this.signature.signer,
this._contractTxId,
input,
tags,
@@ -389,12 +395,27 @@ export class HandlerBasedContract<State> implements Contract<State> {
return this._callStack;
}
connect(signer: ArWallet | SigningFunction): Contract<State> {
if (typeof signer == 'function') {
this.signer = signer;
connect(signature: ArWallet | Signature): Contract<State> {
if (this.isSignatureType(signature)) {
if (
signature.signatureType !== 'arweave' &&
(!(this.warp.environment == 'mainnet') || !(this.warp.interactionsLoader.type() == 'warp'))
) {
throw new Error(
`Unable to use signing function of type: ${signature.signatureType} when not in mainnet environment or bundling is disabled.`
);
} else {
this.signature = {
signer: signature.signer,
signatureType: signature.signatureType
};
}
} else {
this.signer = async (tx: Transaction) => {
await this.warp.arweave.transactions.sign(tx, signer);
this.signature = {
signer: async (tx: Transaction) => {
await this.warp.arweave.transactions.sign(tx, signature);
},
signatureType: 'arweave'
};
}
return this;
@@ -539,7 +560,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
): Promise<InteractionResult<State, View>> {
this.logger.info('Call contract input', input);
this.maybeResetRootContract();
if (!this.signer) {
if (!this.signature) {
this.logger.warn('Wallet not set.');
}
const { arweave, stateEvaluator } = this.warp;
@@ -553,7 +574,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
let effectiveCaller;
if (caller) {
effectiveCaller = caller;
} else if (this.signer) {
} else if (this.signature) {
// we're creating this transaction just to call the signing function on it
// - and retrieve the caller/owner
const dummyTx = await arweave.createTransaction({
@@ -561,7 +582,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
reward: '72600854',
last_tx: 'p7vc1iSP6bvH_fCeUFa9LqoV5qiyW-jdEKouAT0XMoSwrNraB9mgpi29Q10waEpO'
});
await this.signer(dummyTx);
await this.signature.signer(dummyTx);
effectiveCaller = await arweave.wallets.ownerToAddress(dummyTx.owner);
} else {
effectiveCaller = '';
@@ -586,7 +607,7 @@ export class HandlerBasedContract<State> implements Contract<State> {
this.logger.debug('interaction', interaction);
const tx = await createInteractionTx(
arweave,
this.signer,
this.signature?.signer,
this._contractTxId,
input,
tags,
@@ -746,13 +767,13 @@ export class HandlerBasedContract<State> implements Contract<State> {
}
async save(sourceData: SourceData): Promise<any> {
if (!this.signer) {
if (!this.signature) {
throw new Error("Wallet not connected. Use 'connect' method first.");
}
const { arweave } = this.warp;
const source = new SourceImpl(arweave);
const srcTx = await source.save(sourceData, this.signer);
const srcTx = await source.save(sourceData, this.signature.signer);
return srcTx.id;
}
@@ -760,4 +781,8 @@ export class HandlerBasedContract<State> implements Contract<State> {
get rootSortKey(): string {
return this._rootSortKey;
}
private isSignatureType(signature: ArWallet | Signature): signature is Signature {
return (signature as Signature).signer !== undefined;
}
}