Skip to content

Commit

Permalink
Ische/sip2 #781
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacJChen committed Oct 10, 2020
1 parent 63a4c0f commit 8c59559
Show file tree
Hide file tree
Showing 78 changed files with 664 additions and 349 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
],
"rules": {
"dot-notation": ["off"],
"func-style": ["error", "expression"],
"max-len": ["error", { "code": 160, "ignoreStrings": true }],
"no-multi-spaces": ["error", { "ignoreEOLComments": true }],
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"error",
Expand Down
20 changes: 10 additions & 10 deletions lib/bitcoin/BitcoinClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,9 +574,9 @@ export default class BitcoinClient {
const payToScriptAddress = new Address(payToScriptHashOutput);

const freezeTransaction = new Transaction()
.from(unspentCoins)
.to(payToScriptAddress, freezeAmountInSatoshis)
.change(walletAddress);
.from(unspentCoins)
.to(payToScriptAddress, freezeAmountInSatoshis)
.change(walletAddress);

const transactionFee = await this.calculateTransactionFee(freezeTransaction);

Expand Down Expand Up @@ -642,8 +642,8 @@ export default class BitcoinClient {
// Now create a spend transaction using the frozen output. Create the transaction with all
// inputs and outputs as they are needed to calculate the fee.
const spendTransaction = new Transaction()
.from([frozenOutputAsInput])
.to(paytoAddress, previousFreezeAmountInSatoshis);
.from([frozenOutputAsInput])
.to(paytoAddress, previousFreezeAmountInSatoshis);

// The check-sequence-verify lock requires transaction version 2
(spendTransaction as any).version = 2;
Expand All @@ -661,7 +661,7 @@ export default class BitcoinClient {
// and add another one with the correct amount.
spendTransaction.outputs.shift();
spendTransaction.to(paytoAddress, previousFreezeAmountInSatoshis - transactionFee)
.fee(transactionFee);
.fee(transactionFee);

return spendTransaction;
}
Expand Down Expand Up @@ -691,10 +691,10 @@ export default class BitcoinClient {
const publicKeyHashOut = Script.buildPublicKeyHashOut(walletAddress);

const redeemScript = Script.empty()
.add(lockBuffer)
.add(178) // OP_CSV (https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki)
.add(117) // OP_DROP
.add(publicKeyHashOut);
.add(lockBuffer)
.add(178) // OP_CSV (https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki)
.add(117) // OP_DROP
.add(publicKeyHashOut);

return redeemScript;
}
Expand Down
6 changes: 3 additions & 3 deletions lib/bitcoin/BitcoinWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ export default class BitcoinWallet implements IBitcoinWallet {

// Create a script and add it to the input.
const inputScript = Script.empty()
.add(signature.toTxFormat())
.add(this.walletPublicKeyAsBuffer)
.add(inputRedeemScript.toBuffer());
.add(signature.toTxFormat())
.add(this.walletPublicKeyAsBuffer)
.add(inputRedeemScript.toBuffer());

(lockTransaction.inputs[0] as any).setScript(inputScript);

Expand Down
10 changes: 6 additions & 4 deletions lib/bitcoin/MongoDbBlockMetadataStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ export default class MongoDbBlockMetadataStore extends MongoDbStore implements I
let dbCursor: Cursor<BlockMetadata>;

// Add filter to query.
dbCursor = this.collection!.find({ $and: [
{ height: { $gte: fromInclusiveHeight } },
{ height: { $lt: toExclusiveHeight } }
] });
dbCursor = this.collection!.find({
$and: [
{ height: { $gte: fromInclusiveHeight } },
{ height: { $lt: toExclusiveHeight } }
]
});

// Add sort to query.
dbCursor = dbCursor.sort({ height: 1 });
Expand Down
6 changes: 3 additions & 3 deletions lib/bitcoin/lock/LockMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,9 +367,9 @@ export default class LockMonitor {

const relockTransaction =
await this.bitcoinClient.createRelockTransaction(
currentLockIdentifier.transactionId,
currentLockDuration,
this.lockPeriodInBlocks);
currentLockIdentifier.transactionId,
currentLockDuration,
this.lockPeriodInBlocks);

// If the transaction fee is making the relock amount less than the desired amount
if (currentValueTimeLock.amountLocked - relockTransaction.transactionFee < desiredLockAmountInSatoshis) {
Expand Down
8 changes: 4 additions & 4 deletions lib/bitcoin/lock/MongoDbLockTransactionStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ export default class MongoDbLockTransactionStore {
*/
public async getLastLock (): Promise<SavedLockModel | undefined> {
const lastLocks = await this.lockCollection!
.find()
.limit(1)
.sort({ createTimestamp: -1 })
.toArray();
.find()
.limit(1)
.sort({ createTimestamp: -1 })
.toArray();

if (!lastLocks || lastLocks.length <= 0) {
return undefined;
Expand Down
10 changes: 6 additions & 4 deletions lib/common/MongoDbTransactionStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,12 @@ export default class MongoDbTransactionStore implements ITransactionStore {
// if begin === end, query for 1 transaction time
cursor = this.transactionCollection!.find({ transactionTime: { $eq: Long.fromNumber(inclusiveBeginTransactionTime) } });
} else {
cursor = this.transactionCollection!.find({ $and: [
{ transactionTime: { $gte: Long.fromNumber(inclusiveBeginTransactionTime) } },
{ transactionTime: { $lt: Long.fromNumber(exclusiveEndTransactionTime) } }
] });
cursor = this.transactionCollection!.find({
$and: [
{ transactionTime: { $gte: Long.fromNumber(inclusiveBeginTransactionTime) } },
{ transactionTime: { $lt: Long.fromNumber(exclusiveEndTransactionTime) } }
]
});
}

const transactions: TransactionModel[] = await cursor.sort({ transactionNumber: 1 }).toArray();
Expand Down
2 changes: 1 addition & 1 deletion lib/core/Core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default class Core {
this.operationStore,
this.resolver,
this.transactionStore
); // `VersionManager` is last initialized component.
); // `VersionManager` is last initialized component.

await this.observer.startPeriodicProcessing();

Expand Down
28 changes: 15 additions & 13 deletions lib/core/MongoDbOperationStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,19 +106,21 @@ export default class MongoDbOperationStore implements IOperationStore {
}

public async deleteUpdatesEarlierThan (didUniqueSuffix: string, transactionNumber: number, operationIndex: number): Promise<void> {
await this.collection!.deleteMany({ $or: [
{
didSuffix: didUniqueSuffix,
txnNumber: { $lt: Long.fromNumber(transactionNumber) },
type: OperationType.Update
},
{
didSuffix: didUniqueSuffix,
txnNumber: Long.fromNumber(transactionNumber),
opIndex: { $lt: operationIndex },
type: OperationType.Update
}
]});
await this.collection!.deleteMany({
$or: [
{
didSuffix: didUniqueSuffix,
txnNumber: { $lt: Long.fromNumber(transactionNumber) },
type: OperationType.Update
},
{
didSuffix: didUniqueSuffix,
txnNumber: Long.fromNumber(transactionNumber),
opIndex: { $lt: operationIndex },
type: OperationType.Update
}
]
});
}

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/core/Resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export default class Resolver {
private async applyOperation (
operation: AnchoredOperationModel,
didState: DidState | undefined
): Promise<DidState | undefined> {
): Promise<DidState | undefined> {
let appliedDidState = didState;

// NOTE: MUST NOT throw error, else a bad operation can be used to denial resolution for a DID.
Expand Down
4 changes: 2 additions & 2 deletions lib/core/versions/0.11.0/TransactionProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ export default class TransactionProcessor implements ITransactionProcessor {

// Verify required lock if one was needed.
const valueTimeLock = anchorFile.model.writer_lock_id
? await this.blockchain.getValueTimeLock(anchorFile.model.writer_lock_id)
: undefined;
? await this.blockchain.getValueTimeLock(anchorFile.model.writer_lock_id)
: undefined;
ValueTimeLockVerifier.verifyLockAmountAndThrowOnError(
valueTimeLock,
paidOperationCount,
Expand Down
6 changes: 5 additions & 1 deletion lib/core/versions/latest/AnchorFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,11 @@ export default class AnchorFile {

const createOperations = createOperationArray.map(operation => {
return {
suffix_data: operation.encodedSuffixData
suffix_data: {
delta_hash: operation.suffixData.deltaHash,
recovery_commitment: operation.suffixData.recoveryCommitment,
type: operation.suffixData.type
}
};
});

Expand Down
2 changes: 1 addition & 1 deletion lib/core/versions/latest/BatchWriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export default class BatchWriter implements IBatchWriter {
const maxNumberOfOpsAllowedByLock = ValueTimeLockVerifier.calculateMaxNumberOfOperationsAllowed(valueTimeLock, this.versionMetadataFetcher);

if (maxNumberOfOpsAllowedByLock > maxNumberOfOpsAllowedByProtocol) {
// tslint:disable-next-line: max-line-length
// eslint-disable-next-line max-len
console.info(`Maximum number of operations allowed by value time lock: ${maxNumberOfOpsAllowedByLock}; Maximum number of operations allowed by protocol: ${maxNumberOfOpsAllowedByProtocol}`);
}

Expand Down
16 changes: 8 additions & 8 deletions lib/core/versions/latest/ChunkFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ export default class ChunkFile {
throw new SidetreeError(ErrorCode.ChunkFileDeltasPropertyNotArray, 'Invalid chunk file, deltas property is not an array.');
}

// Validate every encoded delta string.
for (const encodedDelta of deltas) {
if (typeof encodedDelta !== 'string') {
throw new SidetreeError(ErrorCode.ChunkFileDeltasNotArrayOfStrings, 'Invalid chunk file, deltas property is not an array of strings.');
// Validate every delta is an object
for (const delta of deltas) {
if (typeof delta !== 'object') {
throw new SidetreeError(ErrorCode.ChunkFileDeltasNotArrayOfObjects, 'Invalid chunk file, deltas property is not an array of objects.');
}

// Verify size of each delta does not exceed the maximum allowed limit.
Delta.validateEncodedDeltaSize(encodedDelta);
Delta.validateDeltaSize(delta);
}
}

Expand All @@ -64,9 +64,9 @@ export default class ChunkFile {
*/
public static async createBuffer (createOperations: CreateOperation[], recoverOperations: RecoverOperation[], updateOperations: UpdateOperation[]) {
const deltas = [];
deltas.push(...createOperations.map(operation => operation.encodedDelta!));
deltas.push(...recoverOperations.map(operation => operation.encodedDelta!));
deltas.push(...updateOperations.map(operation => operation.encodedDelta!));
deltas.push(...createOperations.map(operation => operation.delta!));
deltas.push(...recoverOperations.map(operation => operation.delta!));
deltas.push(...updateOperations.map(operation => operation.delta!));

const chunkFileModel = {
deltas
Expand Down
3 changes: 2 additions & 1 deletion lib/core/versions/latest/CreateOperation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default class CreateOperation implements OperationModel {
public static async parseOperationFromAnchorFile (input: any): Promise<CreateOperation> {
// Issue #442 - Replace `operationBuffer` in `OperationModel` and `AnchoredOperationModel` with actual operation request
const operationBuffer = Buffer.from(JSON.stringify(input));
const operation = await CreateOperation.parseObject(input, operationBuffer, true);
const operation = await CreateOperation.parseJcsObject(input, operationBuffer, true);
return operation;
}

Expand Down Expand Up @@ -157,6 +157,7 @@ export default class CreateOperation implements OperationModel {
// thus an operation with invalid `delta` needs to be processed as an operation with unavailable `delta`,
// so here we let `delta` be `undefined`.
}
// TODO: SIP 2 #781 remove encoded delta and encoded suffix data when old long form is fully deprecated.
encodedDelta = Encoder.encode(JsonCanonicalizer.canonicalizeAsBuffer(operationObject.delta));
}

Expand Down
2 changes: 1 addition & 1 deletion lib/core/versions/latest/Delta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default class Delta {

/**
* Validates size of the encoded delta string.
* TODO: SIP 2 #781 delete this and use validateDeltaSize only in chunk file
* TODO: SIP 2 #781 delete this when long form is fully switched over
* @throws `SidetreeError` if fails validation.
*/
public static validateEncodedDeltaSize (encodedDelta: string) {
Expand Down
2 changes: 1 addition & 1 deletion lib/core/versions/latest/ErrorCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default {
CasFileNotFound: 'cas_file_not_found',
CasFileTooLarge: 'cas_file_too_large',
CasNotReachable: 'cas_not_reachable',
ChunkFileDeltasNotArrayOfStrings: 'chunk_file_deltas_not_array_of_string',
ChunkFileDeltasNotArrayOfObjects: 'chunk_file_deltas_not_array_of_objects',
ChunkFileDeltasPropertyNotArray: 'chunk_file_deltas_property_not_array',
ChunkFileUnexpectedProperty: 'chunk_file_unexpected_property',
CompressorMaxAllowedDecompressedDataSizeExceeded: 'compressor_max_allowed_decompressed_data_size_exceeded',
Expand Down
4 changes: 2 additions & 2 deletions lib/core/versions/latest/Multihash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export default class Multihash {

try {
const contentBuffer = Encoder.decodeAsBuffer(encodedContent);
return Multihash.verify(contentBuffer, encodedMultihash);
return Multihash.verifyEncodedMultihashForContent(contentBuffer, encodedMultihash);
} catch (error) {
console.log(error);
return false;
Expand Down Expand Up @@ -193,7 +193,7 @@ export default class Multihash {
/**
* Verifies the multihash against the content `Buffer`.
*/
private static verify (content: Buffer, encodedMultihash: string): boolean {
public static verifyEncodedMultihashForContent (content: Buffer, encodedMultihash: string): boolean {

try {
const expectedMultihashBuffer = Encoder.decodeAsBuffer(encodedMultihash);
Expand Down
2 changes: 1 addition & 1 deletion lib/core/versions/latest/Operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default class Operation {
const isAnchorFileMode = false;

if (operationType === OperationType.Create) {
return CreateOperation.parseObject(operationObject, operationBuffer, isAnchorFileMode);
return CreateOperation.parseJcsObject(operationObject, operationBuffer, isAnchorFileMode);
} else if (operationType === OperationType.Update) {
return UpdateOperation.parseObject(operationObject, operationBuffer, isAnchorFileMode);
} else if (operationType === OperationType.Recover) {
Expand Down
42 changes: 33 additions & 9 deletions lib/core/versions/latest/OperationProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,19 @@ export default class OperationProcessor implements IOperationProcessor {
lastOperationTransactionNumber: anchoredOperationModel.transactionNumber
};

// Ensure actual delta hash matches expected delta hash.
const isMatchingDelta = Multihash.isValidHash(operation.encodedDelta, operation.suffixData.deltaHash);
// Verify the delta hash against the expected delta hash.
const deltaPayload = operation.delta ? JsonCanonicalizer.canonicalizeAsBuffer({
update_commitment: operation.delta.updateCommitment,
patches: operation.delta.patches
}) : undefined;
if (deltaPayload === undefined) {
return newDidState;
};

const isMatchingDelta = Multihash.verifyEncodedMultihashForContent(deltaPayload, operation.suffixData.deltaHash);
if (!isMatchingDelta) {
return newDidState;
}
};

// Apply the given patches against an empty object.
const delta = operation.delta;
Expand Down Expand Up @@ -163,10 +171,18 @@ export default class OperationProcessor implements IOperationProcessor {
}

// Verify the delta hash against the expected delta hash.
const isValidDelta = Multihash.isValidHash(operation.encodedDelta, operation.signedData.deltaHash);
if (!isValidDelta) {
const deltaPayload = operation.delta ? JsonCanonicalizer.canonicalizeAsBuffer({
update_commitment: operation.delta.updateCommitment,
patches: operation.delta.patches
}) : undefined;
if (deltaPayload === undefined) {
return didState;
}
};

const isMatchingDelta = Multihash.verifyEncodedMultihashForContent(deltaPayload, operation.signedData.deltaHash);
if (!isMatchingDelta) {
return didState;
};

let resultingDocument;
try {
Expand Down Expand Up @@ -221,11 +237,19 @@ export default class OperationProcessor implements IOperationProcessor {
lastOperationTransactionNumber: anchoredOperationModel.transactionNumber
};

// Verify the actual delta hash against the expected delta hash.
const isMatchingDelta = Multihash.isValidHash(operation.encodedDelta, operation.signedData.deltaHash);
// Verify the delta hash against the expected delta hash.
const deltaPayload = operation.delta ? JsonCanonicalizer.canonicalizeAsBuffer({
update_commitment: operation.delta.updateCommitment,
patches: operation.delta.patches
}) : undefined;
if (deltaPayload === undefined) {
return newDidState;
};

const isMatchingDelta = Multihash.verifyEncodedMultihashForContent(deltaPayload, operation.signedData.deltaHash);
if (!isMatchingDelta) {
return newDidState;
}
};

// Apply the given patches against an empty object.
const delta = operation.delta;
Expand Down
Loading

0 comments on commit 8c59559

Please sign in to comment.