Skip to content

Commit bff81fb

Browse files
authored
Merge branch 'master' into feature/get-latest-commit-hash-for-shiva
2 parents f9233f5 + 683a0d6 commit bff81fb

File tree

3 files changed

+359
-0
lines changed

3 files changed

+359
-0
lines changed

local-tests/test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ import { testUseInvalidLitActionIpfsCodeToGenerateSessionSigs } from './tests/te
4444
import { testSolAuthSigToEncryptDecryptString } from './tests/testSolAuthSigToEncryptDecryptString';
4545
import { testEthAuthSigToEncryptDecryptString } from './tests/testEthAuthSigToEncryptDecryptString';
4646
import { testCosmosAuthSigToEncryptDecryptString } from './tests/testCosmosAuthSigToEncryptDecryptString';
47+
import { testKeccakEip1271AuthSigToEncryptDecryptString } from './tests/testKeccakEip1271AuthSigToEncryptDecryptString';
48+
import { testShaEip1271AuthSigToEncryptDecryptString } from './tests/testShaEip1271AuthSigToEncryptDecryptString';
4749
import { testPkpEthersWithEoaSessionSigsToSignMessage } from './tests/testPkpEthersWithEoaSessionSigsToSignMessage';
4850
import { testPkpEthersWithEoaSessionSigsToSignWithAuthContext } from './tests/testPkpEthersWithEoaSessionSigsToSignWithAuthContext';
4951
import { testPkpEthersWithEoaSessionSigsToEthSign } from './tests/testPkpEthersWithEoaSessionSigsToEthSign';
@@ -232,6 +234,11 @@ setLitActionsCodeToLocal();
232234
testCosmosAuthSigToEncryptDecryptString,
233235
};
234236

237+
const eip1271AuthSigTests = {
238+
testKeccakEip1271AuthSigToEncryptDecryptString,
239+
testShaEip1271AuthSigToEncryptDecryptString,
240+
};
241+
235242
const pkpEthersTest = {
236243
eoaSessionSigs: {
237244
testPkpEthersWithEoaSessionSigsToSignWithAuthContext,
@@ -294,6 +301,7 @@ setLitActionsCodeToLocal();
294301
...litActionIpfsIdSessionSigsTests,
295302
...capacityDelegationTests,
296303
...bareAuthSigTests,
304+
...eip1271AuthSigTests,
297305

298306
...pkpEthersTest.eoaSessionSigs,
299307
...pkpEthersTest.pkpSessionSigs,
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import { AuthSig, BaseSiweMessage, ILitNodeClient } from '@lit-protocol/types';
2+
import { AccessControlConditions } from 'local-tests/setup/accs/accs';
3+
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
4+
import { log } from '@lit-protocol/misc';
5+
import { encryptString, decryptToString } from '@lit-protocol/encryption';
6+
import { CENTRALISATION_BY_NETWORK } from '@lit-protocol/constants';
7+
import { createSiweMessage } from '@lit-protocol/auth-helpers';
8+
import { hashMessage } from 'ethers/lib/utils';
9+
import { ethers } from 'ethers';
10+
import { createHash } from 'crypto';
11+
12+
/**
13+
* Test Commands:
14+
* ✅ NETWORK=datil-dev yarn test:local --filter=testKeccakEip1271AuthSigToEncryptDecryptString
15+
* ✅ NETWORK=datil-test yarn test:local --filter=testKeccakEip1271AuthSigToEncryptDecryptString
16+
* ✅ NETWORK=custom yarn test:local --filter=testKeccakEip1271AuthSigToEncryptDecryptString
17+
*/
18+
export const testKeccakEip1271AuthSigToEncryptDecryptString = async (
19+
devEnv: TinnyEnvironment
20+
) => {
21+
const dataToEncrypt = 'Decrypted from EIP1271 AuthSig';
22+
const contractAddress = '0x88105De2349f59767278Fd15c0858f806c08d615';
23+
const deployerAddress = '0x0b1C5E9E82393AD5d1d1e9a498BF7bAAC13b31Ee'; // No purpose other than to be a random address
24+
const abi = [
25+
'function setTempOwner(address _tempOwner) external',
26+
'function getTempOwner() external view returns (address)',
27+
'function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4)',
28+
];
29+
30+
const alice = await devEnv.createRandomPerson();
31+
if (CENTRALISATION_BY_NETWORK[devEnv.network] === 'decentralised') {
32+
// The capacity credits NFT owner automatically uses the capacity credits
33+
// to pay for the encryption
34+
await alice.mintCapacityCreditsNFT();
35+
}
36+
37+
let accs = AccessControlConditions.getEmvBasicAccessControlConditions({
38+
userAddress: contractAddress,
39+
});
40+
accs[0].chain = 'yellowstone'; // Contract deployed on Yellowstone
41+
42+
const encryptRes = await encryptString(
43+
{
44+
accessControlConditions: accs,
45+
dataToEncrypt,
46+
},
47+
devEnv.litNodeClient as unknown as ILitNodeClient
48+
);
49+
50+
// log('encryptRes:', encryptRes);
51+
52+
if (!encryptRes.ciphertext) {
53+
throw new Error(`Expected "ciphertext" in encryptRes`);
54+
}
55+
56+
if (!encryptRes.dataToEncryptHash) {
57+
throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
58+
}
59+
60+
// Craft the SiweMessage to be hashed & signed
61+
const siweMessage = await createSiweMessage<BaseSiweMessage>({
62+
nonce: await devEnv.litNodeClient.getLatestBlockhash(),
63+
walletAddress: alice.wallet.address,
64+
});
65+
66+
const siweSignature = await alice.wallet.signMessage(siweMessage);
67+
log('siweSignature: ', siweSignature);
68+
69+
// Internally generate from wallet.signMessage
70+
const hash = hashMessage(siweMessage);
71+
const hashUint8Array = ethers.utils.arrayify(hash);
72+
log('hash:', hash);
73+
log('hashUint8Array: ', hashUint8Array); // Match it against the hash done on the nodes before calling verifySignature()
74+
75+
const eip1271AuthSig: AuthSig = {
76+
address: contractAddress,
77+
sig: siweSignature,
78+
derivedVia: 'EIP1271',
79+
signedMessage: siweMessage,
80+
};
81+
82+
// log(eip1271AuthSig);
83+
84+
// Test from the contract
85+
const contract = new ethers.Contract(contractAddress, abi, alice.wallet);
86+
const setDeployerAsTempOwnerTx = await contract.setTempOwner(deployerAddress);
87+
await setDeployerAsTempOwnerTx.wait();
88+
89+
log(
90+
'0. isValidSignature should FAIL since Alice (AuthSig.sig) is not the tempOwner yet'
91+
);
92+
try {
93+
const isValid = await contract.isValidSignature(hash, siweSignature);
94+
if (isValid === '0x1626ba7e') {
95+
throw new Error(
96+
`Expected isValidSignature to be 0xffffffff but got ${isValid}`
97+
);
98+
}
99+
} catch (error) {
100+
log('Error calling isValidSignature:', error);
101+
throw error;
102+
}
103+
104+
try {
105+
const _decryptRes = await decryptToString(
106+
{
107+
accessControlConditions: accs,
108+
ciphertext: encryptRes.ciphertext,
109+
dataToEncryptHash: encryptRes.dataToEncryptHash,
110+
authSig: eip1271AuthSig,
111+
chain: 'yellowstone', // Deployed chain
112+
},
113+
devEnv.litNodeClient as unknown as ILitNodeClient
114+
);
115+
} catch (error) {
116+
if (
117+
!error.message.includes('NodeContractAuthsigUnauthorized') ||
118+
!error.message.includes('Access control failed for Smart contract') ||
119+
!error.message.includes(
120+
'validation error: Authsig failed for contract 0x88105De2349f59767278Fd15c0858f806c08d615. Return value was ffffffff.'
121+
)
122+
) {
123+
throw new Error(
124+
`Expected error message to contain specific EIP1271 validation failure, but got: ${error}`
125+
);
126+
}
127+
}
128+
129+
// Should PASS now
130+
log('1. Setting temp owner...');
131+
const setTempOwnerTx = await contract.setTempOwner(alice.wallet.address);
132+
await setTempOwnerTx.wait();
133+
log('Set tempOwner transaction hash: ', setTempOwnerTx.hash);
134+
135+
const tempOwner = await contract.getTempOwner();
136+
if (tempOwner.toLowerCase() !== alice.wallet.address.toLowerCase()) {
137+
throw new Error(
138+
`Expected temp owner to be ${alice.wallet.address} but got ${tempOwner}`
139+
);
140+
}
141+
142+
log('2. Checking isValidSignature...');
143+
try {
144+
const isValid = await contract.isValidSignature(hash, siweSignature);
145+
if (isValid !== '0x1626ba7e') {
146+
throw new Error(
147+
`Expected isValidSignature to be 0x1626ba7e but got ${isValid}`
148+
);
149+
}
150+
} catch (error) {
151+
log('Error calling isValidSignature:', error);
152+
throw error;
153+
}
154+
155+
// -- Decrypt the encrypted string
156+
const decryptRes = await decryptToString(
157+
{
158+
accessControlConditions: accs,
159+
ciphertext: encryptRes.ciphertext,
160+
dataToEncryptHash: encryptRes.dataToEncryptHash,
161+
authSig: eip1271AuthSig,
162+
chain: 'yellowstone', // Deployed chain
163+
},
164+
devEnv.litNodeClient as unknown as ILitNodeClient
165+
);
166+
167+
if (decryptRes !== dataToEncrypt) {
168+
throw new Error(
169+
`Expected decryptRes to be ${dataToEncrypt} but got ${decryptRes}`
170+
);
171+
}
172+
173+
log('✅ decryptRes:', decryptRes);
174+
};
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import { AuthSig, BaseSiweMessage, ILitNodeClient } from '@lit-protocol/types';
2+
import { AccessControlConditions } from 'local-tests/setup/accs/accs';
3+
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
4+
import { log } from '@lit-protocol/misc';
5+
import { encryptString, decryptToString } from '@lit-protocol/encryption';
6+
import { CENTRALISATION_BY_NETWORK } from '@lit-protocol/constants';
7+
import { createSiweMessage } from '@lit-protocol/auth-helpers';
8+
import { joinSignature } from 'ethers/lib/utils';
9+
import { ethers } from 'ethers';
10+
import { createHash } from 'crypto';
11+
12+
/**
13+
* Test Commands:
14+
* ✅ NETWORK=datil-dev yarn test:local --filter=testShaEip1271AuthSigToEncryptDecryptString
15+
* ✅ NETWORK=datil-test yarn test:local --filter=testShaEip1271AuthSigToEncryptDecryptString
16+
* ✅ NETWORK=custom yarn test:local --filter=testShaEip1271AuthSigToEncryptDecryptString
17+
*/
18+
export const testShaEip1271AuthSigToEncryptDecryptString = async (
19+
devEnv: TinnyEnvironment
20+
) => {
21+
const dataToEncrypt = 'Decrypted from EIP1271 AuthSig';
22+
const contractAddress = '0x88105De2349f59767278Fd15c0858f806c08d615';
23+
const deployerAddress = '0x0b1C5E9E82393AD5d1d1e9a498BF7bAAC13b31Ee'; // No purpose other than to be a random address
24+
const abi = [
25+
'function setTempOwner(address _tempOwner) external',
26+
'function getTempOwner() external view returns (address)',
27+
'function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4)',
28+
];
29+
30+
const alice = await devEnv.createRandomPerson();
31+
if (CENTRALISATION_BY_NETWORK[devEnv.network] === 'decentralised') {
32+
// The capacity credits NFT owner automatically uses the capacity credits
33+
// to pay for the encryption
34+
await alice.mintCapacityCreditsNFT();
35+
}
36+
37+
let accs = AccessControlConditions.getEmvBasicAccessControlConditions({
38+
userAddress: contractAddress,
39+
});
40+
accs[0].chain = 'yellowstone'; // Contract deployed on Yellowstone
41+
42+
const encryptRes = await encryptString(
43+
{
44+
accessControlConditions: accs,
45+
dataToEncrypt,
46+
},
47+
devEnv.litNodeClient as unknown as ILitNodeClient
48+
);
49+
50+
// log('encryptRes:', encryptRes);
51+
52+
if (!encryptRes.ciphertext) {
53+
throw new Error(`Expected "ciphertext" in encryptRes`);
54+
}
55+
56+
if (!encryptRes.dataToEncryptHash) {
57+
throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
58+
}
59+
60+
// Craft the SiweMessage to be hashed & signed
61+
const siweMessage = await createSiweMessage<BaseSiweMessage>({
62+
nonce: await devEnv.litNodeClient.getLatestBlockhash(),
63+
walletAddress: alice.wallet.address,
64+
});
65+
66+
// Explicitly SHA256 hash the SIWE message
67+
const hash = createHash('sha256').update(siweMessage).digest();
68+
const hashHex = '0x' + hash.toString('hex');
69+
const hashUint8Array = ethers.utils.arrayify(hashHex);
70+
log('hash:', hashHex);
71+
log('hashUint8Array: ', hashUint8Array); // Match it against the hash done on the nodes before calling verifySignature()
72+
73+
const siweSignature = joinSignature(
74+
alice.wallet._signingKey().signDigest(hashHex)
75+
);
76+
log('siweSignature: ', siweSignature);
77+
78+
const eip1271AuthSig: AuthSig = {
79+
address: contractAddress,
80+
sig: siweSignature,
81+
derivedVia: 'EIP1271_SHA256',
82+
signedMessage: siweMessage,
83+
};
84+
85+
// log(eip1271AuthSig);
86+
87+
// Test from the contract
88+
const contract = new ethers.Contract(contractAddress, abi, alice.wallet);
89+
const setDeployerAsTempOwnerTx = await contract.setTempOwner(deployerAddress);
90+
await setDeployerAsTempOwnerTx.wait();
91+
92+
log(
93+
'0. isValidSignature should FAIL since Alice (AuthSig.sig) is not the tempOwner yet'
94+
);
95+
try {
96+
const isValid = await contract.isValidSignature(hash, siweSignature);
97+
if (isValid === '0x1626ba7e') {
98+
throw new Error(
99+
`Expected isValidSignature to be 0xffffffff but got ${isValid}`
100+
);
101+
}
102+
} catch (error) {
103+
log('Error calling isValidSignature:', error);
104+
throw error;
105+
}
106+
107+
try {
108+
const _decryptRes = await decryptToString(
109+
{
110+
accessControlConditions: accs,
111+
ciphertext: encryptRes.ciphertext,
112+
dataToEncryptHash: encryptRes.dataToEncryptHash,
113+
authSig: eip1271AuthSig,
114+
chain: 'yellowstone', // Deployed chain
115+
},
116+
devEnv.litNodeClient as unknown as ILitNodeClient
117+
);
118+
} catch (error) {
119+
if (
120+
!error.message.includes('NodeContractAuthsigUnauthorized') ||
121+
!error.message.includes('Access control failed for Smart contract') ||
122+
!error.message.includes(
123+
'validation error: Authsig failed for contract 0x88105De2349f59767278Fd15c0858f806c08d615. Return value was ffffffff.'
124+
)
125+
) {
126+
throw new Error(
127+
`Expected error message to contain specific EIP1271 validation failure, but got: ${error}`
128+
);
129+
}
130+
}
131+
132+
// Should PASS now
133+
log('1. Setting temp owner...');
134+
const setTempOwnerTx = await contract.setTempOwner(alice.wallet.address);
135+
await setTempOwnerTx.wait();
136+
log('Set tempOwner transaction hash: ', setTempOwnerTx.hash);
137+
138+
const tempOwner = await contract.getTempOwner();
139+
if (tempOwner.toLowerCase() !== alice.wallet.address.toLowerCase()) {
140+
throw new Error(
141+
`Expected temp owner to be ${alice.wallet.address} but got ${tempOwner}`
142+
);
143+
}
144+
145+
log('2. Checking isValidSignature...');
146+
try {
147+
const isValid = await contract.isValidSignature(hash, siweSignature);
148+
if (isValid !== '0x1626ba7e') {
149+
throw new Error(
150+
`Expected isValidSignature to be 0x1626ba7e but got ${isValid}`
151+
);
152+
}
153+
} catch (error) {
154+
log('Error calling isValidSignature:', error);
155+
throw error;
156+
}
157+
158+
// -- Decrypt the encrypted string
159+
const decryptRes = await decryptToString(
160+
{
161+
accessControlConditions: accs,
162+
ciphertext: encryptRes.ciphertext,
163+
dataToEncryptHash: encryptRes.dataToEncryptHash,
164+
authSig: eip1271AuthSig,
165+
chain: 'yellowstone', // Deployed chain
166+
},
167+
devEnv.litNodeClient as unknown as ILitNodeClient
168+
);
169+
170+
if (decryptRes !== dataToEncrypt) {
171+
throw new Error(
172+
`Expected decryptRes to be ${dataToEncrypt} but got ${decryptRes}`
173+
);
174+
}
175+
176+
log('✅ decryptRes:', decryptRes);
177+
};

0 commit comments

Comments
 (0)