@enbox/agent 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.mjs +9 -9
- package/dist/browser.mjs.map +3 -3
- package/dist/esm/sync-engine-level.js +220 -9
- package/dist/esm/sync-engine-level.js.map +1 -1
- package/dist/esm/sync-messages.js +126 -22
- package/dist/esm/sync-messages.js.map +1 -1
- package/dist/types/sync-engine-level.d.ts +61 -1
- package/dist/types/sync-engine-level.d.ts.map +1 -1
- package/dist/types/sync-messages.d.ts +11 -7
- package/dist/types/sync-messages.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/sync-engine-level.ts +247 -14
- package/src/sync-messages.ts +143 -25
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-messages.js","sourceRoot":"","sources":["../../src/sync-messages.ts"],"names":[],"mappings":";;;;;;;;;AAIA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"sync-messages.js","sourceRoot":"","sources":["../../src/sync-messages.ts"],"names":[],"mappings":";;;;;;;;;AAIA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEtF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,kGAAkG;AAClG,MAAM,eAAe,GAAG,OAAS,CAAC,CAAC,OAAO;AAU1C;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAAC,KAAwB;;IACnE,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,GAAG;QAC9B,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,GAAG;QACzB,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,GAAG;QACzB,CACE,CAAA,MAAA,KAAK,CAAC,KAAK,0CAAE,OAAO,CAAC,UAAU,CAAC,SAAS,MAAK,gBAAgB,CAAC,OAAO;YACtE,CAAA,MAAA,KAAK,CAAC,KAAK,0CAAE,OAAO,CAAC,UAAU,CAAC,MAAM,MAAK,aAAa,CAAC,MAAM;YAC/D,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,GAAG,CAC1B,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAgB,aAAa,CAAC,OAAuB;;QACzD,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC;QAAC,WAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,UAAgB,YAAY;yDAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAUtH;QACC,gEAAgE;QAChE,MAAM,iBAAiB,GAAuB,EAAE,CAAC;QACjD,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;gBAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;oBAAC,SAAS;gBAAC,CAAC;gBACjC,MAAM,SAAS,GAAqB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC/D,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;oBACtB,sDAAsD;oBACtD,MAAM,KAAK,GAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;oBAC1D,SAAS,CAAC,YAAY,GAAG,KAAK,CAAC;oBAC/B,SAAS,CAAC,UAAU,GAAG,IAAI,cAAc,CAAa;wBACpD,KAAK,CAAC,UAAU;4BACd,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;4BAC1B,UAAU,CAAC,KAAK,EAAE,CAAC;wBACrB,CAAC;qBACF,CAAC,CAAC;gBACL,CAAC;gBACD,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAED,qEAAqE;QACrE,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC;YACpC,CAAC,CAAC,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;YACvG,CAAC,CAAC,EAAE,CAAC;QAEP,uDAAuD;QACvD,MAAM,UAAU,GAAG,CAAC,GAAG,iBAAiB,EAAE,GAAG,OAAO,CAAC,CAAC;QAEtD,uDAAuD;QACvD,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;QAE3C,sEAAsE;QACtE,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAEjC,sEAAsE;QACtE,MAAM,gBAAgB,GAAG,CAAC,CAAC;QAC3B,IAAI,OAAO,GAAG,MAAM,CAAC;QAErB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;YAC1E,MAAM,MAAM,GAAuB,EAAE,CAAC;YAEtC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,qFAAqF;gBACrF,MAAM,UAAU,GAAG,KAAK,CAAC,YAAY;oBACnC,CAAC,CAAC,IAAI,cAAc,CAAa,EAAE,KAAK,CAAC,CAAC,IAAU,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,YAAa,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACnG,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;gBAErB,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;gBAExF,IAAI,CAAC,4BAA4B,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC7C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;YAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,qEAAqE;gBACrE,sEAAsE;gBACtE,MAAM,YAAY,GAAa,EAAE,CAAC;gBAClC,MAAM,QAAQ,GAAuB,EAAE,CAAC;gBAExC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBAC3B,IAAI,KAAK,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;wBAC5C,+DAA+D;wBAC/D,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACvB,CAAC;yBAAM,CAAC;wBACN,2DAA2D;wBAC3D,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;wBAC/C,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC;gBAED,oEAAoE;gBACpE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5B,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;oBACtI,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;gBAC9B,CAAC;gBAED,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,OAAO,GAAG,EAAE,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;CAAA;AAED;;;GAGG;AACH,SAAe,kBAAkB,CAAC,OAA2B;;QAC3D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;gBACtB,SAAS;YACX,CAAC;YAED,qEAAqE;YACrE,qEAAqE;YACrE,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,IAAI,SAAS,GAAG,CAAC,CAAC;YAClB,IAAI,iBAAiB,GAAG,KAAK,CAAC;YAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;YAE5C,IAAI,CAAC;gBACH,SAAS,CAAC;oBACR,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;oBAC5C,IAAI,IAAI,EAAE,CAAC;wBAAC,MAAM;oBAAC,CAAC;oBACpB,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC;oBAC9B,IAAI,SAAS,GAAG,eAAe,EAAE,CAAC;wBAChC,iBAAiB,GAAG,IAAI,CAAC;wBACzB,MAAM;oBACR,CAAC;oBACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,CAAC;YAED,IAAI,iBAAiB,EAAE,CAAC;gBACtB,oEAAoE;gBACpE,4CAA4C;gBAC5C,KAAK,CAAC,UAAU,GAAG,SAAS,CAAC;gBAC7B,SAAS;YACX,CAAC;YAED,kDAAkD;YAClD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;YACzC,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC;YAC7B,CAAC;YAED,KAAK,CAAC,YAAY,GAAG,MAAM,CAAC;YAC5B,kFAAkF;YAClF,KAAK,CAAC,UAAU,GAAG,IAAI,cAAc,CAAa;gBAChD,KAAK,CAAC,UAAU;oBACd,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBAC3B,UAAU,CAAC,KAAK,EAAE,CAAC;gBACrB,CAAC;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CAAA;AAED;;GAEG;AACH,MAAM,UAAgB,mBAAmB;yDAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAQjH;QACC,MAAM,OAAO,GAAuB,EAAE,CAAC;QAEvC,IAAI,iBAAqC,CAAC;QAC1C,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,CAAC;gBACH,MAAM,iBAAiB,GAAG,MAAM,cAAc,CAAC,uBAAuB,CAAC;oBACrE,YAAY,EAAG,GAAG;oBAClB,WAAW,EAAI,YAAY,CAAC,YAAY;oBACxC,WAAW;oBACX,QAAQ;oBACR,MAAM,EAAS,IAAI;iBACpB,CAAC,CAAC;gBACH,iBAAiB,GAAG,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,uFAAuF,EAAE,KAAK,CAAC,CAAC;gBAC9G,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QAED,sEAAsE;QACtE,yEAAyE;QACzE,MAAM,WAAW,GAAG,CAAC,CAAC;QACtB,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,OAAO,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC;YAC9D,MAAM,IAAI,WAAW,CAAC;YAGtB,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAO,UAAU,EAAwB,EAAE;;gBAC1F,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,iBAAiB,CAAC;oBACjD,KAAK,EAAW,KAAK;oBACrB,MAAM,EAAU,GAAG;oBACnB,MAAM,EAAU,GAAG;oBACnB,WAAW,EAAK,YAAY,CAAC,YAAY;oBACzC,UAAU,EAAM,WAAW;oBAC3B,aAAa,EAAG,EAAE,UAAU,EAAE,iBAAiB,EAAE;iBAClD,CAAC,CAAC;gBAEH,IAAI,KAAwB,CAAC;gBAC7B,IAAI,CAAC;oBACH,KAAK,IAAG,MAAM,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC;wBACrC,MAAM;wBACN,SAAS,EAAG,GAAG;wBACf,OAAO,EAAK,YAAY,CAAC,OAAO;qBACjC,CAAsB,CAAA,CAAC;gBAC1B,CAAC;gBAAC,OAAO,KAAU,EAAE,CAAC;oBACpB,OAAO,CAAC,KAAK,CAAC,0CAA0C,UAAU,SAAS,MAAM,GAAG,EAAE,MAAA,KAAK,CAAC,OAAO,mCAAI,KAAK,CAAC,CAAC;oBAC9G,OAAO,SAAS,CAAC;gBACnB,CAAC;gBAED,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,CAAA,MAAA,KAAK,CAAC,KAAK,0CAAE,OAAO,CAAA,EAAE,CAAC;oBACvD,OAAO,SAAS,CAAC;gBACnB,CAAC;gBAED,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;gBAC/B,IAAI,UAAkD,CAAC;gBACvD,IAAI,cAAc,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;oBAClD,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC;gBAC/B,CAAC;gBAED,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;YACrD,CAAC,CAAA,CAAC,CAAC,CAAC;YAEJ,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;gBAClC,IAAI,MAAM,EAAE,CAAC;oBACX,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CAAA;AAED;;;;;GAKG;AACH,MAAM,UAAgB,YAAY;yDAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAQ1G;;QACC,+EAA+E;QAC/E,MAAM,OAAO,GAAuB,EAAE,CAAC;QACvC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;YACpH,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,2DAA2D;QAC3D,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAExC,6EAA6E;QAC7E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC;oBAC3C,MAAM;oBACN,SAAS,EAAG,GAAG;oBACf,IAAI,EAAQ,KAAK,CAAC,UAAU;oBAC5B,OAAO,EAAK,KAAK,CAAC,OAAO;iBAC1B,CAAC,CAAC;gBAEH,IAAI,CAAC,4BAA4B,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzC,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;oBAC/C,OAAO,CAAC,KAAK,CAAC,oCAAoC,GAAG,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;gBACxG,CAAC;YACH,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,sEAAsE;gBACtE,MAAM,MAAM,GAAG,MAAA,KAAK,CAAC,OAAO,mCAAI,KAAK,CAAC;gBACtC,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,YAAY,MAAM,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;IACH,CAAC;CAAA;AAED;;GAEG;AACH,MAAM,UAAgB,eAAe;yDAAC,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAOvG;QACC,IAAI,iBAAqC,CAAC;QAC1C,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,CAAC;gBACH,MAAM,iBAAiB,GAAG,MAAM,cAAc,CAAC,uBAAuB,CAAC;oBACrE,YAAY,EAAG,MAAM;oBACrB,WAAW,EAAI,YAAY,CAAC,YAAY;oBACxC,WAAW;oBACX,QAAQ;oBACR,MAAM,EAAS,IAAI;iBACpB,CAAC,CAAC;gBACH,iBAAiB,GAAG,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,uFAAuF,EAAE,KAAK,CAAC,CAAC;gBAC9G,OAAO;YACT,CAAC;QACH,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC;YAC/C,MAAM;YACN,MAAM,EAAU,MAAM;YACtB,WAAW,EAAK,YAAY,CAAC,YAAY;YACzC,UAAU,EAAM,WAAW;YAC3B,aAAa,EAAG,EAAE,UAAU,EAAE,iBAAiB,EAAE;SAClD,CAAC,CAAC;QAEH,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAC9C,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,YAAY,GAAG,KAAK,CAAC,KAAM,CAAC;QAElC,MAAM,MAAM,GAAqB;YAC/B,OAAO,EAAE,YAAY,CAAC,OAAO;SAC9B,CAAC;QAEF,IAAI,cAAc,CAAC,YAAY,CAAC,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC;YACtD,MAAM,CAAC,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC;QACxC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CAAA"}
|
|
@@ -121,7 +121,28 @@ export declare class SyncEngineLevel implements SyncEngine {
|
|
|
121
121
|
*/
|
|
122
122
|
private getDefaultHashHex;
|
|
123
123
|
/**
|
|
124
|
-
*
|
|
124
|
+
* Parse a bit prefix string (e.g. "0110101") into a boolean array
|
|
125
|
+
* for the StateIndex API. Each '1' maps to `true` (right child),
|
|
126
|
+
* each '0' maps to `false` (left child).
|
|
127
|
+
*/
|
|
128
|
+
private static parseBitPrefix;
|
|
129
|
+
/**
|
|
130
|
+
* Access the local DWN's StateIndex directly, bypassing the `processMessage`
|
|
131
|
+
* pipeline. The sync engine runs in the same process as the local DWN, so
|
|
132
|
+
* there is no need for message signing, schema validation, or authentication
|
|
133
|
+
* when querying our own state.
|
|
134
|
+
*
|
|
135
|
+
* Returns `undefined` in remote mode (no in-process DWN). The local methods
|
|
136
|
+
* fall back to `processRequest` in that case, routing through RPC to the
|
|
137
|
+
* local DWN server.
|
|
138
|
+
*/
|
|
139
|
+
private get stateIndex();
|
|
140
|
+
/**
|
|
141
|
+
* Get the SMT root hash from the local DWN.
|
|
142
|
+
*
|
|
143
|
+
* In local mode: queries the StateIndex directly (fast, no processMessage overhead).
|
|
144
|
+
* In remote mode: constructs a signed MessagesSync message and routes through RPC.
|
|
145
|
+
*
|
|
125
146
|
* Returns a hex-encoded root hash string.
|
|
126
147
|
*/
|
|
127
148
|
private getLocalRoot;
|
|
@@ -137,13 +158,52 @@ export declare class SyncEngineLevel implements SyncEngine {
|
|
|
137
158
|
* Returns the sets of messageCids that exist only locally or only remotely.
|
|
138
159
|
*/
|
|
139
160
|
private walkTreeDiff;
|
|
161
|
+
/**
|
|
162
|
+
* Compute the diff between local and remote in a single HTTP round-trip.
|
|
163
|
+
*
|
|
164
|
+
* 1. Walk the local SMT directly (no processMessage) to collect subtree
|
|
165
|
+
* hashes at `MAX_DIFF_DEPTH`.
|
|
166
|
+
* 2. Send a single `MessagesSync action:'diff'` to the remote with all
|
|
167
|
+
* non-empty subtree hashes.
|
|
168
|
+
* 3. The remote compares and returns `onlyRemote` (with inline messages)
|
|
169
|
+
* and `onlyLocal` prefixes.
|
|
170
|
+
* 4. Enumerate local leaves for the `onlyLocal` prefixes directly.
|
|
171
|
+
*
|
|
172
|
+
* This replaces `walkTreeDiff()` which required one HTTP call per tree node.
|
|
173
|
+
*/
|
|
174
|
+
private diffWithRemote;
|
|
175
|
+
/**
|
|
176
|
+
* Walk the local SMT to a given depth and collect non-empty subtree hashes.
|
|
177
|
+
* Returns a `{ prefix: hexHash }` map. Empty subtrees (matching the default
|
|
178
|
+
* hash) are omitted.
|
|
179
|
+
*
|
|
180
|
+
* Uses direct StateIndex access in local mode. In remote mode, falls back
|
|
181
|
+
* to `getLocalSubtreeHash` which routes through RPC.
|
|
182
|
+
*/
|
|
183
|
+
private collectLocalSubtreeHashes;
|
|
184
|
+
/**
|
|
185
|
+
* Get the subtree hash at a given bit prefix from the local DWN.
|
|
186
|
+
*
|
|
187
|
+
* In local mode: queries the StateIndex directly.
|
|
188
|
+
* In remote mode: constructs a signed MessagesSync message and routes through RPC.
|
|
189
|
+
*/
|
|
140
190
|
private getLocalSubtreeHash;
|
|
141
191
|
private getRemoteSubtreeHash;
|
|
192
|
+
/**
|
|
193
|
+
* Get all leaf messageCids under a given prefix from the local DWN.
|
|
194
|
+
*
|
|
195
|
+
* In local mode: queries the StateIndex directly.
|
|
196
|
+
* In remote mode: constructs a signed MessagesSync message and routes through RPC.
|
|
197
|
+
*/
|
|
142
198
|
private getLocalLeaves;
|
|
143
199
|
private getRemoteLeaves;
|
|
144
200
|
/**
|
|
145
201
|
* Fetches missing messages from the remote DWN and processes them locally
|
|
146
202
|
* in dependency order (topological sort).
|
|
203
|
+
*
|
|
204
|
+
* When prefetched entries are provided (from the batched diff response),
|
|
205
|
+
* they are processed directly without additional HTTP round-trips.
|
|
206
|
+
* Only `messageCids` that were NOT prefetched are fetched individually.
|
|
147
207
|
*/
|
|
148
208
|
private pullMessages;
|
|
149
209
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-engine-level.d.ts","sourceRoot":"","sources":["../../src/sync-engine-level.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"sync-engine-level.d.ts","sourceRoot":"","sources":["../../src/sync-engine-level.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { EnboxPlatformAgent } from './types/agent.js';
|
|
2
2
|
import type { PermissionsApi } from './types/permissions.js';
|
|
3
|
-
import type { GenericMessage, UnionMessageReply } from '@enbox/dwn-sdk-js';
|
|
4
|
-
/** Entry type for fetched messages with optional data stream. */
|
|
3
|
+
import type { GenericMessage, MessagesSyncDiffEntry, UnionMessageReply } from '@enbox/dwn-sdk-js';
|
|
4
|
+
/** Entry type for fetched messages with optional data stream and retry buffer. */
|
|
5
5
|
export type SyncMessageEntry = {
|
|
6
6
|
message: GenericMessage;
|
|
7
7
|
dataStream?: ReadableStream<Uint8Array>;
|
|
8
|
+
/** Buffered data bytes for retry — avoids re-fetching from remote when stream is consumed. */
|
|
9
|
+
bufferedData?: Uint8Array;
|
|
8
10
|
};
|
|
9
11
|
/**
|
|
10
12
|
* 202: message was successfully written to the remote DWN
|
|
@@ -21,17 +23,19 @@ export declare function getMessageCid(message: GenericMessage): Promise<string>;
|
|
|
21
23
|
* Fetches missing messages from the remote DWN and processes them on the local DWN
|
|
22
24
|
* in dependency order (topological sort).
|
|
23
25
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* Small data payloads (≤ 1 MB) are buffered during the initial fetch so that
|
|
27
|
+
* retries can replay the data from memory instead of re-fetching from remote.
|
|
28
|
+
* Large payloads are re-fetched on retry since buffering them would consume
|
|
29
|
+
* too much memory.
|
|
28
30
|
*/
|
|
29
|
-
export declare function pullMessages({ did, dwnUrl, delegateDid, protocol, messageCids, agent, permissionsApi }: {
|
|
31
|
+
export declare function pullMessages({ did, dwnUrl, delegateDid, protocol, messageCids, prefetched, agent, permissionsApi }: {
|
|
30
32
|
did: string;
|
|
31
33
|
dwnUrl: string;
|
|
32
34
|
delegateDid?: string;
|
|
33
35
|
protocol?: string;
|
|
34
36
|
messageCids: string[];
|
|
37
|
+
/** Pre-fetched message entries from the batched diff response (already have message + data). */
|
|
38
|
+
prefetched?: MessagesSyncDiffEntry[];
|
|
35
39
|
agent: EnboxPlatformAgent;
|
|
36
40
|
permissionsApi: PermissionsApi;
|
|
37
41
|
}): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-messages.d.ts","sourceRoot":"","sources":["../../src/sync-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAqB,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"sync-messages.d.ts","sourceRoot":"","sources":["../../src/sync-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAqB,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAWrH,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACxC,8FAA8F;IAC9F,YAAY,CAAC,EAAE,UAAU,CAAC;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAS9E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5E;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACzH,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gGAAgG;IAChG,UAAU,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACrC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFhB;AA4DD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACpH,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAyE9B;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAC7G,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,CAiChB;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAC1G,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAwCxC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enbox/agent",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/esm/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -71,8 +71,8 @@
|
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@scure/bip39": "1.2.2",
|
|
74
|
-
"@enbox/dwn-clients": "0.2.
|
|
75
|
-
"@enbox/dwn-sdk-js": "0.2.
|
|
74
|
+
"@enbox/dwn-clients": "0.2.2",
|
|
75
|
+
"@enbox/dwn-sdk-js": "0.2.1",
|
|
76
76
|
"@enbox/common": "0.1.0",
|
|
77
77
|
"@enbox/crypto": "0.1.0",
|
|
78
78
|
"@enbox/dids": "0.1.0",
|
package/src/sync-engine-level.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AbstractLevel } from 'abstract-level';
|
|
2
|
-
import type { GenericMessage, MessageEvent, MessagesSubscribeReply, MessagesSyncReply, SubscriptionMessage } from '@enbox/dwn-sdk-js';
|
|
2
|
+
import type { GenericMessage, MessageEvent, MessagesSubscribeReply, MessagesSyncDiffEntry, MessagesSyncReply, StateIndex, SubscriptionMessage } from '@enbox/dwn-sdk-js';
|
|
3
3
|
|
|
4
4
|
import ms from 'ms';
|
|
5
5
|
|
|
@@ -23,12 +23,20 @@ export type SyncEngineLevelParams = {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Maximum bit prefix depth
|
|
27
|
-
* At depth 16, each subtree covers ~1/65536 of the key space
|
|
28
|
-
* balance between round-trip count and leaf-set size.
|
|
26
|
+
* Maximum bit prefix depth for the per-node tree walk (legacy fallback).
|
|
27
|
+
* At depth 16, each subtree covers ~1/65536 of the key space.
|
|
29
28
|
*/
|
|
30
29
|
const MAX_DIFF_DEPTH = 16;
|
|
31
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Bit depth for the batched diff protocol.
|
|
33
|
+
* Lower than MAX_DIFF_DEPTH because the batched diff sends all subtree hashes
|
|
34
|
+
* in a single request — fine granularity comes from the server-side leaf
|
|
35
|
+
* enumeration, not from deeper prefixes. Depth 8 = 256 buckets, which is
|
|
36
|
+
* a good balance between hash map size and leaf-set resolution.
|
|
37
|
+
*/
|
|
38
|
+
const BATCHED_DIFF_DEPTH = 8;
|
|
39
|
+
|
|
32
40
|
/**
|
|
33
41
|
* Maximum number of concurrent remote HTTP requests during a tree diff.
|
|
34
42
|
* The binary tree walk fans out in parallel — without a limit, depth N
|
|
@@ -289,15 +297,48 @@ export class SyncEngineLevel implements SyncEngine {
|
|
|
289
297
|
continue;
|
|
290
298
|
}
|
|
291
299
|
|
|
292
|
-
// Phase 2:
|
|
293
|
-
|
|
300
|
+
// Phase 2: Compute the diff in a single round-trip using the
|
|
301
|
+
// batched 'diff' action. This replaces the per-node tree walk
|
|
302
|
+
// that previously required dozens of HTTP requests.
|
|
303
|
+
const diff = await this.diffWithRemote({
|
|
294
304
|
did, dwnUrl, delegateDid, protocol,
|
|
295
305
|
});
|
|
296
306
|
|
|
297
307
|
// Phase 3: Pull missing messages (remote has, local doesn't).
|
|
308
|
+
// The diff response may include inline message data — use it
|
|
309
|
+
// directly instead of re-fetching via individual MessagesRead calls.
|
|
298
310
|
if (!direction || direction === 'pull') {
|
|
299
311
|
if (diff.onlyRemote.length > 0) {
|
|
300
|
-
|
|
312
|
+
// Separate entries into three categories:
|
|
313
|
+
// 1. Fully prefetched: have message + inline data (or no data needed)
|
|
314
|
+
// 2. Need data fetch: have message but missing data for RecordsWrite
|
|
315
|
+
// 3. Need full fetch: no message at all
|
|
316
|
+
const prefetched: (MessagesSyncDiffEntry & { message: GenericMessage })[] = [];
|
|
317
|
+
const needsFetchCids: string[] = [];
|
|
318
|
+
|
|
319
|
+
for (const entry of diff.onlyRemote) {
|
|
320
|
+
if (!entry.message) {
|
|
321
|
+
// No message at all — need full fetch.
|
|
322
|
+
needsFetchCids.push(entry.messageCid);
|
|
323
|
+
} else if (
|
|
324
|
+
entry.message.descriptor.interface === 'Records' &&
|
|
325
|
+
entry.message.descriptor.method === 'Write' &&
|
|
326
|
+
(entry.message.descriptor as any).dataCid &&
|
|
327
|
+
!entry.encodedData
|
|
328
|
+
) {
|
|
329
|
+
// RecordsWrite with data but data wasn't inlined (too large).
|
|
330
|
+
// Need to fetch individually to get the data stream.
|
|
331
|
+
needsFetchCids.push(entry.messageCid);
|
|
332
|
+
} else {
|
|
333
|
+
// Fully prefetched (message + data or no data needed).
|
|
334
|
+
prefetched.push(entry as MessagesSyncDiffEntry & { message: GenericMessage });
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
await this.pullMessages({
|
|
338
|
+
did, dwnUrl, delegateDid, protocol,
|
|
339
|
+
messageCids: needsFetchCids,
|
|
340
|
+
prefetched,
|
|
341
|
+
});
|
|
301
342
|
}
|
|
302
343
|
}
|
|
303
344
|
|
|
@@ -807,17 +848,55 @@ export class SyncEngineLevel implements SyncEngine {
|
|
|
807
848
|
return this._defaultHashHex.get(depth) ?? '';
|
|
808
849
|
}
|
|
809
850
|
|
|
851
|
+
/**
|
|
852
|
+
* Parse a bit prefix string (e.g. "0110101") into a boolean array
|
|
853
|
+
* for the StateIndex API. Each '1' maps to `true` (right child),
|
|
854
|
+
* each '0' maps to `false` (left child).
|
|
855
|
+
*/
|
|
856
|
+
private static parseBitPrefix(prefix: string): boolean[] {
|
|
857
|
+
return Array.from(prefix, (ch): boolean => ch === '1');
|
|
858
|
+
}
|
|
859
|
+
|
|
810
860
|
// ---------------------------------------------------------------------------
|
|
811
861
|
// SMT Root Comparison
|
|
812
862
|
// ---------------------------------------------------------------------------
|
|
813
863
|
|
|
814
864
|
/**
|
|
815
|
-
*
|
|
865
|
+
* Access the local DWN's StateIndex directly, bypassing the `processMessage`
|
|
866
|
+
* pipeline. The sync engine runs in the same process as the local DWN, so
|
|
867
|
+
* there is no need for message signing, schema validation, or authentication
|
|
868
|
+
* when querying our own state.
|
|
869
|
+
*
|
|
870
|
+
* Returns `undefined` in remote mode (no in-process DWN). The local methods
|
|
871
|
+
* fall back to `processRequest` in that case, routing through RPC to the
|
|
872
|
+
* local DWN server.
|
|
873
|
+
*/
|
|
874
|
+
private get stateIndex(): StateIndex | undefined {
|
|
875
|
+
if (this.agent.dwn.isRemoteMode) {
|
|
876
|
+
return undefined;
|
|
877
|
+
}
|
|
878
|
+
return this.agent.dwn.node.storage.stateIndex;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* Get the SMT root hash from the local DWN.
|
|
883
|
+
*
|
|
884
|
+
* In local mode: queries the StateIndex directly (fast, no processMessage overhead).
|
|
885
|
+
* In remote mode: constructs a signed MessagesSync message and routes through RPC.
|
|
886
|
+
*
|
|
816
887
|
* Returns a hex-encoded root hash string.
|
|
817
888
|
*/
|
|
818
889
|
private async getLocalRoot(did: string, delegateDid?: string, protocol?: string): Promise<string> {
|
|
819
|
-
const
|
|
890
|
+
const si = this.stateIndex;
|
|
891
|
+
if (si) {
|
|
892
|
+
const rootHash = protocol !== undefined
|
|
893
|
+
? await si.getProtocolRoot(did, protocol)
|
|
894
|
+
: await si.getRoot(did);
|
|
895
|
+
return hashToHex(rootHash);
|
|
896
|
+
}
|
|
820
897
|
|
|
898
|
+
// Remote mode fallback: go through processRequest → RPC.
|
|
899
|
+
const permissionGrantId = await this.getSyncPermissionGrantId(did, delegateDid, protocol);
|
|
821
900
|
const response = await this.agent.dwn.processRequest({
|
|
822
901
|
author : did,
|
|
823
902
|
target : did,
|
|
@@ -829,7 +908,6 @@ export class SyncEngineLevel implements SyncEngine {
|
|
|
829
908
|
permissionGrantId
|
|
830
909
|
}
|
|
831
910
|
});
|
|
832
|
-
|
|
833
911
|
const reply = response.reply as MessagesSyncReply;
|
|
834
912
|
return reply.root ?? '';
|
|
835
913
|
}
|
|
@@ -955,9 +1033,146 @@ export class SyncEngineLevel implements SyncEngine {
|
|
|
955
1033
|
return { onlyLocal, onlyRemote };
|
|
956
1034
|
}
|
|
957
1035
|
|
|
1036
|
+
// ---------------------------------------------------------------------------
|
|
1037
|
+
// Batched Diff — single round-trip set reconciliation
|
|
1038
|
+
// ---------------------------------------------------------------------------
|
|
1039
|
+
|
|
1040
|
+
/**
|
|
1041
|
+
* Compute the diff between local and remote in a single HTTP round-trip.
|
|
1042
|
+
*
|
|
1043
|
+
* 1. Walk the local SMT directly (no processMessage) to collect subtree
|
|
1044
|
+
* hashes at `MAX_DIFF_DEPTH`.
|
|
1045
|
+
* 2. Send a single `MessagesSync action:'diff'` to the remote with all
|
|
1046
|
+
* non-empty subtree hashes.
|
|
1047
|
+
* 3. The remote compares and returns `onlyRemote` (with inline messages)
|
|
1048
|
+
* and `onlyLocal` prefixes.
|
|
1049
|
+
* 4. Enumerate local leaves for the `onlyLocal` prefixes directly.
|
|
1050
|
+
*
|
|
1051
|
+
* This replaces `walkTreeDiff()` which required one HTTP call per tree node.
|
|
1052
|
+
*/
|
|
1053
|
+
private async diffWithRemote({ did, dwnUrl, delegateDid, protocol }: {
|
|
1054
|
+
did: string;
|
|
1055
|
+
dwnUrl: string;
|
|
1056
|
+
delegateDid?: string;
|
|
1057
|
+
protocol?: string;
|
|
1058
|
+
}): Promise<{ onlyRemote: MessagesSyncDiffEntry[]; onlyLocal: string[] }> {
|
|
1059
|
+
// Step 1: Collect local subtree hashes at BATCHED_DIFF_DEPTH directly from StateIndex.
|
|
1060
|
+
const localHashes = await this.collectLocalSubtreeHashes(did, protocol, BATCHED_DIFF_DEPTH);
|
|
1061
|
+
|
|
1062
|
+
// Step 2: Send a single 'diff' request to the remote with our hashes.
|
|
1063
|
+
const permissionGrantId = await this.getSyncPermissionGrantId(did, delegateDid, protocol);
|
|
1064
|
+
|
|
1065
|
+
const syncMessage = await this.agent.dwn.processRequest({
|
|
1066
|
+
store : false,
|
|
1067
|
+
author : did,
|
|
1068
|
+
target : did,
|
|
1069
|
+
messageType : DwnInterface.MessagesSync,
|
|
1070
|
+
granteeDid : delegateDid,
|
|
1071
|
+
messageParams : {
|
|
1072
|
+
action : 'diff',
|
|
1073
|
+
protocol,
|
|
1074
|
+
hashes : localHashes,
|
|
1075
|
+
depth : BATCHED_DIFF_DEPTH,
|
|
1076
|
+
permissionGrantId,
|
|
1077
|
+
}
|
|
1078
|
+
});
|
|
1079
|
+
|
|
1080
|
+
const reply = await this.agent.rpc.sendDwnRequest({
|
|
1081
|
+
dwnUrl,
|
|
1082
|
+
targetDid : did,
|
|
1083
|
+
message : syncMessage.message,
|
|
1084
|
+
}) as MessagesSyncReply;
|
|
1085
|
+
|
|
1086
|
+
if (reply.status.code !== 200) {
|
|
1087
|
+
throw new Error(`SyncEngineLevel: diff failed with ${reply.status.code}: ${reply.status.detail}`);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
// Step 3: Enumerate local leaves for prefixes the remote reported as onlyLocal.
|
|
1091
|
+
const permissionGrantIdForLeaves = await this.getSyncPermissionGrantId(did, delegateDid, protocol);
|
|
1092
|
+
const onlyLocalCids: string[] = [];
|
|
1093
|
+
for (const prefix of reply.onlyLocal ?? []) {
|
|
1094
|
+
const leaves = await this.getLocalLeaves(did, prefix, delegateDid, protocol, permissionGrantIdForLeaves);
|
|
1095
|
+
onlyLocalCids.push(...leaves);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
return {
|
|
1099
|
+
onlyRemote : reply.onlyRemote ?? [],
|
|
1100
|
+
onlyLocal : onlyLocalCids,
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Walk the local SMT to a given depth and collect non-empty subtree hashes.
|
|
1106
|
+
* Returns a `{ prefix: hexHash }` map. Empty subtrees (matching the default
|
|
1107
|
+
* hash) are omitted.
|
|
1108
|
+
*
|
|
1109
|
+
* Uses direct StateIndex access in local mode. In remote mode, falls back
|
|
1110
|
+
* to `getLocalSubtreeHash` which routes through RPC.
|
|
1111
|
+
*/
|
|
1112
|
+
private async collectLocalSubtreeHashes(
|
|
1113
|
+
did: string,
|
|
1114
|
+
protocol: string | undefined,
|
|
1115
|
+
depth: number,
|
|
1116
|
+
): Promise<Record<string, string>> {
|
|
1117
|
+
const result: Record<string, string> = {};
|
|
1118
|
+
const defaultHash = await this.getDefaultHashHex(depth);
|
|
1119
|
+
const si = this.stateIndex;
|
|
1120
|
+
|
|
1121
|
+
const walk = async (prefix: string, currentDepth: number): Promise<void> => {
|
|
1122
|
+
let hexHash: string;
|
|
1123
|
+
|
|
1124
|
+
if (si) {
|
|
1125
|
+
// Fast path: direct StateIndex access (local mode).
|
|
1126
|
+
const bitPath = SyncEngineLevel.parseBitPrefix(prefix);
|
|
1127
|
+
const hash = protocol !== undefined
|
|
1128
|
+
? await si.getProtocolSubtreeHash(did, protocol, bitPath)
|
|
1129
|
+
: await si.getSubtreeHash(did, bitPath);
|
|
1130
|
+
hexHash = hashToHex(hash);
|
|
1131
|
+
} else {
|
|
1132
|
+
// Remote mode fallback.
|
|
1133
|
+
hexHash = await this.getLocalSubtreeHash(did, prefix, undefined, protocol);
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
if (hexHash === defaultHash) {
|
|
1137
|
+
// Empty subtree — omit from the map.
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
if (currentDepth >= depth) {
|
|
1142
|
+
result[prefix] = hexHash;
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// Recurse into children.
|
|
1147
|
+
await Promise.all([
|
|
1148
|
+
walk(prefix + '0', currentDepth + 1),
|
|
1149
|
+
walk(prefix + '1', currentDepth + 1),
|
|
1150
|
+
]);
|
|
1151
|
+
};
|
|
1152
|
+
|
|
1153
|
+
await walk('', 0);
|
|
1154
|
+
return result;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
/**
|
|
1158
|
+
* Get the subtree hash at a given bit prefix from the local DWN.
|
|
1159
|
+
*
|
|
1160
|
+
* In local mode: queries the StateIndex directly.
|
|
1161
|
+
* In remote mode: constructs a signed MessagesSync message and routes through RPC.
|
|
1162
|
+
*/
|
|
958
1163
|
private async getLocalSubtreeHash(
|
|
959
1164
|
did: string, prefix: string, delegateDid?: string, protocol?: string, permissionGrantId?: string
|
|
960
1165
|
): Promise<string> {
|
|
1166
|
+
const si = this.stateIndex;
|
|
1167
|
+
if (si) {
|
|
1168
|
+
const bitPath = SyncEngineLevel.parseBitPrefix(prefix);
|
|
1169
|
+
const hash = protocol !== undefined
|
|
1170
|
+
? await si.getProtocolSubtreeHash(did, protocol, bitPath)
|
|
1171
|
+
: await si.getSubtreeHash(did, bitPath);
|
|
1172
|
+
return hashToHex(hash);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
// Remote mode fallback.
|
|
961
1176
|
const response = await this.agent.dwn.processRequest({
|
|
962
1177
|
author : did,
|
|
963
1178
|
target : did,
|
|
@@ -970,7 +1185,6 @@ export class SyncEngineLevel implements SyncEngine {
|
|
|
970
1185
|
permissionGrantId
|
|
971
1186
|
}
|
|
972
1187
|
});
|
|
973
|
-
|
|
974
1188
|
const reply = response.reply as MessagesSyncReply;
|
|
975
1189
|
return reply.hash ?? '';
|
|
976
1190
|
}
|
|
@@ -1001,9 +1215,24 @@ export class SyncEngineLevel implements SyncEngine {
|
|
|
1001
1215
|
return reply.hash ?? '';
|
|
1002
1216
|
}
|
|
1003
1217
|
|
|
1218
|
+
/**
|
|
1219
|
+
* Get all leaf messageCids under a given prefix from the local DWN.
|
|
1220
|
+
*
|
|
1221
|
+
* In local mode: queries the StateIndex directly.
|
|
1222
|
+
* In remote mode: constructs a signed MessagesSync message and routes through RPC.
|
|
1223
|
+
*/
|
|
1004
1224
|
private async getLocalLeaves(
|
|
1005
1225
|
did: string, prefix: string, delegateDid?: string, protocol?: string, permissionGrantId?: string
|
|
1006
1226
|
): Promise<string[]> {
|
|
1227
|
+
const si = this.stateIndex;
|
|
1228
|
+
if (si) {
|
|
1229
|
+
const bitPath = SyncEngineLevel.parseBitPrefix(prefix);
|
|
1230
|
+
return protocol !== undefined
|
|
1231
|
+
? await si.getProtocolLeaves(did, protocol, bitPath)
|
|
1232
|
+
: await si.getLeaves(did, bitPath);
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
// Remote mode fallback.
|
|
1007
1236
|
const response = await this.agent.dwn.processRequest({
|
|
1008
1237
|
author : did,
|
|
1009
1238
|
target : did,
|
|
@@ -1016,7 +1245,6 @@ export class SyncEngineLevel implements SyncEngine {
|
|
|
1016
1245
|
permissionGrantId
|
|
1017
1246
|
}
|
|
1018
1247
|
});
|
|
1019
|
-
|
|
1020
1248
|
const reply = response.reply as MessagesSyncReply;
|
|
1021
1249
|
return reply.entries ?? [];
|
|
1022
1250
|
}
|
|
@@ -1054,16 +1282,21 @@ export class SyncEngineLevel implements SyncEngine {
|
|
|
1054
1282
|
/**
|
|
1055
1283
|
* Fetches missing messages from the remote DWN and processes them locally
|
|
1056
1284
|
* in dependency order (topological sort).
|
|
1285
|
+
*
|
|
1286
|
+
* When prefetched entries are provided (from the batched diff response),
|
|
1287
|
+
* they are processed directly without additional HTTP round-trips.
|
|
1288
|
+
* Only `messageCids` that were NOT prefetched are fetched individually.
|
|
1057
1289
|
*/
|
|
1058
|
-
private async pullMessages({ did, dwnUrl, delegateDid, protocol, messageCids }: {
|
|
1290
|
+
private async pullMessages({ did, dwnUrl, delegateDid, protocol, messageCids, prefetched }: {
|
|
1059
1291
|
did: string;
|
|
1060
1292
|
dwnUrl: string;
|
|
1061
1293
|
delegateDid?: string;
|
|
1062
1294
|
protocol?: string;
|
|
1063
1295
|
messageCids: string[];
|
|
1296
|
+
prefetched?: MessagesSyncDiffEntry[];
|
|
1064
1297
|
}): Promise<void> {
|
|
1065
1298
|
return pullMessages({
|
|
1066
|
-
did, dwnUrl, delegateDid, protocol, messageCids,
|
|
1299
|
+
did, dwnUrl, delegateDid, protocol, messageCids, prefetched,
|
|
1067
1300
|
agent : this.agent,
|
|
1068
1301
|
permissionsApi : this._permissionsApi,
|
|
1069
1302
|
});
|