Skip to content

Commit

Permalink
- Removing unnecessary witness parameter for Deciders (#402)
Browse files Browse the repository at this point in the history
- Making AndDecider accept more than 2 inputs
  • Loading branch information
willmeister committed Aug 22, 2019
1 parent c4cc067 commit 2ad88f4
Show file tree
Hide file tree
Showing 16 changed files with 233 additions and 293 deletions.
55 changes: 27 additions & 28 deletions packages/core/src/app/ovm/deciders/and-decider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import {
import { CannotDecideError, handleCannotDecideError } from './utils'

export interface AndDeciderInput {
left: Property
leftWitness: any
right: Property
rightWitness: any
properties: Property[]
}

/**
Expand All @@ -28,38 +25,40 @@ export class AndDecider implements Decider {

public async decide(
input: AndDeciderInput,
witness?: undefined,
noCache?: boolean
): Promise<Decision> {
const [leftDecision, rightDecision] = await Promise.all([
input.left.decider
.decide(input.left.input, input.leftWitness, noCache)
.catch(handleCannotDecideError),
input.right.decider
.decide(input.right.input, input.rightWitness, noCache)
.catch(handleCannotDecideError),
])
const decisions: Decision[] = await Promise.all(
input.properties.map((p) =>
p.decider.decide(p.input, noCache).catch(handleCannotDecideError)
)
)

const justification: ImplicationProofItem[] = []
let undecideable = false
let falseDecision
for (const decision of decisions) {
if (!decision) {
undecideable = true
continue
}

if (!!leftDecision && !leftDecision.outcome) {
return this.getDecision(input, leftDecision)
if (!decision.outcome) {
falseDecision = decision
break
}
justification.push(...decision.justification)
}
if (!!rightDecision && !rightDecision.outcome) {
return this.getDecision(input, rightDecision)

if (!!falseDecision) {
return this.getDecision(input, falseDecision)
}
if (!leftDecision || !rightDecision) {

if (undecideable) {
throw new CannotDecideError(
'One of the AND deciders could not decide, and neither decided false.'
'One of the AND deciders could not decide, and none decided false.'
)
}

const justification: ImplicationProofItem[] = []
if (!!leftDecision.justification.length) {
justification.push(...leftDecision.justification)
}
if (!!rightDecision.justification.length) {
justification.push(...rightDecision.justification)
}

return this.getDecision(input, { outcome: true, justification })
}

Expand All @@ -68,7 +67,7 @@ export class AndDecider implements Decider {
* returns true if both sub-Decisions returned true.
*
* @param input The input that led to the Decision
* @param subDecision The decision of the wrapped Property, provided the witness
* @param subDecision The decision of the wrapped Property
* @returns The Decision
*/
private getDecision(input: AndDeciderInput, subDecision: Decision): Decision {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export class MessageNonceLessThanDecider implements Decider {

public async decide(
input: MessageNonceLessThanInput,
witness: undefined,
noCache?: boolean
): Promise<Decision> {
const justification: ImplicationProofItem[] = [
Expand All @@ -30,7 +29,7 @@ export class MessageNonceLessThanDecider implements Decider {
decider: this,
input,
},
implicationWitness: witness,
implicationWitness: undefined,
},
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export interface ForAllSuchThatInput {
quantifier: Quantifier
quantifierParameters: any
propertyFactory: PropertyFactory
witnessFactory?: WitnessFactory | undefined
}

/**
Expand All @@ -32,7 +31,6 @@ export class ForAllSuchThatDecider implements Decider {

public async decide(
input: ForAllSuchThatInput,
_witness?: undefined,
noCache?: boolean
): Promise<Decision> {
const quantifierResult: QuantifierResult = await input.quantifier.getAllQuantified(
Expand All @@ -44,13 +42,9 @@ export class ForAllSuchThatDecider implements Decider {
const trueDecisions: Decision[] = []
for (const res of quantifierResult.results) {
const prop: Property = input.propertyFactory(res)
const witness: any = !!input.witnessFactory
? input.witnessFactory(res)
: undefined
try {
const decision: Decision = await prop.decider.decide(
prop.input,
witness,
noCache
)
if (!decision.outcome) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ export class HashPreimageExistenceDecider implements Decider {
private readonly hashAlgorithm: HashAlgorithm
) {}

public async decide(
input: HashInput,
_witness?: undefined,
_noCache?: boolean
): Promise<Decision> {
public async decide(input: HashInput, _noCache?: boolean): Promise<Decision> {
const preimage: Buffer = await this.db.getPreimage(
input.hash,
this.hashAlgorithm
Expand Down
3 changes: 0 additions & 3 deletions packages/core/src/app/ovm/deciders/not-decider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {

export interface NotDeciderInput {
property: Property
witness: any
}

/**
Expand All @@ -16,12 +15,10 @@ export interface NotDeciderInput {
export class NotDecider implements Decider {
public async decide(
input: NotDeciderInput,
witness?: undefined,
noCache?: boolean
): Promise<Decision> {
const decision: Decision = await input.property.decider.decide(
input.property.input,
input.witness,
noCache
)

Expand Down
6 changes: 2 additions & 4 deletions packages/core/src/app/ovm/deciders/or-decider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { CannotDecideError, handleCannotDecideError } from './utils'

export interface OrDeciderInput {
properties: Property[]
witnesses: any[]
}

/**
Expand All @@ -26,13 +25,12 @@ export class OrDecider implements Decider {

public async decide(
input: OrDeciderInput,
witness?: undefined,
noCache?: boolean
): Promise<Decision> {
const decisions: Decision[] = await Promise.all(
input.properties.map((property: Property, index: number) =>
property.decider
.decide(property.input, input.witnesses[index], noCache)
.decide(property.input, noCache)
.catch(handleCannotDecideError)
)
)
Expand Down Expand Up @@ -74,7 +72,7 @@ export class OrDecider implements Decider {
* returns true if any of the sub-Decisions returned true.
*
* @param input The input that led to the Decision
* @param subDecision The decision of the wrapped Property, provided the witness
* @param subDecision The decision of the wrapped Property
* @returns The Decision
*/
private getDecision(input: OrDeciderInput, subDecision: Decision): Decision {
Expand Down
8 changes: 2 additions & 6 deletions packages/core/src/app/ovm/deciders/signed-by-decider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,15 @@ export class SignedByDecider implements Decider {
private readonly myAddress: Buffer
) {}

public async decide(
input: any,
_witness?: undefined,
_noCache?: boolean
): Promise<Decision> {
public async decide(input: any, _noCache?: boolean): Promise<Decision> {
const signature: Buffer = await this.signedByDb.getMessageSignature(
input.message,
input.publicKey
)

if (!signature && !input.publicKey.equals(this.myAddress)) {
throw new CannotDecideError(
'Signature does not match the provided witness, but we do not know for certain that the message was not signed by the private key associated with the provided public key.'
'We do not have a signature for this public key and message, but we do not know for certain that the message was not signed by the private key associated with the provided public key.'
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export interface ThereExistsSuchThatInput {
quantifier: Quantifier
quantifierParameters: any
propertyFactory: PropertyFactory
witnessFactory: WitnessFactory | undefined
}

/**
Expand All @@ -24,7 +23,6 @@ export interface ThereExistsSuchThatInput {
export class ThereExistsSuchThatDecider implements Decider {
public async decide(
input: ThereExistsSuchThatInput,
_witness?: undefined,
noCache?: boolean
): Promise<Decision> {
const quantifierResult: QuantifierResult = await input.quantifier.getAllQuantified(
Expand All @@ -36,13 +34,9 @@ export class ThereExistsSuchThatDecider implements Decider {
const falseDecisions: Decision[] = []
for (const res of quantifierResult.results) {
const prop: Property = input.propertyFactory(res)
const witness: any = !!input.witnessFactory
? input.witnessFactory(res)
: undefined
try {
const decision: Decision = await prop.decider.decide(
prop.input,
witness,
noCache
)
if (decision.outcome) {
Expand Down
61 changes: 32 additions & 29 deletions packages/core/src/app/ovm/examples/state-channel-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,38 +131,41 @@ export class StateChannelClient {
return {
decider: AndDecider.instance(),
input: {
left: {
decider: this.signedByDecider,
input: {
message: messageToBuffer(
mostRecent.message,
stateChannelMessageToString
),
publicKey: counterparty,
properties: [
{
decider: this.signedByDecider,
input: {
message: messageToBuffer(
mostRecent.message,
stateChannelMessageToString
),
publicKey: counterparty,
},
witness: {
signature: mostRecent.signatures[counterparty.toString()],
},
},
},
leftWitness: undefined,
right: {
decider: ForAllSuchThatDecider.instance(),
input: {
quantifier: this.signedByQuantifier,
quantifierParameters: { address: this.myAddress },
propertyFactory: (signedMessage: Buffer) => {
return {
decider: MessageNonceLessThanDecider.instance(),
input: {
messageWithNonce: deserializeBuffer(
signedMessage,
deserializeMessage,
stateChannelMessageDeserializer
),
lessThanThis: mostRecent.message.nonce.add(ONE),
},
}
{
decider: ForAllSuchThatDecider.instance(),
input: {
quantifier: this.signedByQuantifier,
quantifierParameters: { address: this.myAddress },
propertyFactory: (signedMessage: Buffer) => {
return {
decider: MessageNonceLessThanDecider.instance(),
input: {
messageWithNonce: deserializeBuffer(
signedMessage,
deserializeMessage,
stateChannelMessageDeserializer
),
lessThanThis: mostRecent.message.nonce.add(ONE),
},
}
},
},
},
},
rightWitness: undefined,
],
},
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,21 @@ export type NonceLessThanPropertyFactory = (input: any) => NonceLessThanProperty
export interface StateChannelExitClaim extends Property {
decider: AndDecider
input: {
left: {
decider: SignedByDecider // Asserts this message is signed by counter-party
input: SignedByInput
}
leftWitness: any
right: {
decider: ForAllSuchThatDecider
input: {
quantifier: SignedByQuantifier
quantifierParameters: any
propertyFactory: NonceLessThanPropertyFactory
properties: [
{
decider: SignedByDecider // Asserts this message is signed by counter-party
input: SignedByInput
witness: {}
},
{
decider: ForAllSuchThatDecider
input: {
quantifier: SignedByQuantifier
quantifierParameters: any
propertyFactory: NonceLessThanPropertyFactory
}
}
}
rightWitness: any
]
}
}

Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/types/ovm/decider.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type Proof = ProofItem[]
export interface Property {
decider: Decider
input: {}
witness?: any
}

export type PropertyFactory = (input: any) => Property
Expand All @@ -28,22 +29,21 @@ export interface Decision {
* on the provided input according to the logic of the specific implementation.
*
* For example: A PreimageExistsDecider would be able to make decisions on whether
* or not the provided witness, when hashed, results in the provided input.
* or not a hash preimage has been stored in its database.
*/
export interface Decider {
/**
* Makes a Decision on the provided input, given the provided witness.
* Makes a Decision on the provided input.
*
* If this Decider is capable of caching and the noCache flag is not set,
* it will first check to see if a decision has already been made on this input.
* If this Decider is capable of caching and the noCache flag is set,
* it will make the Decision, if possible, and overwrite the cache.
*
* @param input The input on which a decision is being made
* @param witness [optional] The evidence for the decision if not relying on cached decisions
* @param noCache [optional] Flag set when caching should not be used.
* @returns the Decision that was made if one was possible
* @throws CannotDecideError if it cannot decide.
*/
decide(input: any, witness?: any, noCache?: boolean): Promise<Decision>
decide(input: any, noCache?: boolean): Promise<Decision>
}

0 comments on commit 2ad88f4

Please sign in to comment.