11import { Address , Bytes , Hash , Hex } from 'ox'
2- import { Attestation , encode , encodeForJson , fromParsed , toJson } from './attestation.js'
32import { MAX_PERMISSIONS_COUNT } from './permission.js'
43import {
4+ decodeSessionsTopology ,
55 encodeSessionsTopology ,
66 getIdentitySigners ,
77 isCompleteSessionsTopology ,
88 minimiseSessionsTopology ,
99 SessionsTopology ,
1010} from './session-config.js'
1111import { RSY } from './signature.js'
12- import { minBytesFor , packRSY } from './utils.js'
13- import { Payload } from './index.js'
12+ import { minBytesFor , packRSY , unpackRSY } from './utils.js'
13+ import { Attestation , Payload } from './index.js'
1414
1515export type ImplicitSessionCallSignature = {
16- attestation : Attestation
16+ attestation : Attestation . Attestation
1717 identitySignature : RSY
1818 sessionSignature : RSY
1919}
@@ -46,7 +46,7 @@ export function sessionCallSignatureToJson(callSignature: SessionCallSignature):
4646export function encodeSessionCallSignatureForJson ( callSignature : SessionCallSignature ) : any {
4747 if ( isImplicitSessionCallSignature ( callSignature ) ) {
4848 return {
49- attestation : encodeForJson ( callSignature . attestation ) ,
49+ attestation : Attestation . encodeForJson ( callSignature . attestation ) ,
5050 identitySignature : rsyToRsvStr ( callSignature . identitySignature ) ,
5151 sessionSignature : rsyToRsvStr ( callSignature . sessionSignature ) ,
5252 }
@@ -68,7 +68,7 @@ export function sessionCallSignatureFromJson(json: string): SessionCallSignature
6868export function sessionCallSignatureFromParsed ( decoded : any ) : SessionCallSignature {
6969 if ( decoded . attestation ) {
7070 return {
71- attestation : fromParsed ( decoded . attestation ) ,
71+ attestation : Attestation . fromParsed ( decoded . attestation ) ,
7272 identitySignature : rsyFromRsvStr ( decoded . identitySignature ) ,
7373 sessionSignature : rsyFromRsvStr ( decoded . sessionSignature ) ,
7474 }
@@ -113,7 +113,7 @@ function rsyFromRsvStr(sigStr: string): RSY {
113113 * @param identitySigner The identity signer to encode. Others will be hashed into nodes.
114114 * @returns The encoded session call signatures.
115115 */
116- export function encodeSessionCallSignatures (
116+ export function encodeSessionSignature (
117117 callSignatures : SessionCallSignature [ ] ,
118118 topology : SessionsTopology ,
119119 identitySigner : Address . Address ,
@@ -151,10 +151,12 @@ export function encodeSessionCallSignatures(
151151 // Map each call signature to its attestation index
152152 callSignatures . filter ( isImplicitSessionCallSignature ) . forEach ( ( callSig ) => {
153153 if ( callSig . attestation ) {
154- const attestationStr = toJson ( callSig . attestation )
154+ const attestationStr = Attestation . toJson ( callSig . attestation )
155155 if ( ! attestationMap . has ( attestationStr ) ) {
156156 attestationMap . set ( attestationStr , encodedAttestations . length )
157- encodedAttestations . push ( Bytes . concat ( encode ( callSig . attestation ) , packRSY ( callSig . identitySignature ) ) )
157+ encodedAttestations . push (
158+ Bytes . concat ( Attestation . encode ( callSig . attestation ) , packRSY ( callSig . identitySignature ) ) ,
159+ )
158160 }
159161 }
160162 } )
@@ -169,7 +171,7 @@ export function encodeSessionCallSignatures(
169171 for ( const callSignature of callSignatures ) {
170172 if ( isImplicitSessionCallSignature ( callSignature ) ) {
171173 // Implicit
172- const attestationStr = toJson ( callSignature . attestation )
174+ const attestationStr = Attestation . toJson ( callSignature . attestation )
173175 const attestationIndex = attestationMap . get ( attestationStr )
174176 if ( attestationIndex === undefined ) {
175177 // Unreachable
@@ -193,7 +195,83 @@ export function encodeSessionCallSignatures(
193195 return Bytes . concat ( ...parts )
194196}
195197
196- // Helper
198+ export function decodeSessionSignature ( encodedSignatures : Bytes . Bytes ) : {
199+ topology : SessionsTopology
200+ callSignatures : SessionCallSignature [ ]
201+ } {
202+ let offset = 0
203+
204+ // Parse session topology length (3 bytes)
205+ const topologyLength = Bytes . toNumber ( encodedSignatures . slice ( offset , offset + 3 ) )
206+ offset += 3
207+
208+ // Parse session topology
209+ const topologyBytes = encodedSignatures . slice ( offset , offset + topologyLength )
210+ offset += topologyLength
211+ const topology = decodeSessionsTopology ( topologyBytes )
212+
213+ // Parse attestations count (1 byte)
214+ const attestationsCount = Bytes . toNumber ( encodedSignatures . slice ( offset , offset + 1 ) )
215+ offset += 1
216+
217+ // Parse attestations and identity signatures
218+ const attestations : Attestation . Attestation [ ] = [ ]
219+ const identitySignatures : RSY [ ] = [ ]
220+
221+ for ( let i = 0 ; i < attestationsCount ; i ++ ) {
222+ // Parse attestation
223+ const attestation = Attestation . decode ( encodedSignatures . slice ( offset ) )
224+ offset += Attestation . encode ( attestation ) . length
225+ attestations . push ( attestation )
226+
227+ // Parse identity signature (64 bytes)
228+ const identitySignature = unpackRSY ( encodedSignatures . slice ( offset , offset + 64 ) )
229+ offset += 64
230+ identitySignatures . push ( identitySignature )
231+ }
232+
233+ // Parse call signatures
234+ const callSignatures : SessionCallSignature [ ] = [ ]
235+
236+ while ( offset < encodedSignatures . length ) {
237+ // Parse flag byte
238+ const flagByte = encodedSignatures [ offset ] !
239+ offset += 1
240+
241+ // Parse session signature (64 bytes)
242+ const sessionSignature = unpackRSY ( encodedSignatures . slice ( offset , offset + 64 ) )
243+ offset += 64
244+
245+ // Check if implicit (MSB set) or explicit
246+ if ( ( flagByte & 0x80 ) !== 0 ) {
247+ // Implicit call signature
248+ const attestationIndex = flagByte & 0x7f
249+ if ( attestationIndex >= attestations . length ) {
250+ throw new Error ( 'Invalid attestation index' )
251+ }
252+
253+ callSignatures . push ( {
254+ attestation : attestations [ attestationIndex ] ! ,
255+ identitySignature : identitySignatures [ attestationIndex ] ! ,
256+ sessionSignature,
257+ } )
258+ } else {
259+ // Explicit call signature
260+ const permissionIndex = flagByte
261+ callSignatures . push ( {
262+ permissionIndex : BigInt ( permissionIndex ) ,
263+ sessionSignature,
264+ } )
265+ }
266+ }
267+
268+ return {
269+ topology,
270+ callSignatures,
271+ }
272+ }
273+
274+ // Call encoding
197275
198276export function hashCallWithReplayProtection (
199277 payload : Payload . Calls ,
0 commit comments