Skip to content

Commit

Permalink
feat: identity state transition validation fixes (#1786)
Browse files Browse the repository at this point in the history
Co-authored-by: Lukasz Klimek <[email protected]>
Co-authored-by: markin.io <[email protected]>
Co-authored-by: Ivan Shumkov <[email protected]>
  • Loading branch information
4 people authored Mar 19, 2024
1 parent 5493ae9 commit 807942e
Show file tree
Hide file tree
Showing 139 changed files with 1,886 additions and 1,087 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ async function createGrpcErrorFromDriveResponse(code, info) {
}

// Undefined Drive and DAPI errors
if (code >= 17 && code < 1000) {
if (code >= 17 && code < 10000) {
return new GrpcError(
GrpcErrorCodes.UNKNOWN,
message,
Expand All @@ -110,7 +110,7 @@ async function createGrpcErrorFromDriveResponse(code, info) {
}

// DPP errors
if (code >= 1000 && code < 5000) {
if (code >= 10000 && code < 50000) {
let consensusError;
try {
consensusError = deserializeConsensusError(data.serializedError || []);
Expand All @@ -125,15 +125,15 @@ async function createGrpcErrorFromDriveResponse(code, info) {
}

// Basic
if (code >= 1000 && code < 2000) {
if (code >= 10000 && code < 20000) {
return new InvalidArgumentGrpcError(
consensusError.message,
{ code, ...createRawMetadata(data) },
);
}

// Signature
if (code >= 2000 && code < 3000) {
if (code >= 20000 && code < 30000) {
return new GrpcError(
GrpcErrorCodes.UNAUTHENTICATED,
consensusError.message,
Expand All @@ -142,15 +142,15 @@ async function createGrpcErrorFromDriveResponse(code, info) {
}

// Fee
if (code >= 3000 && code < 4000) {
if (code >= 30000 && code < 40000) {
return new FailedPreconditionGrpcError(
consensusError.message,
{ code, ...createRawMetadata(data) },
);
}

// State
if (code >= 4000 && code < 5000) {
if (code >= 40000 && code < 50000) {
return new InvalidArgumentGrpcError(
consensusError.message,
{ code, ...createRawMetadata(data) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,23 @@ describe('createGrpcErrorFromDriveResponse', () => {
});
});

it('should throw basic consensus error if error code = 1000', async () => {
it('should throw basic consensus error if error code = 10000', async () => {
const consensusError = new ProtocolVersionParsingError('test');

const data = { serializedError: consensusError.serialize() };
info = { data };

const error = await createGrpcErrorFromDriveResponse(1000, cbor.encode(info).toString('base64'));
const error = await createGrpcErrorFromDriveResponse(10000, cbor.encode(info).toString('base64'));

expect(error).to.be.an.instanceOf(InvalidArgumentGrpcError);
expect(error.message).to.be.equals(consensusError.message);
expect(error.getRawMetadata()).to.deep.equal({
code: 1000,
code: 10000,
'drive-error-data-bin': cbor.encode(data),
});
});

it('should throw signature consensus error if error code = 2000', async () => {
it('should throw signature consensus error if error code = 20000', async () => {
const id = await generateRandomIdentifierAsync();

const consensusError = new IdentityNotFoundError(id);
Expand All @@ -91,35 +91,35 @@ describe('createGrpcErrorFromDriveResponse', () => {
info = { data };

const error = await createGrpcErrorFromDriveResponse(
2000,
20000,
cbor.encode(info).toString('base64'),
);

expect(error).to.be.an.instanceOf(GrpcError);
expect(error.message).to.be.equals(consensusError.message);
expect(error.getCode()).to.equal(GrpcErrorCodes.UNAUTHENTICATED);
expect(error.getRawMetadata()).to.deep.equal({
code: 2000,
code: 20000,
'drive-error-data-bin': cbor.encode(data),
});
});

it('should throw fee consensus error if error code = 3000', async () => {
it('should throw fee consensus error if error code = 30000', async () => {
const consensusError = new BalanceIsNotEnoughError(BigInt(20), BigInt(10));

const data = { serializedError: consensusError.serialize() };
info = { data };

const error = await createGrpcErrorFromDriveResponse(3000, cbor.encode(info).toString('base64'));
const error = await createGrpcErrorFromDriveResponse(30000, cbor.encode(info).toString('base64'));

expect(error).to.be.an.instanceOf(FailedPreconditionGrpcError);
expect(error.getRawMetadata()).to.deep.equal({
code: 3000,
code: 30000,
'drive-error-data-bin': cbor.encode(data),
});
});

it('should throw state consensus error if error code = 4000', async () => {
it('should throw state consensus error if error code = 40000', async () => {
const dataContractId = await generateRandomIdentifierAsync();

const consensusError = new DataContractAlreadyPresentError(dataContractId);
Expand All @@ -128,23 +128,23 @@ describe('createGrpcErrorFromDriveResponse', () => {
info = { data };

const error = await createGrpcErrorFromDriveResponse(
4000,
40000,
cbor.encode(info).toString('base64'),
);

expect(error).to.be.an.instanceOf(InvalidArgumentGrpcError);
expect(error.getRawMetadata()).to.deep.equal({
code: 4000,
code: 40000,
'drive-error-data-bin': cbor.encode(data),
});
});

it('should throw Unknown error code >= 5000', async () => {
const error = await createGrpcErrorFromDriveResponse(5000, encodedInfo);
it('should throw Unknown error code >= 50000', async () => {
const error = await createGrpcErrorFromDriveResponse(50000, encodedInfo);

expect(error).to.be.an.instanceOf(GrpcError);
expect(error.getMessage()).to.equal('Internal error');
expect(error.getError().message).to.deep.equal('Unknown Drive’s error code: 5000');
expect(error.getError().message).to.deep.equal('Unknown Drive’s error code: 50000');
});

it('should return InternalGrpcError if codes is undefined', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ async function createGrpcTransportError(grpcError, dapiAddress) {
}

// DPP consensus errors
if (code >= 1000 && code < 5000) {
if (code >= 10000 && code < 50000) {
const consensusError = deserializeConsensusError(data.serializedError || []);

delete data.serializedError;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ describe('createGrpcTransportError', () => {
metadata.set('drive-error-data-bin', driveErrorDataBin);

const grpcError = new GrpcError(
1000,
10001,
'Parsing error',
);
grpcError.metadata = metadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export async function creditTransfer(

this.logger.silly('[Identity#creditTransfer] Created IdentityCreditTransferTransition');

const signerKeyIndex = 2;
const signerKeyIndex = 3;

await signStateTransition(this, identityCreditTransferTransition, identity, signerKeyIndex);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export async function creditWithdrawal(
amount: number,
to: string,
options: WithdrawalOptions = {
signingKeyIndex: 2,
signingKeyIndex: 3,
},
): Promise<Metadata> {
await this.initialize();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,55 @@ export async function createIdentityCreateTransition(

const identityIndex = await account.getUnusedIdentityIndex();

// Authentication master key

const { privateKey: identityMasterPrivateKey } = account.identities
.getIdentityHDKeyByIndex(identityIndex, 0);
const identityMasterPublicKey = identityMasterPrivateKey.toPublicKey();

const { privateKey: identitySecondPrivateKey } = account.identities
const masterKey = new IdentityPublicKey(1);
masterKey.setId(0);
masterKey.setData(identityMasterPublicKey.toBuffer());
masterKey.setSecurityLevel(IdentityPublicKey.SECURITY_LEVELS.MASTER);

// Authentication high level key

const { privateKey: identityHighAuthPrivateKey } = account.identities
.getIdentityHDKeyByIndex(identityIndex, 1);
const identitySecondPublicKey = identitySecondPrivateKey.toPublicKey();
const identityHighAuthPublicKey = identityHighAuthPrivateKey.toPublicKey();

const highAuthKey = new IdentityPublicKey(1);
highAuthKey.setId(1);
highAuthKey.setData(identityHighAuthPublicKey.toBuffer());
highAuthKey.setSecurityLevel(IdentityPublicKey.SECURITY_LEVELS.HIGH);

// Authentication critical level key

const { privateKey: identityThirdPrivateKey } = account.identities
const { privateKey: identityCriticalAuthPrivateKey } = account.identities
.getIdentityHDKeyByIndex(identityIndex, 2);
const identityThirdPublicKey = identityThirdPrivateKey.toPublicKey();
const identityCriticalAuthPublicKey = identityCriticalAuthPrivateKey.toPublicKey();

const keyOne = new IdentityPublicKey(1);
keyOne.setData(identityMasterPublicKey.toBuffer());
keyOne.setSecurityLevel(IdentityPublicKey.SECURITY_LEVELS.MASTER);
const criticalAuthKey = new IdentityPublicKey(1);
criticalAuthKey.setId(2);
criticalAuthKey.setData(identityCriticalAuthPublicKey.toBuffer());
criticalAuthKey.setSecurityLevel(IdentityPublicKey.SECURITY_LEVELS.CRITICAL);

const keyTwo = new IdentityPublicKey(1);
keyTwo.setId(1);
keyTwo.setData(identitySecondPublicKey.toBuffer());
keyTwo.setSecurityLevel(IdentityPublicKey.SECURITY_LEVELS.HIGH);
// Transfer key

const keyThree = new IdentityPublicKey(1);
keyThree.setId(2);
keyThree.setData(identityThirdPublicKey.toBuffer());
keyThree.setSecurityLevel(IdentityPublicKey.SECURITY_LEVELS.CRITICAL);
const { privateKey: identityTransferPrivateKey } = account.identities
.getIdentityHDKeyByIndex(identityIndex, 3);
const identityTransferPublicKey = identityTransferPrivateKey.toPublicKey();

const transferKey = new IdentityPublicKey(1);
transferKey.setId(3);
transferKey.setPurpose(IdentityPublicKey.PURPOSES.TRANSFER);
transferKey.setData(identityTransferPublicKey.toBuffer());
transferKey.setSecurityLevel(IdentityPublicKey.SECURITY_LEVELS.CRITICAL);

// Create Identity
const identity = dpp.identity.create(
assetLockProof.createIdentifier(),
[keyOne, keyTwo, keyThree],
[masterKey, highAuthKey, criticalAuthKey, transferKey],
);

// Create ST
Expand All @@ -65,35 +84,62 @@ export async function createIdentityCreateTransition(
);

// Create key proofs
const [masterKey, secondKey, thirdKey] = identityCreateTransition.getPublicKeys();
const [
stMasterKey, stHighAuthKey, stCriticalAuthKey, stTransferKey,
] = identityCreateTransition.getPublicKeys();

// Sign master key

identityCreateTransition.signByPrivateKey(
identityMasterPrivateKey.toBuffer(),
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
);

await identityCreateTransition
.signByPrivateKey(identityMasterPrivateKey.toBuffer(), IdentityPublicKey.TYPES.ECDSA_SECP256K1);
stMasterKey.setSignature(identityCreateTransition.getSignature());

masterKey.setSignature(identityCreateTransition.getSignature());
identityCreateTransition.setSignature(undefined);

// Sign high auth key

identityCreateTransition.signByPrivateKey(
identityHighAuthPrivateKey.toBuffer(),
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
);

stHighAuthKey.setSignature(identityCreateTransition.getSignature());

identityCreateTransition.setSignature(undefined);

await identityCreateTransition
.signByPrivateKey(identitySecondPrivateKey.toBuffer(), IdentityPublicKey.TYPES.ECDSA_SECP256K1);
// Sign critical auth key

secondKey.setSignature(identityCreateTransition.getSignature());
identityCreateTransition.signByPrivateKey(
identityCriticalAuthPrivateKey.toBuffer(),
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
);

stCriticalAuthKey.setSignature(identityCreateTransition.getSignature());

identityCreateTransition.setSignature(undefined);

await identityCreateTransition
.signByPrivateKey(identityThirdPrivateKey.toBuffer(), IdentityPublicKey.TYPES.ECDSA_SECP256K1);
// Sign transfer key

identityCreateTransition.signByPrivateKey(
identityTransferPrivateKey.toBuffer(),
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
);

thirdKey.setSignature(identityCreateTransition.getSignature());
stTransferKey.setSignature(identityCreateTransition.getSignature());

identityCreateTransition.setSignature(undefined);

// Set public keys back after updating their signatures
identityCreateTransition.setPublicKeys([masterKey, secondKey, thirdKey]);
identityCreateTransition.setPublicKeys([
stMasterKey, stHighAuthKey, stCriticalAuthKey, stTransferKey,
]);

// Sign and validate state transition

await identityCreateTransition
identityCreateTransition
.signByPrivateKey(assetLockPrivateKey.toBuffer(), IdentityPublicKey.TYPES.ECDSA_SECP256K1);

// TODO(versioning): restore
Expand Down
14 changes: 7 additions & 7 deletions packages/platform-test-suite/test/e2e/dpns.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe('DPNS', () => {

expect(broadcastError).to.exist();
expect(broadcastError.message).to.be.equal('Action is not allowed');
expect(broadcastError.code).to.equal(4001);
expect(broadcastError.code).to.equal(40500);
});

it('should not be able to delete domain', async () => {
Expand All @@ -123,7 +123,7 @@ describe('DPNS', () => {

expect(broadcastError).to.exist();
expect(broadcastError.message).to.be.equal('Action is not allowed');
expect(broadcastError.code).to.equal(4001);
expect(broadcastError.code).to.equal(40500);
});
});

Expand Down Expand Up @@ -153,7 +153,7 @@ describe('DPNS', () => {

expect(broadcastError).to.exist();
expect(broadcastError.message).to.be.equal('Can\'t create top level domain for this identity');
expect(broadcastError.code).to.equal(4001);
expect(broadcastError.code).to.equal(40500);
});

it('should be able to register a second level domain', async () => {
Expand Down Expand Up @@ -185,7 +185,7 @@ describe('DPNS', () => {
}

expect(broadcastError).to.exist();
expect(broadcastError.code).to.be.equal(4009);
expect(broadcastError.code).to.be.equal(40105);
expect(broadcastError.message).to.match(/Document \w* has duplicate unique properties \["normalizedParentDomainName", "normalizedLabel"] with other documents/);
});

Expand All @@ -206,7 +206,7 @@ describe('DPNS', () => {

expect(broadcastError).to.exist();
expect(broadcastError.message).to.be.equal('Parent domain is not present');
expect(broadcastError.code).to.equal(4001);
expect(broadcastError.code).to.equal(40500);
});

it('should be able to search a domain', async () => {
Expand Down Expand Up @@ -251,7 +251,7 @@ describe('DPNS', () => {

expect(broadcastError).to.exist();
expect(broadcastError.message).to.be.equal('Action is not allowed');
expect(broadcastError.code).to.equal(4001);
expect(broadcastError.code).to.equal(40500);
});

it('should not be able to delete domain', async () => {
Expand All @@ -267,7 +267,7 @@ describe('DPNS', () => {

expect(broadcastError).to.exist();
expect(broadcastError.message).to.be.equal('Action is not allowed');
expect(broadcastError.code).to.equal(4001);
expect(broadcastError.code).to.equal(40500);
});

it('should not be able to register two domains with same `dashAliasIdentityId` record');
Expand Down
Loading

0 comments on commit 807942e

Please sign in to comment.