1
0
mirror of https://github.com/oceanprotocol-archive/squid-js.git synced 2024-02-02 15:31:51 +01:00

fix lockPayment

This commit is contained in:
Sebastian Gerske 2018-11-22 09:22:27 +01:00
parent 38d7d2c8eb
commit 43fe8634d2
9 changed files with 164 additions and 91 deletions

View File

@ -10,8 +10,11 @@ export default class ServiceAgreement extends ContractBase {
return serviceAgreement return serviceAgreement
} }
public async setupAgreementTemplate(templateId: string, methodReflections: MethodReflection[], public async setupAgreementTemplate(templateId: string,
dependencyMatrix: number[], name: any, fulfillmentIndices: number[], methodReflections: MethodReflection[],
dependencyMatrix: number[],
name: any,
fulfillmentIndices: number[],
fulfillmentOperator: number, fulfillmentOperator: number,
ownerAddress: string) ownerAddress: string)
: Promise<Receipt> { : Promise<Receipt> {

View File

@ -13,7 +13,6 @@ import Service from "../ddo/Service"
import Keeper from "../keeper/Keeper" import Keeper from "../keeper/Keeper"
import Web3Provider from "../keeper/Web3Provider" import Web3Provider from "../keeper/Web3Provider"
import Config from "../models/Config" import Config from "../models/Config"
import InputType from "../models/InputType"
import ValueType from "../models/ValueType" import ValueType from "../models/ValueType"
import SecretStoreProvider from "../secretstore/SecretStoreProvider" import SecretStoreProvider from "../secretstore/SecretStoreProvider"
import Logger from "../utils/Logger" import Logger from "../utils/Logger"
@ -107,11 +106,11 @@ export default class Ocean {
return null return null
} }
const parameters: Parameter[] = condition.methodReflection.inputs.map((input: InputType) => { const parameters: Parameter[] = condition.parameters.map((parameter: Parameter) => {
return { return {
name: input.name, name: parameter.name,
type: input.type, type: parameter.type,
value: mapParameterValueToName(input.name), value: mapParameterValueToName(parameter.name),
} as Parameter } as Parameter
}) })

View File

@ -1,4 +1,5 @@
import MethodReflection from "../../models/MethodReflection" import MethodReflection from "../../models/MethodReflection"
import Parameter from "./Parameter"
export default class Condition { export default class Condition {
public methodReflection: MethodReflection public methodReflection: MethodReflection
@ -7,4 +8,5 @@ export default class Condition {
public dependencyTimeoutFlags: number[] public dependencyTimeoutFlags: number[]
public isTerminalCondition: boolean public isTerminalCondition: boolean
public timeout: number public timeout: number
public parameters: Parameter[]
} }

View File

@ -1,8 +1,11 @@
import Parameter from "./Parameter"
export default class Method { export default class Method {
public name: string public name: string
public contractName: string public contractName: string
public methodName: string public methodName: string
public timeout: number public timeout: number
public parameters: Parameter[]
public dependencies: string[] public dependencies: string[]
public dependencyTimeoutFlags: number[] public dependencyTimeoutFlags: number[]
public isTerminalCondition: boolean public isTerminalCondition: boolean

View File

@ -0,0 +1,4 @@
export default class Parameter {
public name: string
public type: string
}

View File

@ -19,18 +19,12 @@ export default class ServiceAgreement extends OceanBase {
// Logger.log("signing SA", serviceAgreementId) // Logger.log("signing SA", serviceAgreementId)
const service: Service = ddo.findServiceById(serviceDefinitionId) const service: Service = ddo.findServiceById(serviceDefinitionId)
const values: ValuePair[] = ServiceAgreement.getValuesFromService(service, serviceAgreementId) const values: ValuePair[][] = ServiceAgreement.getValuesFromService(service, serviceAgreementId)
const valueHashes = ServiceAgreement.createValueHashes(values) const valueHashes: string[] = ServiceAgreement.createValueHashes(values)
const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromService(service) const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromService(service)
const serviceAgreementHashSignature = await ServiceAgreement const serviceAgreementHashSignature = await ServiceAgreement.createSAHashSignature(service, serviceAgreementId,
.createSAHashSignature( valueHashes, timeoutValues, consumer)
service,
serviceAgreementId,
values,
valueHashes,
timeoutValues,
consumer)
return serviceAgreementHashSignature return serviceAgreementHashSignature
} }
@ -46,8 +40,8 @@ export default class ServiceAgreement extends OceanBase {
// Logger.log("executing SA", serviceAgreementId) // Logger.log("executing SA", serviceAgreementId)
const service: Service = ddo.findServiceById(serviceDefinitionId) const service: Service = ddo.findServiceById(serviceDefinitionId)
const values: ValuePair[] = ServiceAgreement.getValuesFromService(service, serviceAgreementId) const values: ValuePair[][] = ServiceAgreement.getValuesFromService(service, serviceAgreementId)
const valueHashes = ServiceAgreement.createValueHashes(values) const valueHashes: string[] = ServiceAgreement.createValueHashes(values)
const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromService(service) const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromService(service)
// todo get consumer from ddo // todo get consumer from ddo
@ -60,11 +54,9 @@ export default class ServiceAgreement extends OceanBase {
private static async createSAHashSignature(service: Service, private static async createSAHashSignature(service: Service,
serviceAgreementId: string, serviceAgreementId: string,
values: ValuePair[],
valueHashes: string[], valueHashes: string[],
timeoutValues: number[], timeoutValues: number[],
consumer: Account): consumer: Account): Promise<string> {
Promise<string> {
if (!service.templateId) { if (!service.templateId) {
throw new Error("TemplateId not found in ddo.") throw new Error("TemplateId not found in ddo.")
@ -74,13 +66,16 @@ export default class ServiceAgreement extends OceanBase {
return condition.conditionKey return condition.conditionKey
}) })
const serviceAgreementHash = ServiceAgreement if (conditionKeys.length !== valueHashes.length) {
.hashServiceAgreement( throw new Error("Hashing SA failed!")
service.templateId, }
serviceAgreementId,
conditionKeys, const serviceAgreementHash = ServiceAgreement.hashServiceAgreement(
valueHashes, service.templateId,
timeoutValues) serviceAgreementId,
conditionKeys,
valueHashes,
timeoutValues)
const serviceAgreementHashSignature = await Web3Provider const serviceAgreementHashSignature = await Web3Provider
.getWeb3().eth.sign(serviceAgreementHash, consumer.getId()) .getWeb3().eth.sign(serviceAgreementHash, consumer.getId())
@ -130,18 +125,31 @@ export default class ServiceAgreement extends OceanBase {
) )
} }
private static createValueHashes(valuePairs: ValuePair[]): any[] { private static createValueHashes(parameterValuePairs: ValuePair[][]): string[] {
return valuePairs.map((valuePair) => {
return ServiceAgreement.hashSingleValue(valuePair) const hashes: string[] = []
parameterValuePairs.map((valuePairs: ValuePair[]) => {
hashes.push(ServiceAgreement.hashValuePairArray(valuePairs))
}) })
return hashes
} }
private static hashSingleValue(data: ValuePair): string { private static hashValuePairArray(valuePairs: ValuePair[]): string {
let hash: string
try { try {
return Web3Provider.getWeb3().utils.soliditySha3(data).toString("hex") hash = Web3Provider.getWeb3().utils.soliditySha3(...valuePairs).toString("hex")
} catch (err) { } catch (err) {
Logger.error(`Hashing of ${JSON.stringify(data, null, 2)} failed.`) Logger.error(`Hashing of ${JSON.stringify(valuePairs, null, 2)} failed.`)
throw err
} }
if (!hash) {
throw new Error("hashValuePairArray failed to create hash.")
}
return hash
} }
private static hashServiceAgreement(serviceAgreementTemplateId: string, private static hashServiceAgreement(serviceAgreementTemplateId: string,
@ -168,20 +176,22 @@ export default class ServiceAgreement extends OceanBase {
return timeoutValues return timeoutValues
} }
private static getValuesFromService(service: Service, serviceAgreementId: string): ValuePair[] { private static getValuesFromService(service: Service, serviceAgreementId: string): ValuePair[][] {
const values: ValuePair[] = [] const values: ValuePair[][] = []
service.conditions.forEach((condition) => { service.conditions.forEach((condition, i) => {
const contionValues: ValuePair[] = []
condition.parameters.forEach((parameter) => { condition.parameters.forEach((parameter) => {
values.push({
contionValues.push({
type: parameter.type, type: parameter.type,
value: parameter.name === "serviceId" ? "0x" + serviceAgreementId : parameter.value, value: parameter.name === "serviceId" ? "0x" + serviceAgreementId : parameter.value,
} as ValuePair) } as ValuePair)
}) })
})
// Logger.log("Values", JSON.stringify(values, null, 2)) values[i] = contionValues
})
return values return values
} }
@ -198,11 +208,11 @@ export default class ServiceAgreement extends OceanBase {
public async lockPayment(assetId: string, price: number, consumer: Account): Promise<boolean> { public async lockPayment(assetId: string, price: number, consumer: Account): Promise<boolean> {
const {paymentConditions} = await Keeper.getInstance() const {paymentConditions} = await Keeper.getInstance()
const lockPaymentRceipt = const lockPaymentReceipt =
await paymentConditions.lockPayment(this.getId(), assetId, price, await paymentConditions.lockPayment(this.getId(), assetId, price,
consumer.getId()) consumer.getId())
return lockPaymentRceipt.status return lockPaymentReceipt.status
} }
public async grantAccess(assetId: string, documentId: string): Promise<boolean> { public async grantAccess(assetId: string, documentId: string): Promise<boolean> {

View File

@ -12,8 +12,8 @@ import TemplateBase from "./Templates/TemplateBase"
export default class ServiceAgreementTemplate extends OceanBase { export default class ServiceAgreementTemplate extends OceanBase {
private static generateConditionsKey(serviceAgreementTemplateId: string, methodReflection: MethodReflection) private static generateConditionsKey(serviceAgreementTemplateId: string,
: string { methodReflection: MethodReflection): string {
const values = [ const values = [
{type: "bytes32", value: serviceAgreementTemplateId} as ValuePair, {type: "bytes32", value: serviceAgreementTemplateId} as ValuePair,
{type: "address", value: methodReflection.address} as ValuePair, {type: "address", value: methodReflection.address} as ValuePair,
@ -106,6 +106,7 @@ export default class ServiceAgreementTemplate extends OceanBase {
return { return {
methodReflection, methodReflection,
timeout: method.timeout, timeout: method.timeout,
parameters: method.parameters,
dependencies: method.dependencies, dependencies: method.dependencies,
dependencyTimeoutFlags: method.dependencyTimeoutFlags, dependencyTimeoutFlags: method.dependencyTimeoutFlags,
isTerminalCondition: method.isTerminalCondition, isTerminalCondition: method.isTerminalCondition,

View File

@ -11,6 +11,16 @@ export default class Access extends TemplateBase {
contractName: "PaymentConditions", contractName: "PaymentConditions",
methodName: "lockPayment", methodName: "lockPayment",
timeout: 0, timeout: 0,
parameters: [
{
name: "assetId",
type: "bytes32",
},
{
name: "price",
type: "uint256",
},
],
dependencies: [], dependencies: [],
dependencyTimeoutFlags: [], dependencyTimeoutFlags: [],
isTerminalCondition: false, isTerminalCondition: false,
@ -20,6 +30,16 @@ export default class Access extends TemplateBase {
contractName: "AccessConditions", contractName: "AccessConditions",
methodName: "grantAccess", methodName: "grantAccess",
timeout: 10, timeout: 10,
parameters: [
{
name: "assetId",
type: "bytes32",
},
{
name: "documentKeyId",
type: "bytes32",
},
],
dependencies: ["lockPayment"], dependencies: ["lockPayment"],
dependencyTimeoutFlags: [0], dependencyTimeoutFlags: [0],
isTerminalCondition: false, isTerminalCondition: false,
@ -29,6 +49,16 @@ export default class Access extends TemplateBase {
contractName: "PaymentConditions", contractName: "PaymentConditions",
methodName: "releasePayment", methodName: "releasePayment",
timeout: 10, timeout: 10,
parameters: [
{
name: "assetId",
type: "bytes32",
},
{
name: "price",
type: "uint256",
},
],
dependencies: ["grantAccess"], dependencies: ["grantAccess"],
dependencyTimeoutFlags: [0], dependencyTimeoutFlags: [0],
isTerminalCondition: true, isTerminalCondition: true,
@ -38,6 +68,16 @@ export default class Access extends TemplateBase {
contractName: "PaymentConditions", contractName: "PaymentConditions",
methodName: "refundPayment", methodName: "refundPayment",
timeout: 10, timeout: 10,
parameters: [
{
name: "assetId",
type: "bytes32",
},
{
name: "price",
type: "uint256",
},
],
dependencies: ["lockPayment", "grantAccess"], dependencies: ["lockPayment", "grantAccess"],
dependencyTimeoutFlags: [0, 1], dependencyTimeoutFlags: [0, 1],
isTerminalCondition: true, isTerminalCondition: true,

View File

@ -7,7 +7,6 @@ import EventHandlers from "../../src/ddo/EventHandlers"
import MetaData from "../../src/ddo/MetaData" import MetaData from "../../src/ddo/MetaData"
import Parameter from "../../src/ddo/Parameter" import Parameter from "../../src/ddo/Parameter"
import Service from "../../src/ddo/Service" import Service from "../../src/ddo/Service"
import InputType from "../../src/models/InputType"
import Account from "../../src/ocean/Account" import Account from "../../src/ocean/Account"
import IdGenerator from "../../src/ocean/IdGenerator" import IdGenerator from "../../src/ocean/IdGenerator"
import Ocean from "../../src/ocean/Ocean" import Ocean from "../../src/ocean/Ocean"
@ -15,6 +14,7 @@ import Condition from "../../src/ocean/ServiceAgreements/Condition"
import ServiceAgreement from "../../src/ocean/ServiceAgreements/ServiceAgreement" import ServiceAgreement from "../../src/ocean/ServiceAgreements/ServiceAgreement"
import ServiceAgreementTemplate from "../../src/ocean/ServiceAgreements/ServiceAgreementTemplate" import ServiceAgreementTemplate from "../../src/ocean/ServiceAgreements/ServiceAgreementTemplate"
import Access from "../../src/ocean/ServiceAgreements/Templates/Access" import Access from "../../src/ocean/ServiceAgreements/Templates/Access"
import Logger from "../../src/utils/Logger"
import WebServiceConnectorProvider from "../../src/utils/WebServiceConnectorProvider" import WebServiceConnectorProvider from "../../src/utils/WebServiceConnectorProvider"
import config from "../config" import config from "../config"
import TestContractHandler from "../keeper/TestContractHandler" import TestContractHandler from "../keeper/TestContractHandler"
@ -49,58 +49,60 @@ describe("ServiceAgreement", () => {
const conditions: Condition[] = await serviceAgreementTemplate.getConditions() const conditions: Condition[] = await serviceAgreementTemplate.getConditions()
// create ddo conditions out of the keys // create ddo conditions out of the keys
const ddoConditions: DDOCondition[] = conditions.map((condition, index): DDOCondition => { const ddoConditions: DDOCondition[] = conditions
.map((condition: Condition, index): DDOCondition => {
const events: Event[] = [ const events: Event[] = [
{ {
name: "PaymentReleased", name: "PaymentReleased",
actorType: [ actorType: [
"consumer", "consumer",
], ],
handlers: { handlers: {
moduleName: "serviceAgreement", moduleName: "serviceAgreement",
functionName: "fulfillAgreement", functionName: "fulfillAgreement",
version: "0.1", version: "0.1",
} as EventHandlers, } as EventHandlers,
} as Event, } as Event,
] ]
const mapParameterValueToName = (name) => { const mapParameterValueToName = (name) => {
switch (name) { switch (name) {
case "price": case "price":
return metadata.base.price return metadata.base.price
case "assetId": case "assetId":
return "0x" + assetId return "0x" + assetId
case "documentKeyId": case "documentKeyId":
return "0x1234" return "0x1234"
}
return null
} }
return null const parameters: Parameter[] = condition.parameters
} .map((parameter: Parameter) => {
return {
name: parameter.name,
type: parameter.type,
value: mapParameterValueToName(parameter.name),
} as Parameter
})
const parameters: Parameter[] = condition.methodReflection.inputs.map((input: InputType) => {
return { return {
name: input.name, contractName: condition.methodReflection.contractName,
type: input.type, methodName: condition.methodReflection.methodName,
value: mapParameterValueToName(input.name), timeout: condition.timeout,
} as Parameter index,
conditionKey: condition.condtionKey,
parameters,
events,
dependencies: condition.dependencies,
dependencyTimeoutFlags: condition.dependencyTimeoutFlags,
isTerminalCondition: condition.isTerminalCondition,
} as DDOCondition
}) })
return {
contractName: condition.methodReflection.contractName,
methodName: condition.methodReflection.methodName,
timeout: condition.timeout,
index,
conditionKey: condition.condtionKey,
parameters,
events,
dependencies: condition.dependencies,
dependencyTimeoutFlags: condition.dependencyTimeoutFlags,
isTerminalCondition: condition.isTerminalCondition,
} as DDOCondition
})
accessService = { accessService = {
type: "Access", type: "Access",
serviceDefinitionId: IdGenerator.generateId(), serviceDefinitionId: IdGenerator.generateId(),
@ -185,7 +187,7 @@ describe("ServiceAgreement", () => {
}) })
describe("#lockPayment()", () => { describe("#lockPayment()", () => {
xit("should lock the payment in that service agreement", async () => { it("should lock the payment in that service agreement", async () => {
const id: string = IdGenerator.generateId() const id: string = IdGenerator.generateId()
const did: string = `did:op:${id}` const did: string = `did:op:${id}`
@ -204,6 +206,11 @@ describe("ServiceAgreement", () => {
serviceAgreementId, serviceAgreementSignature, consumerAccount, publisherAccount) serviceAgreementId, serviceAgreementSignature, consumerAccount, publisherAccount)
assert(serviceAgreement) assert(serviceAgreement)
// get funds
await consumerAccount.requestTokens(metaDataService.metadata.base.price)
Logger.log(await consumerAccount.getBalance())
const paid: boolean = await serviceAgreement.lockPayment(assetId, metaDataService.metadata.base.price, const paid: boolean = await serviceAgreement.lockPayment(assetId, metaDataService.metadata.base.price,
consumerAccount) consumerAccount)
assert(paid) assert(paid)
@ -230,7 +237,11 @@ describe("ServiceAgreement", () => {
serviceAgreementId, serviceAgreementSignature, consumerAccount, publisherAccount) serviceAgreementId, serviceAgreementSignature, consumerAccount, publisherAccount)
assert(serviceAgreement) assert(serviceAgreement)
const paid: boolean = await serviceAgreement.lockPayment(assetId, 10, consumerAccount) // get funds
await consumerAccount.requestTokens(metaDataService.metadata.base.price)
const paid: boolean = await serviceAgreement.lockPayment(assetId, metaDataService.metadata.base.price,
consumerAccount)
assert(paid) assert(paid)
const accessGranted: boolean = await serviceAgreement.grantAccess(assetId, IdGenerator.generateId()) const accessGranted: boolean = await serviceAgreement.grantAccess(assetId, IdGenerator.generateId())