Skip to content

Commit

Permalink
updating version
Browse files Browse the repository at this point in the history
updating readme, src, and tests to generalize chain id to a metadata field
  • Loading branch information
StoyanD committed Mar 5, 2024
1 parent 7c13ec4 commit 6f19dc1
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 36 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ The 2D nonce is devided into 2 parts. It is 256 bits long, with 192 bits reserve

`nonce-2d = [192 key | 64 seq]`

The key part of the nonce is derived from the destination chain and address that the sender wants to send tokens too.
The key portion of the nonce consists of the 192 bit eth address of the sender and a 32 bit slot that can be used to encode transaction metadata. In cases where that metadata you want to encode exceeds the 32 bits limit, you can encode an UID instead which can be used to look up the metadata in another location.

`key = [32 bit chain| 160 bit eth address]`

To generate the key for a given address and destination chain id:
To generate the key for a given `(address, metadata) = ('0xe7f1725e7734ce288f8367e1bb143e90bb3f0512', '5')`:

`Nonce2D.getHexKeyForDestination('0xe7f1725e7734ce288f8367e1bb143e90bb3f0512', 5)`
`Nonce2D.getHexKeyForDestination('0xe7f1725e7734ce288f8367e1bb143e90bb3f0512', '5')`

To parse a 2d nonce that is already on chain:

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@beamnetwork/nonce-2d",
"version": "0.0.10",
"version": "1.0.0",
"description": "",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
Expand Down
39 changes: 20 additions & 19 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export const NONCE_2D_SEQ_BIT_LENGTH = 64 // 8*8
// Bit length of the Address
export const NONCE_2D_KEY_ADDRESS_BIT_LENGTH = 160 // 20*8

// Bit length of the Chain
export const NONCE_2D_KEY_CHAIN_BIT_LENGTH = 32 // 4*8
// Bit length of the Meta data
export const NONCE_2D_KEY_META_DATA_BIT_LENGTH = 32 // 4*8

// Radix for hex
const HEX_RADIS = 16
Expand All @@ -22,20 +22,20 @@ const HEX_RADIS = 16
* @param seq The sequence as a hex string
*/
export class Nonce2D {
// the key is the first 192 bits of the 256 bit Nonce2D, it includes the address and chain id
// the key is the first 192 bits of the 256 bit Nonce2D, it includes the address and meta data
private _key: string
// the sequence number is the last 64 bits of the 256 bit Nonce2D
private _seq: string
// the chain is the first 32 bits of the key
private _chain: string
// the address is the 160 bits of the key, following the _chain bits
// the meta data is the first 32 bits of the key
private _meta: string
// the address is the 160 bits of the key, following the _meta bits
private _address: string

private constructor(hexNonce2D: string) {
hexNonce2D = include0x(hexNonce2D)
const { key, chain, address } = this.getKeyHex(BigInt(hexNonce2D))
const { key, meta, address } = this.getKeyHex(BigInt(hexNonce2D))
this._key = key
this._chain = chain
this._meta = meta
this._address = address

this._seq = this.getSequenceHex(BigInt(hexNonce2D))
Expand Down Expand Up @@ -63,7 +63,7 @@ export class Nonce2D {
}

/**
* Takes a onchain 2d nonce hex string and converts it to a Nonce2D object
* Takes a on-chain 2d nonce hex string and converts it to a Nonce2D object
*
* @param hexNonce2D The 256 bit Nonce2D as a hex string
* @returns
Expand All @@ -75,7 +75,7 @@ export class Nonce2D {
/**
* Generates a sequence number for a given hex key and sequence number
*
* @param hexKey the 192 bit hex key containing the chain and address
* @param hexKey the 192 bit hex key containing the meta data and address
* @param seq the 64 bit sequence number or defaults to 0 if not provided
* @returns
*/
Expand All @@ -89,12 +89,13 @@ export class Nonce2D {
* to look up the full nonce on-chain for the wallet.
*
* @param ethAddress the destination address in the key(not the address of the 4337 wallet)
* @param chainID the destination chain id in the key
* @param meta the meta data to encode in the key
* @returns the 192 bit hex key for the destination address-chain pair
*/
static getHexKeyForDestination(ethAddress: string, chainID: number): string {
static getHexKeyForDestination(ethAddress: string, meta: string): string {
ethAddress = stripOx(ethAddress)
return ('0x' + chainID.toString(HEX_RADIS) + ethAddress).toLocaleLowerCase()
meta = stripOx(meta)
return ('0x' + meta + ethAddress).toLocaleLowerCase()
}

/**
Expand All @@ -111,9 +112,9 @@ export class Nonce2D {
return this._key
}

// Returns the (up to) 32 bit chain as a hex string
get chain(): string {
return this._chain
// Returns the (up to) 32 bit meta data as a hex string
get meta(): string {
return this._meta
}

// Returns the 160 bit address as a hex string
Expand All @@ -132,18 +133,18 @@ export class Nonce2D {
*/
private getKeyHex(hexNonce2D: bigint): {
key: string
chain: string
meta: string
address: string
} {
const key = this.getKeyNumber(hexNonce2D)
const chain = key >> BigInt(NONCE_2D_KEY_ADDRESS_BIT_LENGTH)
const meta = key >> BigInt(NONCE_2D_KEY_ADDRESS_BIT_LENGTH)
const address = Nonce2D.mask256BitNumber(
key,
NONCE_2D_KEY_ADDRESS_BIT_LENGTH,
)
return {
key: this.toHex(key),
chain: this.toHex(chain),
meta: this.toHex(meta),
address: this.toHex(address),
}
}
Expand Down
23 changes: 10 additions & 13 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ enum ChainID {
OptimismGoerli = 420,
}

// Test chain id
const testChain = ChainID.EthereumGoerli
// Test meta data
const testMeta = '0x' + ChainID.EthereumGoerli.toString(16)
// 256 bit nonce = 32 bytes
const testsHexNonce =
'0x5e7f1725e7734ce288f8367e1bb143e90bb3f05120000000000000001'
// 192 bit key = 4 bytes for chainID = 5(00000005), 20 bytes for address(e7f1725E7734CE288F8367e1Bb143E90bb3F0512)
// 192 bit key = 4 bytes for meta = 5(00000005), 20 bytes for address(e7f1725E7734CE288F8367e1Bb143E90bb3F0512)
const testsKey = '0x5e7f1725e7734ce288f8367e1bb143e90bb3f0512'
// 64 bit sequence = 8 bytes
const testsSeq = '0x1'
Expand All @@ -32,38 +32,35 @@ describe('Nonce2D tests', () => {
const n = Nonce2D.fromHexNonce(testsHexNonce)
expect(n.key).toBe(testsKey)
expect(n.seq).toBe(testsSeq)
expect(Number(n.chain)).toBe(testChain)
expect(n.meta).toBe(testMeta)
expect(n.address).toBe(testsAddress)
})
})

describe('fromHexKey tests', () => {
it('should create a Nonce2D object from a valid key', () => {
const n = Nonce2D.fromHexKey(testsKey, 1)
expect(Number(n.chain)).toBe(testChain)
expect(n.meta).toBe(testMeta)
expect(n.address).toBe(testsAddress)
expect(n.seq).toBe(testsSeq)
})

it('should create a Nonce2D object from a valid key with optional seq', () => {
const seq: number = 13
const n = Nonce2D.fromHexKey(testsKey, seq)
expect(Number(n.chain)).toBe(testChain)
expect(n.meta).toBe(testMeta)
expect(n.address).toBe(testsAddress)
expect(n.seq).toBe('0x' + seq.toString(16))
})
})

describe('getHexKeyForDestination tests', () => {
it('should create a key from an address and chain', () => {
const hexKey = Nonce2D.getHexKeyForDestination(
testsAddress,
ChainID.EthereumGoerli,
)
const hexKey = Nonce2D.getHexKeyForDestination(testsAddress, testMeta)
expect(hexKey).toBe(testsKey)

const nonce2D = Nonce2D.fromHexKey(hexKey)
expect(Number(nonce2D.chain)).toBe(ChainID.EthereumGoerli)
expect(nonce2D.meta).toBe(testMeta)
expect(nonce2D.address).toBe(testsAddress)
})
})
Expand All @@ -73,13 +70,13 @@ describe('Nonce2D tests', () => {
const n = Nonce2D.fromHexNonce(testsHexNonce)
const seq = Number(n.seq)
const key = Number(n.key)
const chain = Number(n.chain)
const meta = Number(n.meta)
const address = Number(n.address)
n.increment()
expect(Number(n.seq)).toBe(seq + 1)
//nothing else should change
expect(Number(n.key)).toBe(key)
expect(Number(n.chain)).toBe(chain)
expect(Number(n.meta)).toBe(meta)
expect(Number(n.address)).toBe(address)
})
})
Expand Down

0 comments on commit 6f19dc1

Please sign in to comment.