Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(eth signer): use a unique anchor in ans-104 headers #311

Merged
merged 5 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/common/contracts/ao-process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import { connect } from '@permaweb/aoconnect';

import { AOContract, AoClient, AoSigner } from '../../types/index.js';
import { getRandomText } from '../../utils/base64.js';
import { safeDecode } from '../../utils/json.js';
import { version } from '../../version.js';
import { WriteInteractionError } from '../error.js';
Expand Down Expand Up @@ -130,18 +131,22 @@ export class AOProcess implements AOContract {
});

// TODO: do a read as a dry run to check if the process supports the action
// anchor is a random text produce non-deterministic messages IDs when deterministic signers are provided (ETH)
const anchor = getRandomText(32);

const messageId = await this.ao.message({
process: this.processId,
// TODO: any other default tags we want to add?
tags: [...tags, { name: 'AR-IO-SDK', value: version }],
data,
signer,
anchor,
});

this.logger.debug(`Sent message to process`, {
messageId,
processId: this.processId,
anchor,
});

// check the result of the send interaction
Expand Down
11 changes: 10 additions & 1 deletion src/utils/base64.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createHash } from 'crypto';
import { createHash, randomBytes } from 'crypto';

// safely encodes and decodes base64url strings to and from buffers
const BASE64_CHAR_62 = '+';
Expand Down Expand Up @@ -53,3 +53,12 @@ export function toB64Url(buffer: Buffer): string {
export function sha256B64Url(input: Buffer): string {
return toB64Url(createHash('sha256').update(Uint8Array.from(input)).digest());
}

export function getRandomText(length = 32): string {
// Generate a buffer of random bytes
const buffer = randomBytes(length);
// Convert bytes to hexadecimal string
return Array.from(buffer, (byte) => byte.toString(16).padStart(2, '0'))
.join('')
.slice(0, length);
}
18 changes: 17 additions & 1 deletion tests/unit/b64.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';

import { fromB64Url, toB64Url } from '../../src/utils/base64.js';
import { fromB64Url, getRandomText, toB64Url } from '../../src/utils/base64.js';

describe('b64utils', () => {
it('should convert various strings to base64url and back', () => {
Expand Down Expand Up @@ -65,4 +65,20 @@ describe('b64utils', () => {
);
}
});

it('should generate random text', () => {
const randomText = getRandomText();
const randomText2 = getRandomText();
assert.strictEqual(randomText.length, 32);
assert.strictEqual(randomText2.length, 32);

assert.notStrictEqual(randomText, randomText2);

const smallRandomText = getRandomText(16);
const smallRandomText2 = getRandomText(16);
assert.strictEqual(smallRandomText.length, 16);
assert.strictEqual(smallRandomText2.length, 16);

assert.notStrictEqual(smallRandomText, smallRandomText2);
});
});
Loading