diff --git a/README.md b/README.md index de3a127ed7..cd1e24ff39 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,83 @@ -OriginTrail Node -================ +![](https://i.imgur.com/Oosqpvy.jpg) + -[comment]: # (TODO: Insert badges for github builds) ![badge](https://img.shields.io/docker/automated/origintrail/ot-node) -__OriginTrail is an ecosystem dedicated to making global supply chains work together by enabling a universal, collaborative and trusted data exchange.__ - + +OriginTrail technology is a set of tools and protocols evolving as the [semantic](https://www.w3.org/standards/semanticweb/) layer for Web3, built on the OriginTrail Decentralized Knowledge Graph (DKG). Its function is to empower developers and system integrators utilizing decentralized knowledge exchange supported by emerging standards and DLT networks. + This repository contains a work-in-progress code for a network node. -__OriginTrail Decentralized Network (ODN)__ is currently running in the __OriginTrail v5 Mainnet__ stage. - For further information about the roadmap please see our [website](https://tech.origintrail.io/roadmap). +OriginTrail Decentralized Network (ODN) is currently running in the OriginTrail v5 Mainnet stage. For further information about the roadmap please see our [website](https://tech.origintrail.io/roadmap). +Please see our main documentation page for more information. -[Please see our main documentation page for more information](http://docs.origintrail.io) -Installation -============= +## Installation Detailed instructions for installation and configuration of OriginTrail Node: - - * [API and technical documentation](http://docs.origintrail.io) - * [Node setup](http://tech.origintrail.io/node-setup) - - -What is OriginTrail -============= -OriginTrail is a purpose-built, open protocol for cross-organizational data sharing in supply chains, supported by blockchain. +* [API and technical documentation](https://docs.origintrail.io/) +* [Node setup](https://tech.origintrail.io/node-setup) + + + +## What is OriginTrail? + +A decentralized knowledge graph (DKG) is a global shared knowledge graph that is designed to benefit organizations and individuals by providing shared public infrastructure for knowledge exchange. -The key issues OriginTrail tackles are: +The OriginTrail DKG: +* removes central authorities - is hosted on the OriginTrail Decentralized Network (ODN) +* utilizes DIDs & Verifiable Credentials for identity and assertions management +* enables Dapps with search, integration, analytics, AI and ML capabilities for any data source: blockchains, IPFS, enterprise systems, web services, personal devices +* enables permissionless PUBLISH and QUERY operations - * Fragmented and siloed data across supply chains - * Low data interoperability - * Preventing vendor lock-in - * Ensuring the integrity of exchanged data +The OriginTrail Decentralized Network is an implementation of the OriginTrail DKG. With the ODN therefore you can query for data across a multitude of systems (discovery), to exchange it via several data exchange protocols and integrate it in your own local knowledge graph or data store. +For detailed information and up to date documentation visit [docs.origintrail.io](https://docs.origintrail.io/) -The OriginTrail Ecosystem is built on 3 main pillars: +## The OriginTrail Ecosystem is built on 3 main pillars - ### Neutrality + +### Neutrality Being an open-source, decentralized system, based on open global standards, neutrality is crucial for the OriginTrail ecosystem as it prevents vendor lock-ins, ensures integrity, and effectively breaks data silos. Neutrality means adopting co-creation principles, working with other blockchain ecosystems and solutions builders even as they may be competing in the same market on the application level. - ### Usability - +### Usability + Both blockchain environments, as well as OriginTrail, are fundamental technologies. In order to ensure the onboarding of enterprises, there needs to be a great focus on enhancing the user experience, as solutions need to meet the expectations of rapid value generation. - ### Inclusiveness - +### Inclusiveness + Continuing to form partnerships with technological and business global leaders that can employ the OriginTrail ecosystem for their communities. Catering to the needs of leading global communities requires us to be making strides in designing technical infrastructure and business models that support the adoption of the OriginTrail in diverse business communities. +For detailed information and up to date documentation visit [docs.origintrail.io](https://docs.origintrail.io/) -OriginTrail Decentralized Network Overview -============= -OriginTrail protocol is utilized within the permissionless OriginTrail Decentralized Network (ODN). The ODN as a network holds a growing Decentralized Knowledge Graph (DKG) with the following characteristics: - * Linked data first structure - the graph, enabling connections between data points from all published datasets on the network, conformant with Semantic Web technologies such as RDF and JSON-LD - * Schema flexibility - enabling the mapping of virtually any data model, preferably structured according to relevant standards (such as GS1 EPCIS and CBV) and recommendations (W3C Web of Things, Verifiable Credentials, PROV, etc.) for machine readability - * Identity verification - enabling the utilization of novel identity frameworks such as Self-sovereign identity, in conjunction with industry-specific identity frameworks (such as GS1 GTIN, GIAI, GRAI and other identification schemes) - * Efficient cryptographic integrity verification of subgraphs, using associated dataset graph fingerprints, computed as Merkle roots of the input datasets - * Cryptographic connection entanglement - allowing linking of data points only when specific cryptographic rules are satisfied - * Trust minimization through decentralization - utilizing a decentralized p2p overlay network for data exchange and the Ethereum blockchain in the consensus layer - - -Therefore the key development principles of OriginTrail ecosystem are: +![](https://i.imgur.com/GoXHOfp.jpg) + +The ODN as a network holds a growing Decentralized Knowledge Graph (DKG) with the following characteristics: +* Linked data first structure - the graph, enabling connections between data points from all published datasets on the network, conformant with Semantic Web technologies such as RDF and JSON-LD +* Schema flexibility - enabling the mapping of virtually any data model, preferably structured according to relevant standards (such as GS1 EPCIS and CBV) and recommendations (W3C Web of Things, Verifiable Credentials, PROV, etc.) for machine readability +* Identity verification - enabling the utilization of novel identity frameworks such as Self-sovereign identity, in conjunction with industry-specific identity frameworks (such as GS1 GTIN, GIAI, GRAI and other identification schemes) +* Efficient cryptographic integrity verification of subgraphs, using associated dataset graph fingerprints, computed as Merkle roots of the input datasets +* Cryptographic connection entanglement - allowing linking of data points only when specific cryptographic rules are satisfied +* Trust minimization through decentralization - utilizing a decentralized p2p overlay network for data exchange and the Ethereum blockchain in the consensus layer - * Connection-first approach - providing ways to connect the world's data into a global, decentralized knowledge graph - * Technological neutrality - avoiding technological lock-ins and striving towards agnosticism where possible - * Decentralization - designing, implementing and utilizing that are not based on trusted-third parties or centralized entities - * Privacy-by-Design approach - according to the [7 Foundational Principles of Privacy by Design](https://www.ipc.on.ca/wp-content/uploads/Resources/7foundationalprinciples.pdf) - * Development transparency - towards the OriginTrail Ecosystem community of developers, node holders and businesses - * Open Source Development - according to [Open Source Software](https://en.wikipedia.org/wiki/Open-source_model) principles - - -Contribution -============ +Therefore the key development principles of OriginTrail ecosystem are: +* Connection-first approach - providing ways to connect the world's data into a global, decentralized knowledge graph +* Technological neutrality - avoiding technological lock-ins and striving towards agnosticism where possible +* Decentralization - designing, implementing and utilizing that are not based on trusted-third parties or centralized entities +* Privacy-by-Design approach - according to the [7 Foundational Principles of Privacy by Design](https://www.ipc.on.ca/wp-content/uploads/Resources/7foundationalprinciples.pdf) +* Development transparency - towards the OriginTrail Ecosystem community of developers, node holders and businesses +* Open Source Development - according to [Open Source Software principles](https://en.wikipedia.org/wiki/Open_source) -OriginTrail is an open source project. We happily invite you to join us in our mission of building decentralised world of supply chain. If you would like to contribute, you are more than welcome. +For detailed information and up to date documentation visit [docs.origintrail.io](https://docs.origintrail.io/) +## Contribution +OriginTrail is an open source project. We happily invite you to join us in our mission of building decentralised world of supply chain. If you would like to contribute, you are more than welcome. -### Useful links +## Useful links [OriginTrail website](https://origintrail.io) [OriginTrail documentation page](http://docs.origintrail.io) @@ -90,3 +88,4 @@ OriginTrail is an open source project. We happily invite you to join us in our m [OriginTrail Twitter](https://twitter.com/origin_trail) +[OriginTrail Developers Twitter](https://twitter.com/OriginTrailDev) diff --git a/config/config.json b/config/config.json index bb9dcf22df..d4bb846d31 100644 --- a/config/config.json +++ b/config/config.json @@ -509,7 +509,7 @@ "blockchain_title": "Polygon", "network_id": "polygon:mainnet", "chain_id": 137, - "hub_contract_address": "0x86dB1592CD083dD7c758196dB55f317fed6A0a22", + "hub_contract_address": "0xe5FC9F71F8e378448c0BD0Fb8E1fb879654E3fbb", "identity_filepath": "polygon_erc725_identity.json", "gas_limit": "2000000", "gas_price": "1000000000", diff --git a/modules/Blockchain/Polygon/abi/token.json b/modules/Blockchain/Polygon/abi/token.json index ce5abdf0c5..14bc13f45b 100644 --- a/modules/Blockchain/Polygon/abi/token.json +++ b/modules/Blockchain/Polygon/abi/token.json @@ -1,680 +1,288 @@ [ { - "constant": true, - "inputs": [], - "name": "mintingFinished", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x05d2035b" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "preicoAndAdvisorsAmounts", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x0688ec24" - }, - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x06fdde03" - }, - { - "constant": false, + "anonymous": false, "inputs": [ { - "name": "_spender", + "indexed": true, + "internalType": "address", + "name": "owner", "type": "address" }, { - "name": "_value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function", - "signature": "0x095ea7b3" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, { - "name": "", + "indexed": false, + "internalType": "uint256", + "name": "value", "type": "uint256" } ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x18160ddd" - }, - { - "constant": true, - "inputs": [], - "name": "decimals", - "outputs": [ - { - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x313ce567" - }, - { - "constant": true, - "inputs": [], - "name": "wallet", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x521eb273" + "name": "Approval", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { - "name": "_spender", + "indexed": true, + "internalType": "address", + "name": "from", "type": "address" }, { - "name": "_subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseApproval", - "outputs": [ - { - "name": "success", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function", - "signature": "0x66188463" - }, - { - "constant": true, - "inputs": [], - "name": "liquidityPool", - "outputs": [ + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, { - "name": "", + "indexed": false, + "internalType": "uint256", + "name": "value", "type": "uint256" } ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x665a11ca" + "name": "Transfer", + "type": "event" }, { - "constant": true, "inputs": [ { - "name": "_owner", + "internalType": "address", + "name": "spender", "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "balance", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x70a08231" - }, - { - "constant": true, - "inputs": [], - "name": "startTime", - "outputs": [ + }, { - "name": "", + "internalType": "uint256", + "name": "amount", "type": "uint256" } ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x78e97925" - }, - { - "constant": false, - "inputs": [], - "name": "finishMinting", + "name": "approve", "outputs": [ { + "internalType": "bool", "name": "", "type": "bool" } ], - "payable": false, "stateMutability": "nonpayable", - "type": "function", - "signature": "0x7d64bcb4" - }, - { - "constant": true, - "inputs": [], - "name": "preicoAndAdvisors", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x8883478e" + "type": "function" }, { - "constant": true, - "inputs": [], - "name": "teamAndFoundersWallet", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x8b8ecffa" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x8da5cb5b" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0x95d89b41" - }, - { - "constant": true, - "inputs": [], - "name": "bountyReward", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0xa10f43a3" - }, - { - "constant": true, - "inputs": [], - "name": "futureDevelopment", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0xa2948cdf" - }, - { - "constant": true, - "inputs": [], - "name": "advisorsAndPreICO", - "outputs": [ + "inputs": [ { - "name": "", + "internalType": "address", + "name": "spender", "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0xc2572c51" - }, - { - "constant": true, - "inputs": [], - "name": "teamAndFounders", - "outputs": [ + }, { - "name": "", + "internalType": "uint256", + "name": "subtractedValue", "type": "uint256" } ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0xc519099d" - }, - { - "constant": true, - "inputs": [], - "name": "TOTAL_NUM_TOKENS", + "name": "decreaseAllowance", "outputs": [ { + "internalType": "bool", "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0xc8e7e5ef" - }, - { - "constant": true, - "inputs": [], - "name": "CORRECTION", - "outputs": [ - { - "name": "", - "type": "uint256" + "type": "bool" } ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0xce5e9ffb" + "stateMutability": "nonpayable", + "type": "function" }, { - "constant": false, "inputs": [ { - "name": "_spender", + "internalType": "address", + "name": "spender", "type": "address" }, { - "name": "_addedValue", + "internalType": "uint256", + "name": "addedValue", "type": "uint256" } ], - "name": "increaseApproval", + "name": "increaseAllowance", "outputs": [ { - "name": "success", + "internalType": "bool", + "name": "", "type": "bool" } ], - "payable": false, "stateMutability": "nonpayable", - "type": "function", - "signature": "0xd73dd623" + "type": "function" }, { - "constant": true, "inputs": [ { - "name": "_owner", + "internalType": "address", + "name": "recipient", "type": "address" }, { - "name": "_spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "name": "remaining", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0xdd62ed3e" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function", - "signature": "0xf2fde38b" - }, - { - "constant": true, - "inputs": [ - { - "name": "", + "internalType": "uint256", + "name": "amount", "type": "uint256" } ], - "name": "founderAmounts", + "name": "transfer", "outputs": [ { + "internalType": "bool", "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function", - "signature": "0xfff83edf" - }, - { - "inputs": [ - { - "name": "_wallet", - "type": "address" - }, - { - "name": "_teamAndFoundersWallet", - "type": "address" - }, - { - "name": "_advisorsAndPreICO", - "type": "address" + "type": "bool" } ], - "payable": false, "stateMutability": "nonpayable", - "type": "constructor", - "signature": "constructor" + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "name": "from", + "internalType": "address", + "name": "sender", "type": "address" }, { - "indexed": true, - "name": "to", + "internalType": "address", + "name": "recipient", "type": "address" }, { - "indexed": false, - "name": "value", + "internalType": "uint256", + "name": "amount", "type": "uint256" } ], - "name": "Transfer", - "type": "event", - "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" - }, - { - "anonymous": false, - "inputs": [ + "name": "transferFrom", + "outputs": [ { - "indexed": false, - "name": "transferIsAllowed", + "internalType": "bool", + "name": "", "type": "bool" } ], - "name": "TransferAllowed", - "type": "event", - "signature": "0x09453fb3c77c88037c1b664345201b4e2c2e71c35ef789fb3f61972c140e0ac5" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "amount", - "type": "uint256" - } - ], - "name": "Mint", - "type": "event", - "signature": "0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885" - }, - { - "anonymous": false, - "inputs": [], - "name": "MintFinished", - "type": "event", - "signature": "0xae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa08" + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "name": "previousOwner", - "type": "address" + "internalType": "string", + "name": "name", + "type": "string" }, { - "indexed": true, - "name": "newOwner", - "type": "address" + "internalType": "string", + "name": "symbol", + "type": "string" } ], - "name": "OwnershipTransferred", - "type": "event", - "signature": "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0" + "stateMutability": "nonpayable", + "type": "constructor" }, { - "anonymous": false, "inputs": [ { - "indexed": true, + "internalType": "address", "name": "owner", "type": "address" }, { - "indexed": true, + "internalType": "address", "name": "spender", "type": "address" - }, + } + ], + "name": "allowance", + "outputs": [ { - "indexed": false, - "name": "value", + "internalType": "uint256", + "name": "", "type": "uint256" } ], - "name": "Approval", - "type": "event", - "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + "stateMutability": "view", + "type": "function" }, { - "constant": false, "inputs": [ { - "name": "from", - "type": "address" - }, - { - "name": "to", + "internalType": "address", + "name": "account", "type": "address" - }, - { - "name": "value", - "type": "uint256" } ], - "name": "transferFrom", + "name": "balanceOf", "outputs": [ { + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function", - "signature": "0x23b872dd" + "stateMutability": "view", + "type": "function" }, { - "constant": false, - "inputs": [ - { - "name": "to", - "type": "address" - }, - { - "name": "value", - "type": "uint256" - } - ], - "name": "transfer", + "inputs": [], + "name": "decimals", "outputs": [ { + "internalType": "uint8", "name": "", - "type": "bool" + "type": "uint8" } ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function", - "signature": "0xa9059cbb" + "stateMutability": "view", + "type": "function" }, { - "constant": false, - "inputs": [ - { - "name": "contributor", - "type": "address" - }, - { - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", + "inputs": [], + "name": "name", "outputs": [ { + "internalType": "string", "name": "", - "type": "bool" + "type": "string" } ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function", - "signature": "0x40c10f19" + "stateMutability": "view", + "type": "function" }, { - "constant": false, - "inputs": [ - { - "name": "contributors", - "type": "address[]" - }, - { - "name": "amounts", - "type": "uint256[]" - } - ], - "name": "mintMany", + "inputs": [], + "name": "symbol", "outputs": [ { + "internalType": "string", "name": "", - "type": "bool" + "type": "string" } ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function", - "signature": "0x4029a3ce" + "stateMutability": "view", + "type": "function" }, { - "constant": false, "inputs": [], - "name": "endMinting", + "name": "totalSupply", "outputs": [ { + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function", - "signature": "0xef70aebf" + "stateMutability": "view", + "type": "function" } -] \ No newline at end of file +] diff --git a/modules/Blockchain/Polygon/index.js b/modules/Blockchain/Polygon/index.js index d1bd5da3d6..94c8ddadaf 100644 --- a/modules/Blockchain/Polygon/index.js +++ b/modules/Blockchain/Polygon/index.js @@ -89,6 +89,22 @@ class Polygon extends Web3Implementation { this.config.gas_price = gasPrice; this.config.gas_price_last_update_timestamp = new Date().getTime(); } + + /** + * Increase token approval for profile + * @param {number} tokenAmountIncrease + * @returns {Promise} + */ + async increaseProfileApproval(tokenAmountIncrease) { + const gasPrice = await this.getGasPrice(); + const options = { + gasLimit: this.web3.utils.toHex(this.config.gas_limit), + gasPrice: this.web3.utils.toHex(gasPrice), + to: this.tokenContractAddress, + }; + this.logger.trace(`[${this.getBlockchainId()}] increaseProfileApproval(amount=${tokenAmountIncrease})`); + return this.transactions.queueTransaction(this.tokenContractAbi, 'increaseAllowance', [this.profileContractAddress, tokenAmountIncrease], options); + } } module.exports = Polygon; diff --git a/modules/Blockchain/Polygon/migrations/2_total_migration.js b/modules/Blockchain/Polygon/migrations/2_total_migration.js index 198d6e99c6..8bfc195c37 100644 --- a/modules/Blockchain/Polygon/migrations/2_total_migration.js +++ b/modules/Blockchain/Polygon/migrations/2_total_migration.js @@ -162,6 +162,83 @@ module.exports = async (deployer, network, accounts) => { console.log('Updated contract in Hub contract map!'); } break; + // eslint-disable-next-line no-case-declarations + case 'mainnet': + const tokenContractAddress = '0xa7b98d63a137bf402b4570799ac4cad0bb1c4b1c'; + await deployer.deploy(Hub, { gas: 6000000, from: accounts[0] }) + .then((result) => { + hub = result; + }); + + await hub.setContractAddress('Owner', accounts[0]); + + profileStorage = await deployer.deploy( + ProfileStorage, + hub.address, { gas: 6000000, from: accounts[0] }, + ); + await hub.setContractAddress('ProfileStorage', profileStorage.address); + + holdingStorage = await deployer.deploy( + HoldingStorage, + hub.address, + { gas: 6000000, from: accounts[0] }, + ); + await hub.setContractAddress('HoldingStorage', holdingStorage.address); + + litigationStorage = await deployer.deploy( + LitigationStorage, + hub.address, + { gas: 6000000, from: accounts[0] }, + ); + await hub.setContractAddress('LitigationStorage', litigationStorage.address); + + approval = await deployer.deploy(Approval); + await hub.setContractAddress('Approval', approval.address); + + await hub.setContractAddress('Token', tokenContractAddress); + + profile = await deployer.deploy(Profile, hub.address, { gas: 9000000, from: accounts[0] }); + await hub.setContractAddress('Profile', profile.address); + + holding = await deployer.deploy(Holding, hub.address, { gas: 8000000, from: accounts[0] }); + await hub.setContractAddress('Holding', holding.address); + + creditorHandler = await deployer.deploy( + CreditorHandler, + hub.address, + { gas: 7000000, from: accounts[0] }, + ); + await hub.setContractAddress('CreditorHandler', creditorHandler.address); + + litigation = await deployer.deploy( + Litigation, + hub.address, + { gas: 6000000, from: accounts[0] }, + ); + await hub.setContractAddress('Litigation', litigation.address); + + replacement = await deployer.deploy( + Replacement, + hub.address, + { gas: 7000000, from: accounts[0] }, + ); + await hub.setContractAddress('Replacement', replacement.address); + + + console.log('\n\n \t Contract adressess on polygon mainnet:'); + console.log(`\t Hub contract address: \t\t\t${hub.address}`); + console.log(`\t Approval contract address: \t\t${approval.address}`); + console.log(`\t Token contract address: \t\t${tokenContractAddress}`); + console.log(`\t Profile contract address: \t\t${profile.address}`); + console.log(`\t Holding contract address: \t\t${holding.address}`); + console.log(`\t Litigation contract address: \t\t${litigation.address}`); + console.log(`\t Replacement contract address: \t\t${replacement.address}`); + + console.log(`\t ProfileStorage contract address: \t${profileStorage.address}`); + console.log(`\t HoldingStorage contract address: \t${holdingStorage.address}`); + console.log(`\t LitigationStorage contract address: \t${litigationStorage.address}`); + + break; default: console.warn('Please use one of the following network identifiers: ganache, mock, test, or rinkeby'); break; diff --git a/modules/Blockchain/Polygon/truffle.js b/modules/Blockchain/Polygon/truffle.js index 118589a1e9..b047ca4cc1 100644 --- a/modules/Blockchain/Polygon/truffle.js +++ b/modules/Blockchain/Polygon/truffle.js @@ -38,5 +38,12 @@ module.exports = { websockets: true, skipDryRun: true, }, + mainnet: { + provider: () => new HDWalletProvider(private_key, rpc_endpoint), + network_id: 137, + gas: 6500000, // Gas limit used for deploys + gasPrice: 40000000000, + skipDryRun: true, + }, }, }; diff --git a/modules/Utilities.js b/modules/Utilities.js index c9fb7f8e66..c1ef8a535b 100644 --- a/modules/Utilities.js +++ b/modules/Utilities.js @@ -21,6 +21,8 @@ const DataIntegrityResolver = require('./service/data-integrity/data-integrity-r const logger = require('./logger'); const { sha3_256 } = require('js-sha3'); +const constants = require('./constants'); + class Utilities { /** @@ -417,22 +419,27 @@ class Utilities { }); } - static getArangoDbVersion({ database }) { - return new Promise((resolve, reject) => { - request - .get(`http://${database.host}:${database.port}/_api/version`) - .auth(database.username, database.password) - .then((res) => { - if (res.status === 200) { - resolve(res.body); - } else { - // eslint-disable-next-line prefer-promise-reject-errors - reject('Failed to contact DB'); - } - }).catch((err) => { - reject(err); - }); - }); + static async getArangoDbVersion({ database }) { + let numberOfRetries = 0; + while (numberOfRetries < constants.GET_ARANGO_DB_STATUS_MAX_RETRY) { + if (numberOfRetries > 0) { + // eslint-disable-next-line no-await-in-loop + await this.sleepForMilliseconds(constants.ARANGO_DB_STATUS_TIMEOUT_IN_MILISECONDS); + } + try { + // eslint-disable-next-line no-await-in-loop + const response = await request.get(`http://${database.host}:${database.port}/_api/version`) + .auth(database.username, database.password); + if (response && response.status === 200) { + return response.body; + } + logger.debug(`Unable to fetch ArangoDB status, try number: ${numberOfRetries + 1}/${constants.GET_ARANGO_DB_STATUS_MAX_RETRY}`); + } catch (error) { + logger.debug(`Error while trying to fetch ArangoDB status, try number: ${numberOfRetries + 1}/${constants.GET_ARANGO_DB_STATUS_MAX_RETRY}. Error: ${error.message}`); + } + numberOfRetries += 1; + } + throw Error('Unable to fetch ArangoDB status'); } /** diff --git a/modules/command/dh/dh-offer-handle-command.js b/modules/command/dh/dh-offer-handle-command.js index 49d969c9b1..451169a9b9 100644 --- a/modules/command/dh/dh-offer-handle-command.js +++ b/modules/command/dh/dh-offer-handle-command.js @@ -30,7 +30,16 @@ class DHOfferHandleCommand extends Command { } = command.data; const { node_wallet } = this.blockchain.getWallet(blockchain_id).response; - + const bid = await Models.bids.findOne({ + where: { + offer_id: offerId, + blockchain_id, + }, + }); + if (bid && (bid.status === 'FAILED' || bid.status === 'SENT')) { + this.logger.trace(`Replication request for offer ${offerId} already sent to node ${dcNodeId}.`); + return Command.empty(); + } this.logger.trace(`Sending replication request for offer ${offerId} to node ${dcNodeId}.`); const response = await this.transport.replicationRequest({ offerId, @@ -40,13 +49,6 @@ class DHOfferHandleCommand extends Command { async_enabled: true, }, dcNodeId); - const bid = await Models.bids.findOne({ - where: { - offer_id: offerId, - blockchain_id, - }, - }); - if (response.status === 'fail') { bid.status = 'FAILED'; let message = `Failed to receive replication from ${dcNodeId} for offer ${offerId} on chain ${blockchain_id}.`; diff --git a/modules/command/dh/dh-pay-out-command.js b/modules/command/dh/dh-pay-out-command.js index bf3d15ae18..7425c95fcc 100644 --- a/modules/command/dh/dh-pay-out-command.js +++ b/modules/command/dh/dh-pay-out-command.js @@ -1,12 +1,9 @@ const Command = require('../command'); -const Utilities = require('../../Utilities'); const constants = require('../../constants'); const Blockchain = require('../../Blockchain'); const Models = require('../../../models/index'); -const DELAY_ON_FAIL_IN_MILLS = 5 * 60 * 1000; - /** * Starts token withdrawal operation */ @@ -34,6 +31,10 @@ class DhPayOutCommand extends Command { blockchain_id, } = command.data; + if (!command.data.retryNumber) { + command.data.retryNumber = 1; + } + const bid = await Models.bids.findOne({ where: { offer_id: offerId, @@ -67,6 +68,7 @@ class DhPayOutCommand extends Command { const { status, timestamp } = await this.blockchain .getLitigation(offerId, blockchainIdentity, blockchain_id).response; + const { litigation_interval_in_minutes } = await Models.bids.findOne({ where: { offer_id: offerId, @@ -90,24 +92,12 @@ class DhPayOutCommand extends Command { await this._clearReplicationDatabaseData(offerId); await this._printBalances(blockchainIdentity, blockchain_id); } catch (error) { + let delay = constants.PAYOUT_COMMAND_RETRY_DELAY_IN_MILISECONDS; if (error.message.includes('Gas price higher than maximum allowed price')) { - this.logger.info('Gas price too high, delaying call for 30 minutes'); - return { - commands: [ - { - name: 'dhPayOutCommand', - delay: constants.GAS_PRICE_VALIDITY_TIME_IN_MILLS, - retries: 3, - transactional: false, - data: { - offerId, - viaAPI: false, - }, - }, - ], - }; + this.logger.info(`Gas price too high, delaying call for ${constants.GAS_PRICE_VALIDITY_TIME_IN_MILLS / 60000} minutes`); + delay = constants.GAS_PRICE_VALIDITY_TIME_IN_MILLS; } - throw error; + return this.rescheduleFailedPayout(command, delay); } } @@ -120,19 +110,26 @@ class DhPayOutCommand extends Command { * @param err */ async recover(command, err) { + return this + .rescheduleFailedPayout(command, constants.PAYOUT_COMMAND_RETRY_DELAY_IN_MILISECONDS); + } + + rescheduleFailedPayout(command, delay) { const { offerId, viaAPI, + retryNumber, } = command.data; - if (!viaAPI) { - this.logger.warn(`Rescheduling failed payout for offer ${offerId}. Schedule delay ${DELAY_ON_FAIL_IN_MILLS} milliseconds`); + if (!viaAPI && retryNumber < constants.MAX_NUMBER_OF_RETRIES_FOR_PAYOUT) { + this.logger.warn(`Rescheduling failed payout for offer ${offerId}. Attempt ${retryNumber}/${constants.MAX_NUMBER_OF_RETRIES_FOR_PAYOUT}. Schedule delay ${delay / 60000} minutes`); + command.data.retryNumber += 1; return { commands: [ { name: 'dhPayOutCommand', data: command.data, - delay: DELAY_ON_FAIL_IN_MILLS, + delay, }, ], }; @@ -193,7 +190,7 @@ class DhPayOutCommand extends Command { const command = { name: 'dhPayOutCommand', delay: 0, - period: constants.GAS_PRICE_VALIDITY_TIME_IN_MILLS, + period: constants.PAYOUT_COMMAND_RETRY_DELAY_IN_MILISECONDS, transactional: false, }; Object.assign(command, map); diff --git a/modules/constants.js b/modules/constants.js index 4ad463e10a..5937020b16 100644 --- a/modules/constants.js +++ b/modules/constants.js @@ -239,3 +239,32 @@ exports.TRAIL_CACHE_DIRECTORY = 'trail_cache'; * Number of datasets to be pruned in one batch */ exports.LOW_ESTIMATED_VALUE_DATASETS_PRUNING_BATCH_NUMBER = 100; + +/** + * + * @constant {number} MAX_NUMBER_OF_RETRIES_FOR_PAYOUT - + * Maximum number of retries for payout command + */ +exports.MAX_NUMBER_OF_RETRIES_FOR_PAYOUT = 5; + +/** + * + * @constant {number} PAYOUT_COMMAND_RETRY_DELAY_IN_MILISECONDS - + * Retry delay for payout command in miliseconds + */ +exports.PAYOUT_COMMAND_RETRY_DELAY_IN_MILISECONDS = 30 * 60 * 1000; + +/** + * + * @constant {number} GET_ARANGO_DB_STATUS_MAX_RETRY - + * Maximum number of times that arango status call should be called + */ +exports.GET_ARANGO_DB_STATUS_MAX_RETRY = 5; + +/** + * + * @constant {number} ARANGO_DB_STATUS_TIMEOUT_IN_MILISECONDS - + * Delay between two Arango db status checks + */ +exports.ARANGO_DB_STATUS_TIMEOUT_IN_MILISECONDS = 5000; + diff --git a/modules/controller/dc-controller.js b/modules/controller/dc-controller.js index 7129892b45..4413729f39 100644 --- a/modules/controller/dc-controller.js +++ b/modules/controller/dc-controller.js @@ -591,36 +591,35 @@ class DCController { const result = await this.graphStorage.findLocalQuery({ identifierKeys: keys, }); - const response = this.importService.packLocalQueryData(result); - for (let i = 0; i < response.length; i += 1) { - let offer_id = null; - - // eslint-disable-next-line no-await-in-loop - const offer = await Models.offers.findOne({ - where: { data_set_id: response[i].datasets[0], status: { [Models.Sequelize.Op.not]: 'FAILED' } }, - }); - - if (offer) { - // eslint-disable-next-line prefer-destructuring - offer_id = offer.offer_id; - } else { + const responses = this.importService.packLocalQueryData(result); + const datasetInfos = {}; + const replicationInfos = {}; + for (let i = 0; i < responses.length; i += 1) { + const response = responses[i]; + const datasetId = response.datasets[0]; + + if (!datasetInfos[datasetId]) { // eslint-disable-next-line no-await-in-loop - const bid = await Models.bids.findOne({ - where: { data_set_id: response[i].datasets[0], status: { [Models.Sequelize.Op.not]: 'FAILED' } }, + datasetInfos[datasetId] = await Models.data_info.findOne({ + where: { data_set_id: datasetId }, }); + } + const datasetInfo = datasetInfos[datasetId]; - // eslint-disable-next-line prefer-destructuring - if (bid) { offer_id = bid.offer_id; } + if (!replicationInfos[datasetId]) { + // eslint-disable-next-line no-await-in-loop + replicationInfos[datasetId] = await ImportUtilities + .getReplicationInfo(datasetId, datasetInfo.origin); } + const replicationInfo = replicationInfos[datasetId]; - // eslint-disable-next-line prefer-destructuring - response[i].dataset_id = response[i].datasets[0]; - response[i].offer_id = offer_id; - delete response[i].datasets; + response.dataset_id = datasetId; + response.replication_info = replicationInfo; + delete response.datasets; } res.status(200); - res.send(response); + res.send(responses); } async getMerkleProofs(req, res) { diff --git a/modules/service/dataset-pruning-service.js b/modules/service/dataset-pruning-service.js index 0f8fda82b9..3fe118dfa8 100644 --- a/modules/service/dataset-pruning-service.js +++ b/modules/service/dataset-pruning-service.js @@ -234,12 +234,12 @@ class DatasetPruningService { } if (this.diskService.folderExists(defaultBackupFolderPath) - && this.diskService.getFolderSize(defaultBackupFolderPath) > 0) { + && this.diskService.getFolderSize(defaultBackupFolderPath) > 10) { this.logger.warn('Detected ot-node backup on machine. please remove backup data in order to enable low estimated value datasets pruning!'); return false; } - if (arangoDbEngineFolderSize > minimumArangoDbFolderSizeForPruning) { + if (arangoDbEngineFolderSize < minimumArangoDbFolderSizeForPruning) { this.logger.warn('Reached minimum Graph DB folder size, low estimated value datasets wont be pruned. ' + `Minimum size of Graph DB is 20% of total disk size. Current Graph DB folder size is: ${arangoDbEngineFolderSize}kb`); return false; diff --git a/modules/service/high-availability-service.js b/modules/service/high-availability-service.js index 6e29a8d361..fc142a93e9 100644 --- a/modules/service/high-availability-service.js +++ b/modules/service/high-availability-service.js @@ -297,11 +297,23 @@ class HighAvailabilityService { this.logger.trace('Starting postgres replication'); execSync('/etc/init.d/postgresql stop'); if (fs.existsSync('/var/lib/postgresql/12/main')) { + if (fs.existsSync('/ot-node/data/tmp-postgres-backup')) { + execSync('rm -r /ot-node/data/tmp-postgres-backup'); + } + execSync('mkdir /ot-node/data/tmp-postgres-backup'); + execSync('cp -r /var/lib/postgresql/12/main/* /ot-node/data/tmp-postgres-backup'); + execSync('rm -rfv /var/lib/postgresql/12/main/*'); + } + try { + execSync(`su -c "pg_basebackup -h ${remoteHostname} -U ${remoteOpDbUsername} -p 5432 -D /var/lib/postgresql/12/main/ -Fp -Xs -P -R" - postgres`); + execSync('/etc/init.d/postgresql start'); + } catch (error) { execSync('rm -rfv /var/lib/postgresql/12/main/*'); + execSync('cp -r /ot-node/data/tmp-postgres-backup/* /var/lib/postgresql/12/main/'); + throw error; } - execSync(`su -c "pg_basebackup -h ${remoteHostname} -U ${remoteOpDbUsername} -p 5432 -D /var/lib/postgresql/12/main/ -Fp -Xs -P -R" - postgres`); - execSync('/etc/init.d/postgresql start'); this.logger.trace('Postgres replication started successfully'); + execSync('rm -r /ot-node/data/tmp-postgres-backup'); } stopPostgresReplication() { diff --git a/modules/service/import-service.js b/modules/service/import-service.js index df3ec02c1e..a3fc4601fd 100644 --- a/modules/service/import-service.js +++ b/modules/service/import-service.js @@ -637,19 +637,33 @@ class ImportService { packTrailData(data) { const reconstructedObjects = []; + const datasets = []; for (const object of data) { const { rootObject, relatedObjects } = object; + const dataVertices = relatedObjects.filter(x => x.vertex.vertexType === 'Data'); + let numberOfCopies = dataVertices.length; + if (!numberOfCopies) numberOfCopies = 1; + for (let i = 0; i < numberOfCopies; i += 1) { + if (dataVertices.length > 0) { + datasets.push(dataVertices[i].vertex.datasets); + } else { + datasets.push(rootObject.datasets); + } - reconstructedObjects.push(this._createObjectGraph(rootObject, relatedObjects)); + reconstructedObjects.push(this._createObjectGraph( + rootObject, + relatedObjects, + i, + )); + } } const otObjects = []; - for (let i = 0; i < reconstructedObjects.length; i += 1) { if (reconstructedObjects[i] && reconstructedObjects[i]['@id']) { otObjects.push({ otObject: reconstructedObjects[i], - datasets: data[i].rootObject.datasets, + datasets: datasets[i], }); } } @@ -681,8 +695,8 @@ class ImportService { return otObjects; } - _createObjectGraph(graphObject, relatedObjects) { - const otObject = this._constructOtObject(relatedObjects); + _createObjectGraph(graphObject, relatedObjects, copyNumber = 0) { + const otObject = this._constructOtObject(relatedObjects, copyNumber); otObject['@id'] = graphObject.uid; if (graphObject.vertexType === constants.vertexType.entityObject) { otObject['@type'] = constants.objectType.otObject; @@ -692,7 +706,8 @@ class ImportService { return otObject; } - _constructOtObject(relatedObjects) { + _constructOtObject(relatedObjects, copyNumber) { + let dataCounter = 0; const otObject = {}; otObject.identifiers = []; otObject.relations = []; @@ -717,7 +732,10 @@ class ImportService { // Check for properties. // Relation 'HAS_DATA' goes from entityVertex to dataVertex. if (relatedObject.edge.edgeType === constants.edgeType.dataRelation) { - otObject.properties = Utilities.copyObject(relatedObject.vertex.data); + if (dataCounter === copyNumber) { + otObject.properties = Utilities.copyObject(relatedObject.vertex.data); + } + dataCounter += 1; } diff --git a/modules/transpiler/epcis/epcis-otjson-transpiler.js b/modules/transpiler/epcis/epcis-otjson-transpiler.js index 24844c4bb6..f951af5671 100644 --- a/modules/transpiler/epcis/epcis-otjson-transpiler.js +++ b/modules/transpiler/epcis/epcis-otjson-transpiler.js @@ -1071,6 +1071,23 @@ class EpcisOtJsonTranspiler { } break; // eslint-disable-next-line + case 'giai': + // eslint-disable-next-line + itemReference = splitted[3]; + const serialGiai = splitted[4]; + checkDigit = this._checkDigitGS1(`${companyPrefix.substr(1)}${itemReference}`); + + identifiers = { + giai: identifier, + companyPrefix: companyPrefix.substr(1), + itemReference, + }; + + if (serialGiai) { + identifiers.serial = serialGiai; + } + break; + // eslint-disable-next-line case 'sscc': // eslint-disable-next-line const serialReference = splitted[3]; diff --git a/origintrail_noderc.image b/origintrail_noderc.image index 3b28cd18d4..2b0050c307 100644 --- a/origintrail_noderc.image +++ b/origintrail_noderc.image @@ -5,7 +5,7 @@ "implementations": [ { "blockchain_title": "Ethereum", - "network_id": "development", + "network_id": "stargazer", "hub_contract_address":"0x0987197628Bb06133B6FA2409eb4cF9FCaFe8d3a", "rpc_server_url":"http://localhost:7545/", "identity_filepath": "erc725_identity.json", @@ -48,4 +48,4 @@ "autoUpdater":{ "enabled":false } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 94771d3882..ef6137c8bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "origintrail_node", - "version": "5.1.1", + "version": "5.1.2", "description": "OriginTrail node", "main": ".eslintrc.js", "config": { diff --git a/scripts/backup.js b/scripts/backup.js index 398e394d9e..ac3a389aa9 100644 --- a/scripts/backup.js +++ b/scripts/backup.js @@ -12,6 +12,9 @@ const Utilities = require('../modules/Utilities'); const pjson = require('../package.json'); const defaultConfigFile = require('../config/config.json'); +const operationalDbFileName = 'system.db'; +const operationDbBackupMaxNumberOfRetries = 10; +const operationDbTimeoutInMilliseconds = 2000; // Get the environment name let environment; if (!process.env.NODE_ENV) { @@ -92,7 +95,7 @@ function getCertificateFileNames() { } function getDataFileNames() { - return ['kademlia.crt', 'kademlia.key', 'houston.txt', 'system.db']; + return ['kademlia.crt', 'kademlia.key', 'houston.txt']; } function getMigrationFileNames() { @@ -142,7 +145,38 @@ function createBackupFolder() { return path.join(argv.backup_directory, timestamp); } -function main() { +async function backupOperationalDb(backupDir) { + let runInLoop = true; + let numberOfRetries = 0; + while (runInLoop) { + if (numberOfRetries !== 0) { + // eslint-disable-next-line no-await-in-loop + await Utilities.sleepForMilliseconds(operationDbTimeoutInMilliseconds); + } + const result = moveFileFromNodeToBackup( + operationalDbFileName, + config.appDataPath, + backupDir, + ); + numberOfRetries += 1; + if (result) { + try { + const destination = path.join(backupDir, operationalDbFileName); + console.log('Performing integrity check for operational db copy, this check might take a while.'); + execSync(`sqlite3 ${destination} "pragma integrity_check;" ".exit"`); + console.log('Integrity check for operational db copy passed.'); + runInLoop = false; + } catch (error) { + console.log(`Integrity check for backed up operational db copy failed. Retry number ${numberOfRetries}/${operationDbBackupMaxNumberOfRetries}`); + if (numberOfRetries === operationDbBackupMaxNumberOfRetries) { + throw error; + } + } + } + } +} + +async function main() { let backupDir; try { loadConfiguration(); @@ -172,6 +206,8 @@ function main() { } } + await backupOperationalDb(backupDir); + for (const file of certs) { moveFileFromNodeToBackup(file, argv.certs, backupDir, false); } diff --git a/test/bdd/steps/endpoints.js b/test/bdd/steps/endpoints.js index 876913a466..1dc59128be 100644 --- a/test/bdd/steps/endpoints.js +++ b/test/bdd/steps/endpoints.js @@ -390,7 +390,7 @@ Given(/^([DC|DH]+) runs local query consisting of path: "(\S+)", value: "(\S+)" const queryNetworkResponse = await httpApiHelper.apiQueryLocal(dv.state.node_rpc_url, jsonQuery); expect(queryNetworkResponse.length, 'Response should be an array').to.be.equal(1); - expect(Object.keys(queryNetworkResponse[0]), 'Array element should have datasets, offers, otObject').to.have.members(['dataset_id', 'offer_id', 'otObject']); + expect(Object.keys(queryNetworkResponse[0]), 'Array element should have datasets, offers, otObject').to.have.members(['dataset_id', 'replication_info', 'otObject']); // eslint-disable-next-line prefer-destructuring this.state.lastLocalQueryResponse = queryNetworkResponse[0]; }); @@ -399,7 +399,7 @@ Then(/^The last local query should return otObject from the last imported datase expect(this.state.lastLocalQueryResponse, 'Last local query not defined').to.not.be.equal(null); expect(!!this.state.lastImport, 'Nothing was imported. Use other step to do it.').to.be.equal(true); expect(!!this.state.lastImport.data.dataset_id, 'Last imports data set id seems not defined').to.be.equal(true); - expect(Object.keys(this.state.lastLocalQueryResponse), 'Array element should have datasets, otObject').to.have.members(['dataset_id', 'offer_id', 'otObject']); + expect(Object.keys(this.state.lastLocalQueryResponse), 'Array element should have datasets, otObject').to.have.members(['dataset_id', 'replication_info', 'otObject']); expect(this.state.lastImport.data.dataset_id, 'otObject should be from the latest imported dataset').to.be.equal(this.state.lastLocalQueryResponse.dataset_id); }); diff --git a/test/docker/check_image.sh b/test/docker/check_image.sh index 43565662a2..33182077c7 100755 --- a/test/docker/check_image.sh +++ b/test/docker/check_image.sh @@ -8,7 +8,7 @@ docker images cat $ARTIFACTS_DIR/truffle-migrate.log | grep "Hub contract address:" node test/docker/getHubAddress.js cp origintrail_noderc.image new_config_file -docker run -d --name=mynode -p 8900:8900 -p 5278:5278 -p 3000:3000 --network host -v new_config_file:/ot-node/.origintrail_noderc myimage:latest +docker run -d --name=mynode -p 8900:8900 -p 5278:5278 -p 3000:3000 --network host -v "$(pwd)"/new_config_file:/ot-node/.origintrail_noderc myimage:latest # TODO make sure that one of acct-keys is in origintrail_noderc.image # cat $ARTIFACTS_DIR/acct-keys.log # Give some time for node to start @@ -16,7 +16,7 @@ sleep 180 # docker container inspect mynode # docker network inspect host docker logs mynode --tail 1000 > $ARTIFACTS_DIR/docker.logs -docker exec mynode /bin/sh -c "curl -X POST http://127.0.0.1:8900/api/latest/import -F standard_id=GS1-EPCIS -F file=@/importers/xml_examples/Retail/03_Pink_to_orange_shipment.xml" > importResult.json +docker exec mynode /bin/sh -c "curl -X POST http://127.0.0.1:8900/api/latest/import -F standard_id=GS1-EPCIS -F file=\"$(pwd)/importers/xml_examples/Retail/03_Pink_to_orange_shipment.xml\"" > importResult.json cp importResult.json $ARTIFACTS_DIR/importResult.json # TODO better asserts that import response has one key, handler_id diff --git a/test/docker/cleanup_image.sh b/test/docker/cleanup_image.sh index 15bf4e8afb..81898a4a75 100755 --- a/test/docker/cleanup_image.sh +++ b/test/docker/cleanup_image.sh @@ -5,4 +5,4 @@ set -ev docker logs mynode docker stop mynode docker rm mynode -docker rmi myimage:latest \ No newline at end of file +docker rmi myimage:latest