Summary
After submitting a backward-compatible DataContractUpdate for Yappr auth vault contract 64RTgHjGXhtiN9t5S4u6hVDps7oHuTBaaHrQEFYcxt9M, reads of authVault documents started failing with:
protocol: Corrupted Serialization: error reading string from serialized document
The update was accepted by Platform and the contract now reports version 2.
Expected
A contract update that only changes authVaultAccess should not break reads of existing authVault documents, especially because the authVault schema itself is unchanged.
Actual
After the update:
authVaultAccess queries still work
authVault queries fail
- direct
getDocument / sdk.documents.get(...) for an existing authVault also fails
This reproduces outside the app in a standalone Node script using @dashevo/evo-sdk@3.1.0-dev.1, so it does not appear to be an application-layer bug.
Contract
Contract ID:
64RTgHjGXhtiN9t5S4u6hVDps7oHuTBaaHrQEFYcxt9M
Contract version after update:
Schema delta
Only authVaultAccess changed. authVault did not.
Pre-update (v1)
{
"authVault": {
"properties": {
"version": { "type": "integer", "position": 0 },
"secretKind": { "type": "string", "enum": ["login-key", "auth-key"], "position": 1 },
"ciphertext": { "type": "array", "byteArray": true, "position": 2 },
"iv": { "type": "array", "byteArray": true, "position": 3 },
"bundleHash": { "type": "array", "byteArray": true, "position": 4 },
"updatedAt": { "type": "integer", "position": 5 },
"active": { "type": "boolean", "position": 6 }
}
},
"authVaultAccess": {
"properties": {
"vaultId": { "type": "array", "byteArray": true, "position": 0 },
"kind": { "type": "string", "enum": ["password", "passkey-prf"], "position": 1 },
"label": { "type": "string", "position": 2 },
"status": { "type": "string", "enum": ["active", "revoked"], "position": 3 },
"wrappedDek": { "type": "array", "byteArray": true, "position": 4 },
"iv": { "type": "array", "byteArray": true, "position": 5 },
"kdfType": { "type": "string", "position": 6 },
"pbkdf2Salt": { "type": "array", "byteArray": true, "position": 7 },
"pbkdf2Iterations": { "type": "integer", "position": 8 },
"credentialId": { "type": "array", "byteArray": true, "position": 9 },
"credentialIdHash": { "type": "array", "byteArray": true, "position": 10 },
"prfInput": { "type": "array", "byteArray": true, "position": 11 },
"rpId": { "type": "string", "position": 12 }
}
}
}
Post-update (v2)
{
"authVault": {
"properties": {
"version": { "type": "integer", "position": 0 },
"secretKind": { "type": "string", "enum": ["login-key", "auth-key"], "position": 1 },
"ciphertext": { "type": "array", "byteArray": true, "position": 2 },
"iv": { "type": "array", "byteArray": true, "position": 3 },
"bundleHash": { "type": "array", "byteArray": true, "position": 4 },
"updatedAt": { "type": "integer", "position": 5 },
"active": { "type": "boolean", "position": 6 }
}
},
"authVaultAccess": {
"properties": {
"vaultId": { "type": "array", "byteArray": true, "position": 0 },
"kind": { "type": "string", "enum": ["password", "passkey-prf", "auth-key"], "position": 1 },
"label": { "type": "string", "position": 2 },
"status": { "type": "string", "enum": ["active", "revoked"], "position": 3 },
"wrappedDek": { "type": "array", "byteArray": true, "position": 4 },
"iv": { "type": "array", "byteArray": true, "position": 5 },
"kdfType": { "type": "string", "position": 6 },
"pbkdf2Salt": { "type": "array", "byteArray": true, "position": 7 },
"pbkdf2Iterations": { "type": "integer", "position": 8 },
"credentialId": { "type": "array", "byteArray": true, "position": 9 },
"credentialIdHash": { "type": "array", "byteArray": true, "position": 10 },
"prfInput": { "type": "array", "byteArray": true, "position": 11 },
"rpId": { "type": "string", "position": 12 },
"authKeyId": { "type": "integer", "minimum": 0, "maximum": 4294967295, "position": 13 }
}
}
}
Minimal repro
Using @dashevo/evo-sdk@3.1.0-dev.1 on testnet:
import { EvoSDK } from '@dashevo/evo-sdk';
const sdk = EvoSDK.testnetTrusted({ settings: { timeoutMs: 8000 } });
await sdk.connect();
const contractId = '64RTgHjGXhtiN9t5S4u6hVDps7oHuTBaaHrQEFYcxt9M';
const authVaultAccess = await sdk.documents.query({
dataContractId: contractId,
documentTypeName: 'authVaultAccess',
limit: 1,
});
console.log('authVaultAccess ok', authVaultAccess.size);
const authVault = await sdk.documents.query({
dataContractId: contractId,
documentTypeName: 'authVault',
limit: 1,
});
console.log('authVault ok', authVault.size);
Actual result:
authVaultAccess ok 1
protocol: Corrupted Serialization: error reading string from serialized document
Owner-filtered query also fails:
await sdk.documents.query({
dataContractId: contractId,
documentTypeName: 'authVault',
where: [['$ownerId', '==', '3TvXzxbW2w2zeaTwXjXyLwjjN9M3UXzYy8d1w4Gv272x']],
limit: 1,
});
Direct get for an existing vault id also fails:
await sdk.documents.get(
contractId,
'authVault',
'GEcUCZVRbMng5ozZGcFAy5TPZMF5diN4Pm9o311PrC6t'
);
Notes
- The contract fetch itself succeeds and reports version
2
authVaultAccess continues to deserialize correctly
authVault schema appears unchanged between v1 and v2
- This suggests a regression in document decoding after contract update rather than a problem in the app query layer
Summary
After submitting a backward-compatible
DataContractUpdatefor Yappr auth vault contract64RTgHjGXhtiN9t5S4u6hVDps7oHuTBaaHrQEFYcxt9M, reads ofauthVaultdocuments started failing with:The update was accepted by Platform and the contract now reports version
2.Expected
A contract update that only changes
authVaultAccessshould not break reads of existingauthVaultdocuments, especially because theauthVaultschema itself is unchanged.Actual
After the update:
authVaultAccessqueries still workauthVaultqueries failgetDocument/sdk.documents.get(...)for an existingauthVaultalso failsThis reproduces outside the app in a standalone Node script using
@dashevo/evo-sdk@3.1.0-dev.1, so it does not appear to be an application-layer bug.Contract
Contract ID:
Contract version after update:
Schema delta
Only
authVaultAccesschanged.authVaultdid not.Pre-update (
v1){ "authVault": { "properties": { "version": { "type": "integer", "position": 0 }, "secretKind": { "type": "string", "enum": ["login-key", "auth-key"], "position": 1 }, "ciphertext": { "type": "array", "byteArray": true, "position": 2 }, "iv": { "type": "array", "byteArray": true, "position": 3 }, "bundleHash": { "type": "array", "byteArray": true, "position": 4 }, "updatedAt": { "type": "integer", "position": 5 }, "active": { "type": "boolean", "position": 6 } } }, "authVaultAccess": { "properties": { "vaultId": { "type": "array", "byteArray": true, "position": 0 }, "kind": { "type": "string", "enum": ["password", "passkey-prf"], "position": 1 }, "label": { "type": "string", "position": 2 }, "status": { "type": "string", "enum": ["active", "revoked"], "position": 3 }, "wrappedDek": { "type": "array", "byteArray": true, "position": 4 }, "iv": { "type": "array", "byteArray": true, "position": 5 }, "kdfType": { "type": "string", "position": 6 }, "pbkdf2Salt": { "type": "array", "byteArray": true, "position": 7 }, "pbkdf2Iterations": { "type": "integer", "position": 8 }, "credentialId": { "type": "array", "byteArray": true, "position": 9 }, "credentialIdHash": { "type": "array", "byteArray": true, "position": 10 }, "prfInput": { "type": "array", "byteArray": true, "position": 11 }, "rpId": { "type": "string", "position": 12 } } } }Post-update (
v2){ "authVault": { "properties": { "version": { "type": "integer", "position": 0 }, "secretKind": { "type": "string", "enum": ["login-key", "auth-key"], "position": 1 }, "ciphertext": { "type": "array", "byteArray": true, "position": 2 }, "iv": { "type": "array", "byteArray": true, "position": 3 }, "bundleHash": { "type": "array", "byteArray": true, "position": 4 }, "updatedAt": { "type": "integer", "position": 5 }, "active": { "type": "boolean", "position": 6 } } }, "authVaultAccess": { "properties": { "vaultId": { "type": "array", "byteArray": true, "position": 0 }, "kind": { "type": "string", "enum": ["password", "passkey-prf", "auth-key"], "position": 1 }, "label": { "type": "string", "position": 2 }, "status": { "type": "string", "enum": ["active", "revoked"], "position": 3 }, "wrappedDek": { "type": "array", "byteArray": true, "position": 4 }, "iv": { "type": "array", "byteArray": true, "position": 5 }, "kdfType": { "type": "string", "position": 6 }, "pbkdf2Salt": { "type": "array", "byteArray": true, "position": 7 }, "pbkdf2Iterations": { "type": "integer", "position": 8 }, "credentialId": { "type": "array", "byteArray": true, "position": 9 }, "credentialIdHash": { "type": "array", "byteArray": true, "position": 10 }, "prfInput": { "type": "array", "byteArray": true, "position": 11 }, "rpId": { "type": "string", "position": 12 }, "authKeyId": { "type": "integer", "minimum": 0, "maximum": 4294967295, "position": 13 } } } }Minimal repro
Using
@dashevo/evo-sdk@3.1.0-dev.1on testnet:Actual result:
Owner-filtered query also fails:
Direct get for an existing vault id also fails:
Notes
2authVaultAccesscontinues to deserialize correctlyauthVaultschema appears unchanged betweenv1andv2