From e7e54ff42175e33a366b2226b8368b6668975ac2 Mon Sep 17 00:00:00 2001 From: Lily Anne Hall Date: Sat, 16 Nov 2024 11:30:00 -0800 Subject: [PATCH] consolidate protocol spec into one document for archival --- README.md | 11 +- Storj/core/CONTRIBUTING.md | 114 - Storj/core/INSTALL.md | 80 - Storj/core/ISSUE_TEMPLATE.md | 41 - Storj/core/README.md | 59 - Storj/core/TRUSTED_KEYS | 2 - Storj/core/dist/.gitkeep | 0 Storj/core/doc/assets/tunneling-diagram | 1 - Storj/core/doc/command-line-interface.md | 97 - Storj/core/doc/contract-topics.md | 130 - Storj/core/doc/data-transfer.md | 29 - Storj/core/doc/environment-variables.md | 39 - Storj/core/doc/file-encryption.md | 114 - Storj/core/doc/index.json | 29 - Storj/core/doc/private-testnet.md | 70 - Storj/core/doc/renting-data.md | 302 - Storj/core/doc/tunnel-connections.md | 114 - Storj/core/docs/AuditStream.html | 721 -- Storj/core/docs/Blacklist.html | 484 -- Storj/core/docs/BridgeClient.html | 6926 ----------------- Storj/core/docs/Contact.html | 632 -- Storj/core/docs/Contract.html | 4264 ---------- Storj/core/docs/DataCipherKeyIv.html | 722 -- Storj/core/docs/DecryptStream.html | 424 - Storj/core/docs/DeterministicKeyIv.html | 878 --- Storj/core/docs/EmbeddedStorageAdapter.html | 1882 ----- Storj/core/docs/EncryptStream.html | 424 - Storj/core/docs/ExchangeReport.html | 751 -- Storj/core/docs/FarmerInterface.html | 3279 -------- Storj/core/docs/FileDemuxer.html | 819 -- Storj/core/docs/FileMuxer.html | 699 -- Storj/core/docs/KeyPair.html | 926 --- Storj/core/docs/KeyRing.html | 2237 ------ Storj/core/docs/Monitor.html | 1353 ---- Storj/core/docs/Network.html | 2795 ------- Storj/core/docs/OfferManager.html | 607 -- Storj/core/docs/OfferStream.html | 1068 --- Storj/core/docs/ProofStream.html | 356 - Storj/core/docs/Protocol.html | 5070 ------------ Storj/core/docs/RAMStorageAdapter.html | 2259 ------ Storj/core/docs/RenterInterface.html | 4698 ----------- Storj/core/docs/ShardServer.html | 1615 ---- Storj/core/docs/StorageAdapter.html | 3108 -------- Storj/core/docs/StorageItem.html | 1399 ---- Storj/core/docs/StorageManager.html | 1115 --- Storj/core/docs/StorageMigration.html | 425 - Storj/core/docs/Transport.html | 943 --- Storj/core/docs/TriggerManager.html | 1275 --- Storj/core/docs/UploadState.html | 570 -- Storj/core/docs/Verification.html | 408 - Storj/core/docs/assets/tunneling-diagram | 1 - Storj/core/docs/assets/tunneling.png | Bin 41277 -> 0 bytes .../core/docs/fonts/OpenSans-Bold-webfont.eot | Bin 19544 -> 0 bytes .../core/docs/fonts/OpenSans-Bold-webfont.svg | 1830 ----- .../docs/fonts/OpenSans-Bold-webfont.woff | Bin 22432 -> 0 bytes .../fonts/OpenSans-BoldItalic-webfont.eot | Bin 20133 -> 0 bytes .../fonts/OpenSans-BoldItalic-webfont.svg | 1830 ----- .../fonts/OpenSans-BoldItalic-webfont.woff | Bin 23048 -> 0 bytes .../docs/fonts/OpenSans-Italic-webfont.eot | Bin 20265 -> 0 bytes .../docs/fonts/OpenSans-Italic-webfont.svg | 1830 ----- .../docs/fonts/OpenSans-Italic-webfont.woff | Bin 23188 -> 0 bytes .../docs/fonts/OpenSans-Light-webfont.eot | Bin 19514 -> 0 bytes .../docs/fonts/OpenSans-Light-webfont.svg | 1831 ----- .../docs/fonts/OpenSans-Light-webfont.woff | Bin 22248 -> 0 bytes .../fonts/OpenSans-LightItalic-webfont.eot | Bin 20535 -> 0 bytes .../fonts/OpenSans-LightItalic-webfont.svg | 1835 ----- .../fonts/OpenSans-LightItalic-webfont.woff | Bin 23400 -> 0 bytes .../docs/fonts/OpenSans-Regular-webfont.eot | Bin 19836 -> 0 bytes .../docs/fonts/OpenSans-Regular-webfont.svg | 1831 ----- .../docs/fonts/OpenSans-Regular-webfont.woff | Bin 22660 -> 0 bytes Storj/core/docs/index.html | 115 - Storj/core/docs/index.js.html | 161 - .../docs/lib_audit-tools_audit-stream.js.html | 223 - .../docs/lib_audit-tools_proof-stream.js.html | 189 - .../docs/lib_audit-tools_verification.js.html | 131 - .../docs/lib_bridge-client_blacklist.js.html | 213 - .../lib_bridge-client_exchange-report.js.html | 118 - .../core/docs/lib_bridge-client_index.js.html | 1396 ---- .../lib_bridge-client_upload-state.js.html | 130 - Storj/core/docs/lib_constants.js.html | 112 - Storj/core/docs/lib_contract_index.js.html | 514 -- .../docs/lib_contract_offer-manager.js.html | 102 - .../docs/lib_contract_offer-stream.js.html | 176 - .../lib_crypto-tools_cipher-key-iv.js.html | 121 - .../lib_crypto-tools_decrypt-stream.js.html | 120 - ..._crypto-tools_deterministic-key-iv.js.html | 128 - .../lib_crypto-tools_encrypt-stream.js.html | 120 - .../docs/lib_crypto-tools_keypair.js.html | 144 - .../docs/lib_crypto-tools_keyring.js.html | 439 -- Storj/core/docs/lib_deps.js.html | 76 - .../lib_file-handling_file-demuxer.js.html | 238 - .../docs/lib_file-handling_file-muxer.js.html | 230 - Storj/core/docs/lib_network_contact.js.html | 141 - Storj/core/docs/lib_network_farmer.js.html | 439 -- Storj/core/docs/lib_network_index.js.html | 1005 --- Storj/core/docs/lib_network_monitor.js.html | 285 - Storj/core/docs/lib_network_protocol.js.html | 758 -- Storj/core/docs/lib_network_renter.js.html | 356 - .../docs/lib_network_shard-server.js.html | 346 - Storj/core/docs/lib_network_transport.js.html | 478 -- Storj/core/docs/lib_patches.js.html | 67 - Storj/core/docs/lib_sips_0003_index.js.html | 59 - .../lib_sips_0003_trigger-manager.js.html | 188 - Storj/core/docs/lib_sips_index.js.html | 60 - Storj/core/docs/lib_storage_adapter.js.html | 318 - .../lib_storage_adapters_embedded.js.html | 333 - .../docs/lib_storage_adapters_ram.js.html | 216 - Storj/core/docs/lib_storage_item.js.html | 222 - Storj/core/docs/lib_storage_manager.js.html | 245 - Storj/core/docs/lib_storage_migration.js.html | 188 - Storj/core/docs/lib_utils.js.html | 640 -- Storj/core/docs/lib_version.js.html | 72 - Storj/core/docs/module-storj.html | 2197 ------ Storj/core/docs/module-storj_constants.html | 1919 ----- Storj/core/docs/module-storj_deps.html | 296 - Storj/core/docs/module-storj_patches.html | 85 - Storj/core/docs/module-storj_sips.html | 151 - Storj/core/docs/module-storj_sips_0003.html | 151 - Storj/core/docs/module-storj_utils.html | 5990 -------------- Storj/core/docs/module-storj_version.html | 233 - Storj/core/docs/scripts/linenumber.js | 25 - .../scripts/prettify/Apache-License-2.0.txt | 202 - Storj/core/docs/scripts/prettify/lang-css.js | 2 - Storj/core/docs/scripts/prettify/prettify.js | 28 - Storj/core/docs/styles/jsdoc-default.css | 358 - Storj/core/docs/styles/prettify-jsdoc.css | 111 - Storj/core/docs/styles/prettify-tomorrow.css | 132 - .../docs/tutorial-command-line-interface.html | 122 - Storj/core/docs/tutorial-contract-topics.html | 146 - Storj/core/docs/tutorial-data-transfer.html | 81 - .../docs/tutorial-environment-variables.html | 76 - Storj/core/docs/tutorial-file-encryption.html | 147 - Storj/core/docs/tutorial-private-testnet.html | 106 - Storj/core/docs/tutorial-protocol-spec.html | 996 --- Storj/core/docs/tutorial-renting-data.html | 314 - .../docs/tutorial-tunnel-connections.html | 149 - Storj/core/script/publishdoc.js | 10 - Storj/{core => protocol-v2}/.eslintignore | 0 Storj/{core => protocol-v2}/.eslintrc | 0 Storj/{core => protocol-v2}/.gitignore | 0 Storj/{core => protocol-v2}/.jsdoc.json | 0 Storj/{core => protocol-v2}/.jshintrc | 0 Storj/{core => protocol-v2}/.nvmrc | 0 Storj/{core => protocol-v2}/.travis.yml | 0 Storj/{core => protocol-v2}/LICENSE-AGPL-3.0 | 0 Storj/{core => protocol-v2}/LICENSE-LGPL-3.0 | 0 .../README.md} | 644 +- .../assets/images}/tunneling.png | Bin Storj/{core => protocol-v2}/bench/index.js | 0 .../example/1-create-user.js | 0 .../example/2-generate-keypair.js | 0 .../example/3-authenticate-with-keypair.js | 0 .../example/4a-list-keys.js | 0 .../example/4b-add-remove-keys.js | 0 .../example/5a-list-buckets.js | 0 .../example/5b-add-remove-bucket.js | 0 .../example/6a-upload-file.js | 0 .../example/6b-download-file.js | 0 .../example/6c-list-bucket-files.js | 0 .../example/6d-delete-file-from-bucket.js | 0 Storj/{core => protocol-v2}/index.js | 0 .../lib/audit-tools/audit-stream.js | 0 .../lib/audit-tools/proof-stream.js | 0 .../lib/audit-tools/verification.js | 0 .../lib/bridge-client/blacklist.js | 0 .../lib/bridge-client/exchange-report.js | 0 .../lib/bridge-client/index.js | 0 .../lib/bridge-client/upload-state.js | 0 Storj/{core => protocol-v2}/lib/constants.js | 0 .../lib/contract/index.js | 0 .../lib/contract/offer-manager.js | 0 .../lib/contract/offer-stream.js | 0 .../lib/contract/schema.json | 0 .../lib/crypto-tools/cipher-key-iv.js | 0 .../lib/crypto-tools/decrypt-stream.js | 0 .../lib/crypto-tools/deterministic-key-iv.js | 0 .../lib/crypto-tools/encrypt-stream.js | 0 .../lib/crypto-tools/keypair.js | 0 .../lib/crypto-tools/keyring.js | 0 Storj/{core => protocol-v2}/lib/deps.js | 0 .../lib/file-handling/file-demuxer.js | 0 .../lib/file-handling/file-muxer.js | 0 .../lib/network/contact.js | 0 .../lib/network/farmer.js | 0 .../lib/network/index.js | 0 .../lib/network/monitor.js | 0 .../lib/network/protocol.js | 0 .../lib/network/renter.js | 0 .../lib/network/shard-server.js | 0 .../lib/network/transport.js | 0 Storj/{core => protocol-v2}/lib/patches.js | 0 .../lib/sips/0003/index.js | 0 .../lib/sips/0003/trigger-manager.js | 0 Storj/{core => protocol-v2}/lib/sips/index.js | 0 .../lib/storage/adapter.js | 0 .../lib/storage/adapters/embedded.js | 0 .../lib/storage/adapters/ram.js | 0 .../{core => protocol-v2}/lib/storage/item.js | 0 .../lib/storage/manager.js | 0 .../lib/storage/migration.js | 0 Storj/{core => protocol-v2}/lib/utils.js | 0 Storj/{core => protocol-v2}/lib/version.js | 0 Storj/{core => protocol-v2}/package-lock.json | 0 Storj/{core => protocol-v2}/package.json | 0 Storj/{core => protocol-v2}/test/.eslintrc | 0 .../test/audit-tools/audit-stream.unit.js | 0 .../test/audit-tools/proof-stream.unit.js | 0 .../test/audit-tools/verification.unit.js | 0 .../test/bridge-client/blacklist.unit.js | 0 .../bridge-client/exchange-report.unit.js | 0 .../test/bridge-client/index.unit.js | 0 .../test/bridge-client/upload-state.unit.js | 0 .../test/contract/index.unit.js | 0 .../test/contract/offer-manager.unit.js | 0 .../test/contract/offer-stream.unit.js | 0 .../test/crypto-tools/cipher-key-iv.unit.js | 0 .../crypto-tools/deterministic-key-iv.unit.js | 0 .../encrypt-stream+decrypt-stream.unit.js | 0 .../test/crypto-tools/keypair.unit.js | 0 .../test/crypto-tools/keyring.unit.js | 0 .../test/file-handling/file-demuxer.unit.js | 0 .../test/file-handling/file-muxer.unit.js | 0 .../test/network/contact.unit.js | 0 .../test/network/farmer.unit.js | 0 .../test/network/index.unit.js | 0 .../test/network/monitor.unit.js | 0 .../test/network/protocol.unit.js | 0 .../test/network/renter.unit.js | 0 .../test/network/shard-server.unit.js | 0 .../test/network/transport.unit.js | 0 .../test/sips/0003/trigger-manager.unit.js | 0 .../test/storage/adapter.unit.js | 0 .../test/storage/adapters/embedded.unit.js | 0 .../test/storage/adapters/ram.unit.js | 0 .../test/storage/item.unit.js | 0 .../test/storage/manager.unit.js | 0 .../test/storage/migration.unit.js | 0 .../{core => protocol-v2}/test/utils.unit.js | 0 .../test/version.unit.js | 0 239 files changed, 648 insertions(+), 92987 deletions(-) delete mode 100644 Storj/core/CONTRIBUTING.md delete mode 100644 Storj/core/INSTALL.md delete mode 100644 Storj/core/ISSUE_TEMPLATE.md delete mode 100644 Storj/core/README.md delete mode 100644 Storj/core/TRUSTED_KEYS delete mode 100644 Storj/core/dist/.gitkeep delete mode 100644 Storj/core/doc/assets/tunneling-diagram delete mode 100644 Storj/core/doc/command-line-interface.md delete mode 100644 Storj/core/doc/contract-topics.md delete mode 100644 Storj/core/doc/data-transfer.md delete mode 100644 Storj/core/doc/environment-variables.md delete mode 100644 Storj/core/doc/file-encryption.md delete mode 100644 Storj/core/doc/index.json delete mode 100644 Storj/core/doc/private-testnet.md delete mode 100644 Storj/core/doc/renting-data.md delete mode 100644 Storj/core/doc/tunnel-connections.md delete mode 100644 Storj/core/docs/AuditStream.html delete mode 100644 Storj/core/docs/Blacklist.html delete mode 100644 Storj/core/docs/BridgeClient.html delete mode 100644 Storj/core/docs/Contact.html delete mode 100644 Storj/core/docs/Contract.html delete mode 100644 Storj/core/docs/DataCipherKeyIv.html delete mode 100644 Storj/core/docs/DecryptStream.html delete mode 100644 Storj/core/docs/DeterministicKeyIv.html delete mode 100644 Storj/core/docs/EmbeddedStorageAdapter.html delete mode 100644 Storj/core/docs/EncryptStream.html delete mode 100644 Storj/core/docs/ExchangeReport.html delete mode 100644 Storj/core/docs/FarmerInterface.html delete mode 100644 Storj/core/docs/FileDemuxer.html delete mode 100644 Storj/core/docs/FileMuxer.html delete mode 100644 Storj/core/docs/KeyPair.html delete mode 100644 Storj/core/docs/KeyRing.html delete mode 100644 Storj/core/docs/Monitor.html delete mode 100644 Storj/core/docs/Network.html delete mode 100644 Storj/core/docs/OfferManager.html delete mode 100644 Storj/core/docs/OfferStream.html delete mode 100644 Storj/core/docs/ProofStream.html delete mode 100644 Storj/core/docs/Protocol.html delete mode 100644 Storj/core/docs/RAMStorageAdapter.html delete mode 100644 Storj/core/docs/RenterInterface.html delete mode 100644 Storj/core/docs/ShardServer.html delete mode 100644 Storj/core/docs/StorageAdapter.html delete mode 100644 Storj/core/docs/StorageItem.html delete mode 100644 Storj/core/docs/StorageManager.html delete mode 100644 Storj/core/docs/StorageMigration.html delete mode 100644 Storj/core/docs/Transport.html delete mode 100644 Storj/core/docs/TriggerManager.html delete mode 100644 Storj/core/docs/UploadState.html delete mode 100644 Storj/core/docs/Verification.html delete mode 100644 Storj/core/docs/assets/tunneling-diagram delete mode 100644 Storj/core/docs/assets/tunneling.png delete mode 100644 Storj/core/docs/fonts/OpenSans-Bold-webfont.eot delete mode 100644 Storj/core/docs/fonts/OpenSans-Bold-webfont.svg delete mode 100644 Storj/core/docs/fonts/OpenSans-Bold-webfont.woff delete mode 100644 Storj/core/docs/fonts/OpenSans-BoldItalic-webfont.eot delete mode 100644 Storj/core/docs/fonts/OpenSans-BoldItalic-webfont.svg delete mode 100644 Storj/core/docs/fonts/OpenSans-BoldItalic-webfont.woff delete mode 100644 Storj/core/docs/fonts/OpenSans-Italic-webfont.eot delete mode 100644 Storj/core/docs/fonts/OpenSans-Italic-webfont.svg delete mode 100644 Storj/core/docs/fonts/OpenSans-Italic-webfont.woff delete mode 100644 Storj/core/docs/fonts/OpenSans-Light-webfont.eot delete mode 100644 Storj/core/docs/fonts/OpenSans-Light-webfont.svg delete mode 100644 Storj/core/docs/fonts/OpenSans-Light-webfont.woff delete mode 100644 Storj/core/docs/fonts/OpenSans-LightItalic-webfont.eot delete mode 100644 Storj/core/docs/fonts/OpenSans-LightItalic-webfont.svg delete mode 100644 Storj/core/docs/fonts/OpenSans-LightItalic-webfont.woff delete mode 100644 Storj/core/docs/fonts/OpenSans-Regular-webfont.eot delete mode 100644 Storj/core/docs/fonts/OpenSans-Regular-webfont.svg delete mode 100644 Storj/core/docs/fonts/OpenSans-Regular-webfont.woff delete mode 100644 Storj/core/docs/index.html delete mode 100644 Storj/core/docs/index.js.html delete mode 100644 Storj/core/docs/lib_audit-tools_audit-stream.js.html delete mode 100644 Storj/core/docs/lib_audit-tools_proof-stream.js.html delete mode 100644 Storj/core/docs/lib_audit-tools_verification.js.html delete mode 100644 Storj/core/docs/lib_bridge-client_blacklist.js.html delete mode 100644 Storj/core/docs/lib_bridge-client_exchange-report.js.html delete mode 100644 Storj/core/docs/lib_bridge-client_index.js.html delete mode 100644 Storj/core/docs/lib_bridge-client_upload-state.js.html delete mode 100644 Storj/core/docs/lib_constants.js.html delete mode 100644 Storj/core/docs/lib_contract_index.js.html delete mode 100644 Storj/core/docs/lib_contract_offer-manager.js.html delete mode 100644 Storj/core/docs/lib_contract_offer-stream.js.html delete mode 100644 Storj/core/docs/lib_crypto-tools_cipher-key-iv.js.html delete mode 100644 Storj/core/docs/lib_crypto-tools_decrypt-stream.js.html delete mode 100644 Storj/core/docs/lib_crypto-tools_deterministic-key-iv.js.html delete mode 100644 Storj/core/docs/lib_crypto-tools_encrypt-stream.js.html delete mode 100644 Storj/core/docs/lib_crypto-tools_keypair.js.html delete mode 100644 Storj/core/docs/lib_crypto-tools_keyring.js.html delete mode 100644 Storj/core/docs/lib_deps.js.html delete mode 100644 Storj/core/docs/lib_file-handling_file-demuxer.js.html delete mode 100644 Storj/core/docs/lib_file-handling_file-muxer.js.html delete mode 100644 Storj/core/docs/lib_network_contact.js.html delete mode 100644 Storj/core/docs/lib_network_farmer.js.html delete mode 100644 Storj/core/docs/lib_network_index.js.html delete mode 100644 Storj/core/docs/lib_network_monitor.js.html delete mode 100644 Storj/core/docs/lib_network_protocol.js.html delete mode 100644 Storj/core/docs/lib_network_renter.js.html delete mode 100644 Storj/core/docs/lib_network_shard-server.js.html delete mode 100644 Storj/core/docs/lib_network_transport.js.html delete mode 100644 Storj/core/docs/lib_patches.js.html delete mode 100644 Storj/core/docs/lib_sips_0003_index.js.html delete mode 100644 Storj/core/docs/lib_sips_0003_trigger-manager.js.html delete mode 100644 Storj/core/docs/lib_sips_index.js.html delete mode 100644 Storj/core/docs/lib_storage_adapter.js.html delete mode 100644 Storj/core/docs/lib_storage_adapters_embedded.js.html delete mode 100644 Storj/core/docs/lib_storage_adapters_ram.js.html delete mode 100644 Storj/core/docs/lib_storage_item.js.html delete mode 100644 Storj/core/docs/lib_storage_manager.js.html delete mode 100644 Storj/core/docs/lib_storage_migration.js.html delete mode 100644 Storj/core/docs/lib_utils.js.html delete mode 100644 Storj/core/docs/lib_version.js.html delete mode 100644 Storj/core/docs/module-storj.html delete mode 100644 Storj/core/docs/module-storj_constants.html delete mode 100644 Storj/core/docs/module-storj_deps.html delete mode 100644 Storj/core/docs/module-storj_patches.html delete mode 100644 Storj/core/docs/module-storj_sips.html delete mode 100644 Storj/core/docs/module-storj_sips_0003.html delete mode 100644 Storj/core/docs/module-storj_utils.html delete mode 100644 Storj/core/docs/module-storj_version.html delete mode 100644 Storj/core/docs/scripts/linenumber.js delete mode 100644 Storj/core/docs/scripts/prettify/Apache-License-2.0.txt delete mode 100644 Storj/core/docs/scripts/prettify/lang-css.js delete mode 100644 Storj/core/docs/scripts/prettify/prettify.js delete mode 100644 Storj/core/docs/styles/jsdoc-default.css delete mode 100644 Storj/core/docs/styles/prettify-jsdoc.css delete mode 100644 Storj/core/docs/styles/prettify-tomorrow.css delete mode 100644 Storj/core/docs/tutorial-command-line-interface.html delete mode 100644 Storj/core/docs/tutorial-contract-topics.html delete mode 100644 Storj/core/docs/tutorial-data-transfer.html delete mode 100644 Storj/core/docs/tutorial-environment-variables.html delete mode 100644 Storj/core/docs/tutorial-file-encryption.html delete mode 100644 Storj/core/docs/tutorial-private-testnet.html delete mode 100644 Storj/core/docs/tutorial-protocol-spec.html delete mode 100644 Storj/core/docs/tutorial-renting-data.html delete mode 100644 Storj/core/docs/tutorial-tunnel-connections.html delete mode 100644 Storj/core/script/publishdoc.js rename Storj/{core => protocol-v2}/.eslintignore (100%) rename Storj/{core => protocol-v2}/.eslintrc (100%) rename Storj/{core => protocol-v2}/.gitignore (100%) rename Storj/{core => protocol-v2}/.jsdoc.json (100%) rename Storj/{core => protocol-v2}/.jshintrc (100%) rename Storj/{core => protocol-v2}/.nvmrc (100%) rename Storj/{core => protocol-v2}/.travis.yml (100%) rename Storj/{core => protocol-v2}/LICENSE-AGPL-3.0 (100%) rename Storj/{core => protocol-v2}/LICENSE-LGPL-3.0 (100%) rename Storj/{core/doc/protocol-spec.md => protocol-v2/README.md} (61%) rename Storj/{core/doc/assets => protocol-v2/assets/images}/tunneling.png (100%) rename Storj/{core => protocol-v2}/bench/index.js (100%) rename Storj/{core => protocol-v2}/example/1-create-user.js (100%) rename Storj/{core => protocol-v2}/example/2-generate-keypair.js (100%) rename Storj/{core => protocol-v2}/example/3-authenticate-with-keypair.js (100%) rename Storj/{core => protocol-v2}/example/4a-list-keys.js (100%) rename Storj/{core => protocol-v2}/example/4b-add-remove-keys.js (100%) rename Storj/{core => protocol-v2}/example/5a-list-buckets.js (100%) rename Storj/{core => protocol-v2}/example/5b-add-remove-bucket.js (100%) rename Storj/{core => protocol-v2}/example/6a-upload-file.js (100%) rename Storj/{core => protocol-v2}/example/6b-download-file.js (100%) rename Storj/{core => protocol-v2}/example/6c-list-bucket-files.js (100%) rename Storj/{core => protocol-v2}/example/6d-delete-file-from-bucket.js (100%) rename Storj/{core => protocol-v2}/index.js (100%) rename Storj/{core => protocol-v2}/lib/audit-tools/audit-stream.js (100%) rename Storj/{core => protocol-v2}/lib/audit-tools/proof-stream.js (100%) rename Storj/{core => protocol-v2}/lib/audit-tools/verification.js (100%) rename Storj/{core => protocol-v2}/lib/bridge-client/blacklist.js (100%) rename Storj/{core => protocol-v2}/lib/bridge-client/exchange-report.js (100%) rename Storj/{core => protocol-v2}/lib/bridge-client/index.js (100%) rename Storj/{core => protocol-v2}/lib/bridge-client/upload-state.js (100%) rename Storj/{core => protocol-v2}/lib/constants.js (100%) rename Storj/{core => protocol-v2}/lib/contract/index.js (100%) rename Storj/{core => protocol-v2}/lib/contract/offer-manager.js (100%) rename Storj/{core => protocol-v2}/lib/contract/offer-stream.js (100%) rename Storj/{core => protocol-v2}/lib/contract/schema.json (100%) rename Storj/{core => protocol-v2}/lib/crypto-tools/cipher-key-iv.js (100%) rename Storj/{core => protocol-v2}/lib/crypto-tools/decrypt-stream.js (100%) rename Storj/{core => protocol-v2}/lib/crypto-tools/deterministic-key-iv.js (100%) rename Storj/{core => protocol-v2}/lib/crypto-tools/encrypt-stream.js (100%) rename Storj/{core => protocol-v2}/lib/crypto-tools/keypair.js (100%) rename Storj/{core => protocol-v2}/lib/crypto-tools/keyring.js (100%) rename Storj/{core => protocol-v2}/lib/deps.js (100%) rename Storj/{core => protocol-v2}/lib/file-handling/file-demuxer.js (100%) rename Storj/{core => protocol-v2}/lib/file-handling/file-muxer.js (100%) rename Storj/{core => protocol-v2}/lib/network/contact.js (100%) rename Storj/{core => protocol-v2}/lib/network/farmer.js (100%) rename Storj/{core => protocol-v2}/lib/network/index.js (100%) rename Storj/{core => protocol-v2}/lib/network/monitor.js (100%) rename Storj/{core => protocol-v2}/lib/network/protocol.js (100%) rename Storj/{core => protocol-v2}/lib/network/renter.js (100%) rename Storj/{core => protocol-v2}/lib/network/shard-server.js (100%) rename Storj/{core => protocol-v2}/lib/network/transport.js (100%) rename Storj/{core => protocol-v2}/lib/patches.js (100%) rename Storj/{core => protocol-v2}/lib/sips/0003/index.js (100%) rename Storj/{core => protocol-v2}/lib/sips/0003/trigger-manager.js (100%) rename Storj/{core => protocol-v2}/lib/sips/index.js (100%) rename Storj/{core => protocol-v2}/lib/storage/adapter.js (100%) rename Storj/{core => protocol-v2}/lib/storage/adapters/embedded.js (100%) rename Storj/{core => protocol-v2}/lib/storage/adapters/ram.js (100%) rename Storj/{core => protocol-v2}/lib/storage/item.js (100%) rename Storj/{core => protocol-v2}/lib/storage/manager.js (100%) rename Storj/{core => protocol-v2}/lib/storage/migration.js (100%) rename Storj/{core => protocol-v2}/lib/utils.js (100%) rename Storj/{core => protocol-v2}/lib/version.js (100%) rename Storj/{core => protocol-v2}/package-lock.json (100%) rename Storj/{core => protocol-v2}/package.json (100%) rename Storj/{core => protocol-v2}/test/.eslintrc (100%) rename Storj/{core => protocol-v2}/test/audit-tools/audit-stream.unit.js (100%) rename Storj/{core => protocol-v2}/test/audit-tools/proof-stream.unit.js (100%) rename Storj/{core => protocol-v2}/test/audit-tools/verification.unit.js (100%) rename Storj/{core => protocol-v2}/test/bridge-client/blacklist.unit.js (100%) rename Storj/{core => protocol-v2}/test/bridge-client/exchange-report.unit.js (100%) rename Storj/{core => protocol-v2}/test/bridge-client/index.unit.js (100%) rename Storj/{core => protocol-v2}/test/bridge-client/upload-state.unit.js (100%) rename Storj/{core => protocol-v2}/test/contract/index.unit.js (100%) rename Storj/{core => protocol-v2}/test/contract/offer-manager.unit.js (100%) rename Storj/{core => protocol-v2}/test/contract/offer-stream.unit.js (100%) rename Storj/{core => protocol-v2}/test/crypto-tools/cipher-key-iv.unit.js (100%) rename Storj/{core => protocol-v2}/test/crypto-tools/deterministic-key-iv.unit.js (100%) rename Storj/{core => protocol-v2}/test/crypto-tools/encrypt-stream+decrypt-stream.unit.js (100%) rename Storj/{core => protocol-v2}/test/crypto-tools/keypair.unit.js (100%) rename Storj/{core => protocol-v2}/test/crypto-tools/keyring.unit.js (100%) rename Storj/{core => protocol-v2}/test/file-handling/file-demuxer.unit.js (100%) rename Storj/{core => protocol-v2}/test/file-handling/file-muxer.unit.js (100%) rename Storj/{core => protocol-v2}/test/network/contact.unit.js (100%) rename Storj/{core => protocol-v2}/test/network/farmer.unit.js (100%) rename Storj/{core => protocol-v2}/test/network/index.unit.js (100%) rename Storj/{core => protocol-v2}/test/network/monitor.unit.js (100%) rename Storj/{core => protocol-v2}/test/network/protocol.unit.js (100%) rename Storj/{core => protocol-v2}/test/network/renter.unit.js (100%) rename Storj/{core => protocol-v2}/test/network/shard-server.unit.js (100%) rename Storj/{core => protocol-v2}/test/network/transport.unit.js (100%) rename Storj/{core => protocol-v2}/test/sips/0003/trigger-manager.unit.js (100%) rename Storj/{core => protocol-v2}/test/storage/adapter.unit.js (100%) rename Storj/{core => protocol-v2}/test/storage/adapters/embedded.unit.js (100%) rename Storj/{core => protocol-v2}/test/storage/adapters/ram.unit.js (100%) rename Storj/{core => protocol-v2}/test/storage/item.unit.js (100%) rename Storj/{core => protocol-v2}/test/storage/manager.unit.js (100%) rename Storj/{core => protocol-v2}/test/storage/migration.unit.js (100%) rename Storj/{core => protocol-v2}/test/utils.unit.js (100%) rename Storj/{core => protocol-v2}/test/version.unit.js (100%) diff --git a/README.md b/README.md index 5f92eaa..cb02011 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@ # lily anne hall *research publications* -## white papers +## white papers, technical specifications -* [Storj: a peer-to-peer cloud storage network](./Storj/Storj.Whitepaper.V2.pdf) (Contributor -- Storj, 2016) - -## experiments +### Storj * [KFS: a LevelDB sharding algorithm based on the XOR metric](./Storj/kfs) (Author -- Storj, 2016) +* [Storj: a peer-to-peer cloud storage network](./Storj/Storj.Whitepaper.V2.pdf) (Contributor -- Storj, 2016) +* [Protocol Specification V2](./Storj/protocol-v2) (Author -- Storj, 2016) +* [SIP 0003: Remote Notifications and Triggers](./Storj/sip-0003) (Author -- Storj, 2016) +* [SIP 0004: Contract Transfers and Renewals](./Storj/sip-0004) (Contributor -- Storj, 2016) +* [SIP 0032: Hierarchically Deterministic Node IDs](./Storj/sip-0032) (Contributor -- Storj, 2016) ## security audits diff --git a/Storj/core/CONTRIBUTING.md b/Storj/core/CONTRIBUTING.md deleted file mode 100644 index 22372c0..0000000 --- a/Storj/core/CONTRIBUTING.md +++ /dev/null @@ -1,114 +0,0 @@ -Contributing -============ - -Want to contribute, but not sure where to start? Check out our [issue -board](http://waffle.io/storj/core)! - -This document outlines general patterns and conventions for contributing -to the project. For in-depth documentation on StorjCORE, [read the -documentation](http://storj.github.io/core). - -Contributor License Agreement ------------------------------ - -By submitting pull requests, you agree that your work may be licensed under -one of: - -* GNU Affero General Public License Version 3 (or later) -* GNU Lesser General Public License Version 3 (or later) - -You also assert that you have completed the -[Contributor License Agreement](https://storj.io/cla) - -Reporting Issues ----------------- - -When submitting an issue, please take care to follow the -`ISSUE_TEMPLATE.md` and include as much information as possible. Bonus points -for a corresponding pull request that fixes the issue. - -Pull Requests for Swag ----------------------- -We love pull requests, so to encourage more of them we are offering -awesome swag. Only SIGNIFICANT pull requests count. Fixing a comma -doesn’t count, but fixing a bug, adding more test coverage, or writing -guides & documentation does. - -- Make 1x pull requests to get into the contributors list and website -- Make 2x pull requests, we will send you a packet of stickers -- Make 5x pull requests, and we will send you a t-shirt and more stickers -- Make 10x pull requests, and you get a job interview with James + other swag - -If we miss a milestones (probably because we are working hard), just let -us know so we can get you your swag. - -Style & Conventions -------------------- - -### Style Guide - -StorjCORE adheres to -[Felix's Node.js Style Guide](https://github.com/felixge/node-style-guide). -Please take the time to review the style guide and take care to follow it. - -### Project Structure - -* `bin/` - Command line utilities linked during global installation -* `dist/` - Placeholder for browser bundles generated with `npm run build` -* `doc/` - Markdown documentation on various topics not covered by JSDoc -* `lib/` - All core classes and modules -* `script/` - Miscellaneous scripts and utilities used for development -* `test/` - Unit and integration tests for core classes and modules - -### Inline Documentation - -You should also make the best use of [JSDoc](http://usejsdoc.org/) comments as -shown throughout the source code. These annotation are used to generate the -library's documentation website. Please be as descriptive as possible and take -care to familiarize yourself with all of the possible JSDoc tags for -being as thorough as possible. - -Test Coverage -------------- - -Pull requests submitted without additional test coverage are unlikely to be -merged. Pull requests that decrease test coverage will be rejected. If your -submission fixes a bug that was not previously caught with the test suite, then -please add an additional test that does cover it. - -You can run the coverage report with: - -``` -npm run coverage -``` - -Linting -------- - -To help maintain consistent expectations for code quality and enforcing these -conventions, there is an included `.jshintrc` file. Most editors support using -this to alert you of offending code in real time but, if your editor does not, -you can run the linter with: - -``` -npm run linter -``` - -Alternatively, the linter will run as part of the test suite as well, which can -be executed with: - -``` -npm test -``` - -Credits -------- - -Before sending your PR, go ahead and add yourself to the `contributors` array -in the `package.json` file - you earned it :thumbsup:. - -![HACK THE PLANET](http://i.giphy.com/X1OGEvUf2t58A.gif) - ---- - -Have fun and be excellent! diff --git a/Storj/core/INSTALL.md b/Storj/core/INSTALL.md deleted file mode 100644 index 99b28df..0000000 --- a/Storj/core/INSTALL.md +++ /dev/null @@ -1,80 +0,0 @@ -### Prerequisites - -* Node.js LTS (v4.x.x) -* Python 2.7 -* Git 2.x.x - -### Installing on GNU/Linux & Mac OSX - -Install Node.js and it's package manager NPM using Node Version Manager: - -``` -curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash -``` - -> Detailed NVM installation instructions can be found [here](https://github.com/creationix/nvm#install-script). - -After NVM is installed, source your `~/.bashrc`, `~/.profile`, or `~/.zshrc` -depending on your shell of choice: - -``` -source ~/.zshrc -``` - -Now that you can call the `nvm` program, install Node.js (which comes with NPM): - -``` -nvm install 4.4.4 -``` - -> You'll also need to make sure you have a C++ compiler installed before -> proceeding to the next step. Debian based distributions can install the -> `build-essential` package using APT and Mac OSX users can install with -> `xcode-select --install` and follow the wizard. - -### Installing on Windows (Manual) - -Download [Node.js LTS](https://nodejs.org/en/download/) for Windows, launch the -installer and follow the setup instructions. Restart your PC, then test it from -the command prompt: - -``` -node --version -npm --version -``` - -Install the [latest version of Python 2.7](https://www.python.org/ftp/python/2.7.11/python-2.7.11.amd64.msi), -launch the installer and follow the instructions. To use Python from the shell -and add it to the system you have to add the path in "System Variables": - -Navigate to: - -``` -Control Panel > System > Advanced System Settings > Environment Variables > System Variables > Path > Edit -``` - -Then add `;C:\Python27` or the installation path and test it in the command -prompt by running: - -``` -python -V -``` - -Next, install [Git](https://git-for-windows.github.io/) for your Windows -version. Then, install [Visual Studio Community 2015](https://www.visualstudio.com/) -and during the setup choose `Custom Installation > Programming Languages` and -select **Visual C++** and **Common Tools for Visual C++**. - -Finally, set the new environment variable in the Windows command prompt with: - -```` -setx GYP_MSVS_VERSION 2015 -``` - -### Installing on Windows (Automated) - -Install utilizing automated script - -https://github.com/Storj/storj-automation/archive/master.zip - -Run the `install.bat` located in `/Windows/storj-automate` diff --git a/Storj/core/ISSUE_TEMPLATE.md b/Storj/core/ISSUE_TEMPLATE.md deleted file mode 100644 index 465dc4b..0000000 --- a/Storj/core/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,41 +0,0 @@ -### Package Versions - -Replace the values below using the output from `npm list storj`. Use ```npm list -g storj``` if installed globally. - -``` -storj-bridge@0.6.5 /home/gordon/Code/storj-bridge -└── storj@0.6.5 -> /home/gordon/Code/storj-core -``` - -Replace the values below using the output from `node --version`. - -``` -v4.2.3 -``` - -### Expected Behavior - -Please describe the program's expected behavior. Include an example of your -usage code in the back ticks below if applicable. - -``` - -``` - -### Actual Behavior - -Please describe the program's actual behavior. Please include any stack traces -or log output in the back ticks below. - -``` - -``` - -### Steps to Reproduce - -Please include the steps the reproduce the issue, numbered below. Include as -much detail as possible. - -1. ... -2. ... -3. ... diff --git a/Storj/core/README.md b/Storj/core/README.md deleted file mode 100644 index fe4960d..0000000 --- a/Storj/core/README.md +++ /dev/null @@ -1,59 +0,0 @@ -[![Storj](https://nodei.co/npm/storj-lib.png?downloads=true)](http://storj.github.io/core) -========================================================================================== - -[![Build Status](https://img.shields.io/travis/Storj/core.svg?style=flat-square)](https://travis-ci.org/Storj/core) -[![Coverage Status](https://img.shields.io/coveralls/Storj/core.svg?style=flat-square)](https://coveralls.io/r/Storj/core) -[![NPM](https://img.shields.io/npm/v/storj-lib.svg?style=flat-square)](https://www.npmjs.com/package/storj-lib) -[![License](https://img.shields.io/badge/license-AGPL3.0-blue.svg?style=flat-square)](https://raw.githubusercontent.com/Storj/core/master/LICENSE) - -This package exposes a module that provides all of the tools needed to -integrate with the Storj network. You must have Node.js v6.9.1, Python v2.x.x, -and Git installed. [Complete documentation can be found here](http://storj.github.io/core). - -``` -npm install storj-lib --save -``` - -> If you want access to the [Storj CLI](https://github.com/storj/core-cli), -> you must install it separately or use the [`storj`](https://github.com/storj/npm-meta) -> metapackage to install both the core library *and* command line interface. - -Usage Examples --------------- - -- [Example 1 - Creating a User](https://github.com/Storj/core/blob/master/example/1-create-user.js) -- [Example 2 - Generating a KeyPair](https://github.com/Storj/core/blob/master/example/2-generate-keypair.js) -- [Example 3 - Authenticating with a KeyPair](https://github.com/Storj/core/blob/master/example/3-authenticate-with-keypair.js) -- [Example 4 - Listing Keys](https://github.com/Storj/core/blob/master/example/4a-list-keys.js) -- [Example 4b - Add/Remove Keys](https://github.com/Storj/core/blob/master/example/4b-add-remove-keys.js) -- [Example 5a - List Buckets](https://github.com/Storj/core/blob/master/example/5a-list-buckets.js) -- [Example 5b - Add/Remove Bucket](https://github.com/Storj/core/blob/master/example/5b-add-remove-bucket.js) -- [Example 6a - Upload File](https://github.com/Storj/core/blob/master/example/6a-upload-file.js) -- [Example 6b - Download File](https://github.com/Storj/core/blob/master/example/6b-download-file.js) -- [Example 6c - List Bucket Files](https://github.com/Storj/core/blob/master/example/6c-list-bucket-files.js) -- [Example 6d - Delete File from Bucket](https://github.com/Storj/core/blob/master/example/6d-delete-file-from-bucket.js) - -License -------- - -Storj Core - Implementation of the Storj protocol for Node.js -Copyright (C) 2016 Storj Labs, Inc - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published -by the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -*Certain parts of this program are licensed under the GNU Lesser General -Public License as published by the Free Software Foundation. You can -redistribute it and/or modify it under the terms either version 3 of the -License, or (at your option) any later version.* - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see -[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/). diff --git a/Storj/core/TRUSTED_KEYS b/Storj/core/TRUSTED_KEYS deleted file mode 100644 index 5878d7a..0000000 --- a/Storj/core/TRUSTED_KEYS +++ /dev/null @@ -1,2 +0,0 @@ -xpub6AHweYHAxk1EhJSBctQD1nLWPog6Sy2eTpKQLExR1hfzTyyZQWvU4EYNXv1NJN7GpLYXnDLt4PzN874g6zSjAQdFCHZN7U7nbYKYVDUzD42 -xpub6BUG8pGsfYw7jFBkSx3WivxrnyEJK71FwLvwUVXZrVFWCxAf9d9wN53rCbvkszffYTGWktME7Qz1xXudXSUGPjWtZGYnZLiDgSJW1WKK7g9 diff --git a/Storj/core/dist/.gitkeep b/Storj/core/dist/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/Storj/core/doc/assets/tunneling-diagram b/Storj/core/doc/assets/tunneling-diagram deleted file mode 100644 index 1213e26..0000000 --- a/Storj/core/doc/assets/tunneling-diagram +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/Storj/core/doc/command-line-interface.md b/Storj/core/doc/command-line-interface.md deleted file mode 100644 index 185739c..0000000 --- a/Storj/core/doc/command-line-interface.md +++ /dev/null @@ -1,97 +0,0 @@ -This package comes equipped with a command line interface for performing a -number of useful operations on the Storj network. The CLI program is generally -focused on interacting with a remote [Bridge](https://github.com/Storj/bridge) -service and makes use of the library's {@link BridgeClient} class to do so. In -addition to interacting with a bridge node, the tool also exposes some general -purpose utilities. - -To use the CLI, follow the instructions in the [README](https://github.com/Storj/core/blob/master/README.md) to install the module -**globally** or if you are working from within the git repository, you can use: - -``` -npm link -``` - -### Communicating with a Bridge - -Once you have access to the `storj` command, register and authenticate with the -bridge: - -``` -> $ storj register - [...] > Enter your email address > gordon@storj.io - [...] > Enter your password > ************* - - [info] Registered! Check your email to activate your account. -``` - -Follow the activation link you receive via email and come back to the CLI to -pair with your account: - -``` -> $ storj login - [...] > Enter your email address > gordon@storj.io - [...] > Enter your password > ************* - - [info] This device has been successfully paired. -``` - -Now you can create buckets, transfer files, and manage your bridge account. - -### Audits, Proofs, and Verifications - -The CLI also includes some utility commands for generating file possession -audits, proving possession, and verifying proofs. You can generate a challenge -set and merkle tree for a file easily: - -``` -> $ storj prepare-audits 2 CONTRIBUTING.md - [info] Generating challenges and merkle tree... - [info] - [info] Merkle Root - [info] ----------- - [info] 9c8c37935f58d46e3301efe4f44724b8785a81a5 - [info] - [info] Challenges - [info] ---------- - [info] c8573773616e072230d40131e7ce8537d384825e337e5903ff7367ddea798c52 - [info] 7c4d4f57f40d5c95f962e7cd72347e4077e1885aaffd8c1ccbbd02c8d7c48dce - [info] - [info] Merkle Leaves - [info] ------------- - [info] aaf42766d87a37e6dffbae7172fd0073006bf5f3 - [info] ccee086dbc8a16b93b79912cb37f3b037bbf8269 -``` - -A farmer can use parts of this data to prove possession of a file shard: - -``` -> $ storj prove-file aaf42766d87a37e6dffbae7172fd0073006bf5f3,ccee086dbc8a16b93b79912cb37f3b037bbf8269 c8573773616e072230d40131e7ce8537d384825e337e5903ff7367ddea798c52 CONTRIBUTING.md - [info] Generating proof of possession... - [info] - [info] Challenge Response - [info] ------------------ - [info] [["153a0d4b1d228043992fec585cadb51974b053f7"],"ccee086dbc8a16b93b79912cb37f3b037bbf8269"] -``` - -The result of this operation can be used by the original renter to verify the -the proof and confirm that the farmer still has possession of the file: - -``` -> $ storj verify-proof 9c8c37935f58d46e3301efe4f44724b8785a81a5 2 '[["153a0d4b1d228043992fec585cadb51974b053f7"],"ccee086dbc8a16b93b79912cb37f3b037bbf8269"]' - [info] - [info] Expected: 9c8c37935f58d46e3301efe4f44724b8785a81a5 - [info] Actual: 9c8c37935f58d46e3301efe4f44724b8785a81a5 - [info] - [info] The proof response is valid -``` - -For more detailed usage information of the command line interface, run -`storj --help`. - -### Temporary Files -On Windows temporary files are stored: - -``` -C:\Users\\AppData\Local\Temp -``` diff --git a/Storj/core/doc/contract-topics.md b/Storj/core/doc/contract-topics.md deleted file mode 100644 index f51e870..0000000 --- a/Storj/core/doc/contract-topics.md +++ /dev/null @@ -1,130 +0,0 @@ -Nodes solicit storage contracts with the network by publishing information -about their storage requirements as outlined in {@tutorial protocol-spec}. -Storj implements a distributed publish/subscribe system based on an algorithm -called [Quasar](https://github.com/kadtools/kad-quasar). - -Quasar works by allowing nodes to advertise topics of interest to their -neighbors and keeping a record of these topics in their neighborhood by storing -them in an attenuated bloom filter. Each node has a view of the topics in which -their neighbors are interested up to 3 hops away. By the nature of this -design, the network forms gravity wells wherein messages of interest are -efficiently relayed to nodes that are subscribed to the topic without flooding -the network. - -This approach works well when there is a diverse number of topics. The Storj -protocol leverages this by defining a matrix of *criteria* and *descriptors* -in the form of opcodes representing the degree of which the criteria must be -met. - -### Criteria - -At the time of writing, there are 4 criteria column in the topic matrix: - -* Size -* Duration -* Availability -* Speed - -#### Size - -Refers to the size of the data to be stored. - -#### Duration - -Refers to the length of time for which the data should be stored. - -#### Availability - -Refers to the relative uptime of required by the contract for retrieval of the -stored data. - -#### Speed - -Refers to the throughput desired for retrieval of the stored data. - -### Descriptors - -At the time of writing, there are 3 descriptor opcodes representing *low*, -*medium*, and *high* degrees of the criteria. - -* Low: `0x01` -* Medium: `0x02` -* High: `0x03` - -The ranges represented by these descriptors are advisory and may change based -on network performance and improvements to hardware over time. - -``` -------------------------------------------------------------------------------- -| Descriptor | Size | Duration | Availability | Speed | -|-----------------|-------------|------------|--------------|-----------------| -| Low (`0x01`) | 0mb - 8mb | 0d - 30d | 0% - 50% | 0mbps - 6mbps | -|-----------------|-------------|------------|--------------|-----------------| -| Medium (`0x02`) | 8mb - 16mb | 30d - 90d | 50% - 80% | 6mbps - 12mbps | -|-----------------|-------------|------------|--------------|-----------------| -| High (`0x03`) | 16mb - 32mb | 90d - 270d | 80% - 99% | 12mbps - 32mbps | -------------------------------------------------------------------------------- -``` - -### Topic Format - -When publishing or subscribing to a given topic representing the degrees of -these criteria, nodes must serialize the opcodes as the hex representation of -the bytes in proper sequence. This sequence is defined as: - -``` -prefix|size|duration|availability|speed -``` - -The first byte, "prefix", is the **static identifier** for a contract -publication. Contracts are not the only type of publication shared in the -network, so the prefix acts as a namespace for a type of publication topic. - -**The prefix for a contract publication is:** `0x0f`. - -To illustrate by example, we can determine the proper topic by analyzing the -*use case* for a given file shard. For instance, if we want to store an asset -that is displayed on a web page we can infer the following: - -* The file is small -* The file may change often, so we should only store it for medium duration -* The file needs to always be available -* The file should be transferred quickly - -Using the matrix, we can determine the proper opcode sequence: - -``` -[0x0f, 0x01, 0x02, 0x03, 0x03] -``` - -Serialized as hex, our topic string becomes: - -``` -0f01020303 -``` - -Another example, by contrast, is data *backup*. Data backup is quite different -than the previous example: - -* The file is large (perhaps part of a hard drive backup) -* The file will not change and should be stored long term -* The file will not be accessed often, if ever -* The file does not need to be transferred at high speed - -Using the matrix, we can determine the proper opcode sequence: - -``` -[0x0f, 0x03, 0x03, 0x01, 0x01] -``` - -Serialized as hex, our topic string becomes: - -``` -0f03030101 -``` - -The resulting hex string from the serialized opcode byte sequence should be -used as the `topic` parameter of a `PUBLISH` RPC as defined in the -{@tutorial protocol-spec}. Nodes that are subscribed to the topic will receive -the proposed storage contract and may begin contract negotiation with you -directly. diff --git a/Storj/core/doc/data-transfer.md b/Storj/core/doc/data-transfer.md deleted file mode 100644 index f3cbd2a..0000000 --- a/Storj/core/doc/data-transfer.md +++ /dev/null @@ -1,29 +0,0 @@ -Transfering file shards to farmers is a simple process. After a successful -`CONSIGN` or `RETRIEVE` RPC yields a token, the renter may construct an HTTP -request to the farmer, to push or pull the data. - -#### Uploading Shards - -To upload a shard to a given farmer, construct an HTTP request: - -* Method: `POST` -* Path: `/shards/{hash}?token={token}` -* Headers: - * `content-type: application/octet-stream` - * `x-storj-node-id: {farmer node id}` - -Then simply write the encrypted shard to the request. Farmers will respond with -appropriate status codes and messages to indicate the result. - -#### Downloading Shards - -To download a shard from a given farmer, construct an HTTP request: - -* Method: `GET` -* Path: `/shards/{hash}?token={token}` -* Headers: - * `content-type: application/octet-stream` - * `x-storj-node-id: {farmer node id}` - -You will receive the shard as a response of type `application/octet-stream` if -you are authorized. diff --git a/Storj/core/doc/environment-variables.md b/Storj/core/doc/environment-variables.md deleted file mode 100644 index c4bfb81..0000000 --- a/Storj/core/doc/environment-variables.md +++ /dev/null @@ -1,39 +0,0 @@ -Below is a list of environment variables that can be used to alter the -behavior of the core library and associated tooling. - -#### `STORJ_NETWORK` - -This value will be postfixed to your announced protocol version in the network. -A value of `testnet` would advertise to the network you are running -`0.7.0-testnet`, which will isolate you to other nodes running the same exact -version. See {@tutorial private-testnet} for more information. - -#### `STORJ_ALLOW_LOOPBACK` - -By default, the {@link Network} class will drop and ignore message from nodes -who identify themeselves as a loopback interface like `localhost`, `127.0.0.1`, -etc. This is a security precaution to prevent others from causing you to send -messages to yourself as well as prevent invalid contacts in your routing table. - -To disable this feature (primarily for local testing), set this variable to `1`. - -#### `STORJ_BRIDGE` - -This variable will change the default URI for the {@link BridgeClient} class. -The default value is `https://api.storj.io`. If you run your own bridge, -testing one locally, or otherwise would like to default to a different host, -set this variable. - -This works well with the CLI (see {@tutorial command-line-interface}) when -testing against other bridges. - -#### `STORJ_KEYPASS` - -This variable will set the `--keypass` used to unlock the keyring. - -Setting your password will make it so other users can't grep it with `ps -a`. - -#### `STORJ_TEMP` - -This variable will set the folder to which the encrypted file will be placed -when uploading a file. Shards will also be placed in this folder during upload. diff --git a/Storj/core/doc/file-encryption.md b/Storj/core/doc/file-encryption.md deleted file mode 100644 index a0e80d8..0000000 --- a/Storj/core/doc/file-encryption.md +++ /dev/null @@ -1,114 +0,0 @@ -This document serves to provide a detailed account of how files are encrypted -by default by Storj Core to promote interoperability between different -implementations of clients. - -#### Sharding and Encryption Scheme - -Before data is stored in the network, the Storj Core library automatically -handles file encryption, sharding, and key management for you. - -In order of operations: - -1. Complete file is encrypted with a unique key and initialization vector -2. File is demultiplexed (or "sharded") into individual chunks -3. Each shard is offered to the network and transferred -4. Key and IV are encrypted with a passphrase and stored locally - -#### Key and Initialization Vector Generation - -Files are encrypted using [AES-256-CTR](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard). Use -of CTR allows for random read-access to known indices. File `keys` are -generated via one of two methods: - -* Local PBKDF2 key derivation (default) -* Passphrase-based deterministic key derivation (recommended) - -##### PBKDF2 Key Derivation - -By default, the `key` for each file is the result of a standard key derivation -function, [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2). PBKDF2 generates a -key from a password and a salt. These two values are randomly generated bytes: - -* Password: 512 random bytes -* Salt: 32 random bytes - -The key length of the PBKDF2 is 512 bytes, should use 25000 iterations, and use -SHA-512 as the digest. To create the cipher/decipher and initialization vector, -derive the SHA-256 hash of the resulting PBKDF2 for the cipher/decipher `key` -and use the first 16 bytes of the original salt as the `iv`. The -{@link DataCipherKeyIv} class represents these values, and provides methods for -their generation. - -The {@link KeyRing} class stores the original `password` and `salt` locally in -an encrypted JSON document keyed by the ObjectId returned from -[Storj Bridge](https://github.com/Storj/bridge) for the file object. The -cleartext JSON document has two properties: `pass` and `salt`. - -``` -{ - "pass": "c7c311ee213d10baefd620a004d76485190d82...", - "salt": "6d33490c999e9d613ccf4b146446763df15de2..." -} -``` - -This JSON string is encrypted with AES-256-CBC using a user-defined passphrase, -and encoded as [Base58](https://en.wikipedia.org/wiki/Base58). Each of those -encrypted JSON documents is stored in a directory called `key.ring/`, where the -file name is the ObjectId returned from [Storj Bridge](https://github.com/Storj/bridge) for the file object. - -###### Portable Key Ring Format - -Because the keys in the key ring are generated and stored locally, files -encrypted with these keys cannot be accessed by other machines without first -duplicating the key files onto that machine. To mitigate this, Storj Core can -create a simple portable key ring archive. - -A {@link KeyRing} created by Storj Core can be exported into a portable format, -which is simply a gzipped tape archive (`.tar.gz` or `.tgz`). Importing this -archive simply entails: - -1. Decompress and unpack the archive -2. Decrypt each JSON document using the original passphrase -3. Encrypt each document with the passphrase of the target keyring -4. Move the files into the target keyring, optionally overwriting conflicts - -##### Passphrase-based Key Derivation - -Rather than relying on locally-generated keys, it is recommended that the user -generate a high-entropy passphrase, and generate keys from it via a -deterministic key derivation process. Using this method, the user may grant -access to all encrypted files by simply transferring the passphrase. Storj Core -offers tools for this based on Bitcoin's BIP39 Mnemonic passphrases. - -{@link KeyRing} provides tools for generating a mnemonic passphrase and -writing it to disk. If a mnemonic is found, Storj Core will prefer -passphrase-based key derivation to PBKDF2 derivation. Storj clients should -create a file key as follows: - -1. Prepend the passphrase to the Bucket ID -2. Calculate the `sha512` hash of the resulting string -3. Take the first 64 bits of the resulting hash to make the **Bucket Key** -4. Prepend the Bucket Key to the File ID -5. Calculate the `sha512` hash of the resulting string -6. Take the first 64 bits of the resulting hash to make the **File Key** - -As any client with access to the passphrase can easily generate file keys on -demand, this provides additional portability of files between machines and -applications. - -It is strongly recommended that users write down the passphrase, and keep it in -a secure place. - -###### Public Bucket Key Storage - -Public Buckets are a feature of Bridge, not a feature of Storj. When a Public -Bucket is created, the Bucket Key is stored with Bridge. It is then provided to -clients requesting PUSH or PULL tokens from that bucket. - -#### References - -* {@link DataCipherKeyIv} -* {@link DeterministicKeyIV} -* {@link EncryptStream} -* {@link DecryptStream} -* {@link KeyRing} diff --git a/Storj/core/doc/index.json b/Storj/core/doc/index.json deleted file mode 100644 index c55cabd..0000000 --- a/Storj/core/doc/index.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "protocol-spec": { - "title": "Protocol Specification" - }, - "data-transfer": { - "title": "Transferring File Shards" - }, - "contract-topics": { - "title": "Publishing Storage Contracts" - }, - "private-testnet": { - "title": "Running a Test Network" - }, - "tunnel-connections": { - "title": "Tunnelling Connections" - }, - "renting-data": { - "title": "Renting Data to the Network" - }, - "command-line-interface": { - "title": "Using the Command Line Tools" - }, - "environment-variables": { - "title": "Environment Variables" - }, - "file-encryption": { - "title": "File Encryption Standards" - } -} diff --git a/Storj/core/doc/private-testnet.md b/Storj/core/doc/private-testnet.md deleted file mode 100644 index 4539da0..0000000 --- a/Storj/core/doc/private-testnet.md +++ /dev/null @@ -1,70 +0,0 @@ -Setting up a private or partitioned version of the Storj network is very simple. -The Storj protocol requires the inclusion of a `protocol` property nested -inside the `contact` data included in every RPC message. See -{@tutorial protocol-spec} for more information on the RPC message format. - -### Protocol Identifier Format - -Nodes on the Storj network identify the version of the protocol they are -running with the use of a [semantic version](http://semver.org/) tag. When a -node is trying to determine whether or not another node is compatible with her -version of the protocol, she checks the following: - -* Is the `MAJOR` version the same? -* Is the `MAJOR` version `0`? -* Is the `MINOR` version the same? - -If both nodes are running the *same* `MAJOR` version and that version is -**not** `0`, then the nodes are compatible. If the `MAJOR` version **is** `0`, -then the nodes are compatible *only* if the `MINOR` version is the same. - -For example: - -* `0.5.1` **is** compatible with `0.5.3` -* `0.5.1` **is not** compatible with `0.6.0` -* `1.5.1` **is** compatible with `1.13.0` -* `2.1.0` **is not** compatible with `1.13.0` - -### Special Identifiers - -The semantic versions specification also allows for special identifiers by -postfixing the version with a hyphen followed by some identifier. This is where -the network partitioning magic happens. - -Let's say, for example, I work for "Widgets Ltd" and I want to deploy a Storj -network within the Widgets Ltd private network. Every workstation would run a -modified version of [`storj/farmer`](https://github.com/storj/farmer) or maybe -my own custom interface built atop `storj/core`. - -I would simply change my Storj-based software to use the version -`1.5.0-widgetsltd`. The Storj protocol sees this identifies as a *strict* match -and therefore any nodes running this version of the software will only -communicate with nodes running the **exact** protocol identifier. - -### Changing the Version - -Changing the version in `storj/core` is easy as pie. In your code, simply -import the module and change the identifier like so: - -``` -// Import core library -var storj = require('storj'); - -// Modify protocol version -storj.version.protocol = '1.5.0-widgetsltd'; - -// Get on with your stuff... -``` - -If you are running "vanilla" Storj software, you can change the protocol -version by setting the `STORJ_NETWORK` environment variable. This will add a -postfix to the protocol version, which will partition the network to nodes -that are running that *exact* version: - -``` -STORJ_NETWORK=testnet storjshare --datadir /path/to/shards -``` - -This concept applies broadly to deploying a custom Storj network for any -purpose. This could be used for a public testnet (`x.x.x-testnet`) or for the -private network example above. diff --git a/Storj/core/doc/renting-data.md b/Storj/core/doc/renting-data.md deleted file mode 100644 index fd1662d..0000000 --- a/Storj/core/doc/renting-data.md +++ /dev/null @@ -1,302 +0,0 @@ -This tutorial covers the process for using StorjCORE to rent data to farmers on -the network programmatically using a number of tools included in the library. -This walkthrough should also serve as an overview for a number of the tools -included in the library and how they work together. - -### Bootstrapping - -Before we can join the network, we need to set up a few required components: - -* {@link KeyPair} - for representing our identity on the network -* {@link StorageAdapter} - for persisting our contracts and shard metadata -* {@link StorageManager} - for managing our persistence layer - -Start by importing the `storj` module and instantiating these objects: - -``` -var storj = require('storj'); -var keypair = new storj.KeyPair(); -var persistence = new storj.EmbeddedStorageAdapter('/path/to/datadir'); -var manager = new storj.StorageManager(persistence); -``` - -Now that we have a way of identifying ourselves to the network and keeping a -record of our contracts, we can use the {@link RenterInterface} to join the -network. - -``` -var renter = new storj.RenterInterface({ - keyPair: keypair, - storageManager: manager, - rpcAddress: 'ip.or.hostname', - rpcPort: 1337 -}); - -renter.join(function(err) { - if (err) { - return console.error('Failed to join the network'); - } - - // CONTINUED IN NEXT EXAMPLE... -}); -``` - -### File Preparation - -Now that we have a connection to the network, we are ready to store some data. -Before we can actually store the data, we need to get some information about -the shards we need to store. We need to know: - -* The hash of each shard that will be stored -* The size of each shard that will be stored -* The length of time we wish to store the data -* The number of audits we intend to issue over the life of the contract - -To get this information we need to process the file using a few more of the -core components: - -* {@link FileDemuxer} - for breaking the file into shards -* {@link DataCipherKeyIv} - for generating encryption key -* {@link EncryptStream} - for encrypting the shards -* {@link Contract} - for constructing the terms of the storage - -We will start by demultiplexing the file into several shard streams. Let's -break our file into 6 shards. We will start by creating a {@link FileDemuxer}: - -``` -var demuxer = new storj.FileDemuxer('/path/to/file'); -``` - -Now that we have prepared to shard a file, we need to set up event listeners on -the demuxer for whenever a new shard stream is available. Once a shard stream -is available, we need to encrypt it and calculate it's hash and size so we can -create an appropriate {@link Contract} to offer the network. In addition we -will write the encrypted shard to temporary storage so we don't have to process -the file again when we are ready to transfer the data: - -``` -var tmpdir = require('os').tmpdir(); -var crypto = require('crypto'); -var path = require('path'); - -demuxer.on('shard', function(shardStream) { - var tmpName = path.join(tmpdir, crypto.randomBytes(6).toString('hex')); - var tmpFile = fs.createWriteStream(tmpName); - var key = new storj.DataCipherKeyIv('password', 'salt'); - var encrypter = new storj.EncryptStream(key); - var hasher = crypto.createHash('sha256'); - var size = 0; - - encrypter.on('data', function(bytes) { - hasher.update(bytes); - size += bytes.length; - }); - - tmpFile.on('finish', function() { - // CONTINUED IN NEXT EXAMPLE... - }); - - shardStream.pipe(encrypter).pipe(tmpFile); -}); -``` - -### Contract Negotiation - -When each shard is finished being encrypted and we know it's size and hash, it -is time to create a {@link Contract} and offer it to the network. The example -below is continued from inside the `tmpFile.on('finish', callback)` in the -example above: - -``` -var hash = utils.rmd160sha256(hasher.digest()); -var contract = new storj.Contract({ - renter_id: keypair.getNodeID(), - data_size: size, - data_hash: hash, - store_begin: Date.now(), - store_end: Date.now() + 604800000, // 7 days from now - audit_count: 12 -}); - -renter.getStorageOffer(contract, function(err, farmer, contract) { - // CONTINUED IN NEXT EXAMPLE... -}); -``` - -Now we have created a {@link Contract} for the shard and we are waiting for an -offer from a farmer on the network. When we receive one, the callback supplied -to {@link RenterInterface#getStorageOffer} above will trigger and we can -proceed to transfer the shard to the farmer, but first we need to tell the -farmer we are ready to transfer the shard to them and include the audit -information they will need in the future. We will be using: - -* {@link AuditStream} - for generating audit challenges and merkle tree -* {@link StorageItem} - for storing our private record of challenges - -Let's continue by reading the encrypted shard temporary file we just created -and generating the challenges and merkle tree and saving a copy of the contract -and associated challenges: - -``` -var item = new storj.StorageItem({ hash: hash }); -var auditGenerator = new storj.AuditStream(12); -var encryptedShard = fs.createReadStream(tmpName); - -auditGenerator.on('finish', function() { - item.addContract(farmer, contract); - item.addAuditRecords(farmer, auditGenerator); - - manager.save(item, function(err) { - if (err) { - return console.error(err); - } - - // CONTINUED IN NEXT EXAMPLE... - }); -}); - -encryptedShard.pipe(auditGenerator); -``` - -### Transferring Shards - -Now that we have stored a copy of our contract and challenges, it's time to -authorize a "data channel" (as described in {@tutorial data-channels}) and -transfer the shard to the farmer. - -``` -renter.getConsignToken(farmer, contract, auditGenerator, function(err, token) { - if (err) { - return console.error(err); - } - - var upload = storj.utils.createShardUploader(farmer, hash, token); - var encryptedShard = fs.createReadStream(tmpName); - - encryptedShard.pipe(upload).on('end', () => { - // CONTINUED IN THE NEXT EXAMPLE - }); -}); -``` - -Remember that these operations for contract negotiation and shard transfer are -taking place for **each** shard in the original file. You'll want to keep track -of shards and their associated contracts by grouping references to them -logically as the **file** that they compose. This is the responsibility of -implementing clients. If you do not wish to manage this yourself, consider -running a [Bridge](https://github.com/storj/bridge) or using the -[Storj API](https://storj.io). - -### Replicating Shards for Redundancy - -Once we have successfully consigned our data to a farmer, we can ensure that in -the event that farmer disappears, our data can be recovered from elsewhere. We -use mirrors to accomplish this. Mirroring is a method for *passively* -replicating our data, meaning that instead of uploading it again, we instruct a -new farmer to retrieve it from the location we already stored it. - - -> We are also going to use the [async](https://github.com/caolan/async) module -> for managing flow control. - -First we'll need to negotiate a few more contracts, then authorize some -retrieval tokens (outlined later in this document), and finally request some -mirrors. - -``` -var redundancy = 3; -var mirrors = []; - -function _getMirroringContract(n, next) { - renter.getStorageOffer(contract, function(err, mirror, contract) { - renter.getRetrieveToken(farmer, contract, function(err, token) { - if (err) { - return next(err); - } - - mirrors.push(mirror); - next(null, { farmer: farmer, hash: hash, token: token }); - }); - }); -} - -async.timesSeries(redundancy, _getMirroringContract, function(err, sources) { - if (err) { - return console.error(err); - } - - renter.getMirrorNodes(sources, mirrors, function(err, completed) { - if (err) { - return console.error('Failed to replicate to all mirrors'); - } - - console.info('Replicated to %s mirrors', completed.length); - }); -}); -``` - -### Auditing Farmer Storage - -Now that we have successfully consigned a shard, we will want to be sure that -the farmer is being honest about storing it. We can verify this by requesting -a proof using the challenges we generated previously. We will be using: - -* {@link Verification} - for validating the farmer's challenge response - -``` -var merkleRoot = auditGenerator.getPrivateRecord().root; -var treeDepth = auditGenerator.getPrivateRecord().depth; - -renter.getStorageProof(farmer, item, function(err, proof) { - if (err) { - return console.error(err); - } - - var verification = new storj.Verification(proof); - var verifyResult = verification.verify(merkleRoot, treeDepth); - - if (verifyResult[0] !== verifyResult[1]) { - return console.error('The proof is not valid'); - } - - manager.save(item, function(err) { - if (err) { - return console.error(err); - } - - // CONTINUED IN NEXT EXAMPLE - }); -}); -``` - -### Retrieving Shards - -Now that we have verified that the farmer is storing the shard, we know that we -can later retrieve it when needed. The process for doing this is very similar -to the process for storing the shard, only this time we'll be asking for a -retrieval token and we will be receiving data over the data channel instead of -sending. We'll also be using: - -* {@link DecryptStream} - for decrypting the shard stream - -``` -renter.getRetrieveToken(farmer, contract, function(err, token) { - if (err) { - return console.error(err); - } - - var download = utils.createShardDownloader(farmer, hash, token); - var decrypter = new storj.DecryptStream(keypair); - var fileDestination = fs.createWriteStream('/path/to/download/shard'); - - download.pipe(decrypter).pipe(fileDestination); - - fileDestination.on('finish', function() { - console.info('Successfully downloaded shard!'); - }); -}); -``` - -This concludes the tutorial. To dive deeper, follow the reference links -throughout this walkthrough and read the documentation on each of the classes -used here. diff --git a/Storj/core/doc/tunnel-connections.md b/Storj/core/doc/tunnel-connections.md deleted file mode 100644 index 08ca0cc..0000000 --- a/Storj/core/doc/tunnel-connections.md +++ /dev/null @@ -1,114 +0,0 @@ -One of the most daunting problems to tackle when designing a stable and -reliable distributed network is the traversal of various constraints such as -NAT and firewalls. In some cases, software can use various strategies to -"punch out" of these constraints and become publicly addressable on the -Internet. The StorjCORE library makes use of these strategies, but when they -fail we must devise more complex tactics for ensuring that network participants -are reachable by their peers. - -The Storj protocol defines a series of RPC messages that can be exchanged -in order to establish a "tunnel". See the {@tutorial protocol-spec} for more -detail on these RPC messages and their purposes. A tunnel is, in essence, a -proxy that allows a client that is not exposed to the Internet to be -addressable as if it were. - -This works by a private node opening a long-lived connection to a public node -who establishes a dedicated means for accepting messages on behalf of the -private node and "pipes" any data received via those means directly back to the -private node over the previously established connection. - -Once a tunnel has been established, the private node can begin identifying -herself to the network using her tunnel's address, instead of her own. Private -nodes do not need to use the tunnel to contact other nodes on the network, but -rather only *to be contacted*. - -### Announcing Willingness - -When a node joins the network and is publicly addressable, it has the ability -to announce to the network that it is willing and capable of tunneling -connections on behalf on nodes who are private or unable to punch out to -become addressable on the Internet. The process of doing this uses the same -publish/subscribe system described in the {@tutorial contract-topics} -specification which enables nodes to maintain a view of subscriptions in their -neighborhood of the network as described in the {@tutorial protocol-spec}. - -The difference between a contract publication and a tunnel announcement is in -the opcode used for the topic and in the contents of the publication. Tunnel -announcement publications use the opcode prefix `0x0e` followed by a single -criteria degree opcode to indicate their willingness to tunnel (`0x00` to -indicate "I am no longer tunneling" and `0x01` to indicate "I am ready to -tunnel"). - -Whenever the condition changes, such as a node's maximum number of tunnels is -reached or when a tunnel becomes available, it should issue a `PUBLISH` RPC -message to it's nearest neighbors. - -``` -{ - "method": "PUBLISH", - "params": { - "uuid": "7f0c40a2-e465-4f3e-b617-3d53460e34f7", - "topic": "0e01", - "contents": { - "address": "10.0.0.2", - "port": 1337 - }, - "publishers": [ - "48dc026fa01ae26822bfb23f98e725444d6775b0" - ], - "ttl": 1455228597837, - "contact": { - "address": "10.0.0.2", - "port": 1337, - "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0", - "protocol": "0.6.0" - }, - "nonce": 1455216323786, - "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..." - }, - "id": "7b6a2ab35da6826995abf3310a4875097df88cdb" -} -``` - -Public nodes should subscribe to these topics so that they can maintain an -up-to-date list of nodes who are capable and willing to tunnel connections, so -they can respond accurately to `FIND_TUNNEL` messages from private nodes. - -### Establishing a Tunnel - -After a private node has discovered some willing tunnels using the `FIND_TUNNEL` -RPC message defined in the {@tutorial protocol-spec}, it can now begin the -handshake to establish the tunnel. This begins by sending the `OPEN_TUNNEL` RPC -message to the desired tunneler node. The recipient of `OPEN_TUNNEL` will -check: - -* Do I have enough remaining tunnels? (based on arbitrary limit set by node) -* Am I already tunneling for this nodeID? -* Has a payment channel been opened? (**future spec**) - -If the tunneling node has enough tunnels, is not already tunneling the node, -and (in a future spec) if a payment channel has been opened for bandwidth, then -the tunneling node opens a new dedicated TCP socket on an available port -that will be used by the requester to send/receive HTTP messages. - -``` -{ - "result": { - "proxyPort": 12000, - "contact": { - "address": "10.0.0.3", - "port": 1337, - "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0", - "protocol": "0.6.0" - }, - "nonce": 1455216323786, - "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..." - }, - "id": "7b6a2ab35da6826995abf3310a4875097df88cdb" -} -``` - -Now the private node can open a TCP connect to the `proxyPort` provided and -messages sent to the tunneler that specify your node ID in the -`x-storj-node-id` header will be written to the connected socket. From there, -you may pipe this socket directly to your locally running node. diff --git a/Storj/core/docs/AuditStream.html b/Storj/core/docs/AuditStream.html deleted file mode 100644 index 4220d87..0000000 --- a/Storj/core/docs/AuditStream.html +++ /dev/null @@ -1,721 +0,0 @@ - - - - - JSDoc: Class: AuditStream - - - - - - - - - - -
- -

Class: AuditStream

- - - - - - -
- -
- -

AuditStream(audits)

- - -
- -
-
- - - - - - -

new AuditStream(audits)

- - - - - - -
- Represents a streaming audit challenge generator -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
audits - - -Number - - - - Total number of challenges to generate
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - -
Fires:
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

(static) fromRecords(challenges, tree) → {AuditStream}

- - - - - - -
- Returns a new instance from the predefined challenges and tree -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
challenges - - -Array - - - - The precomputed challenges
tree - - -Array - - - - The bottom leaves of the existing merkle tree
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -AuditStream - - -
-
- - - - - - - - - - - - - -

getPrivateRecord() → {Object}

- - - - - - -
- Returns the challenges, the tree depth, and merkle root -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- challenge - Private audit record with challenges -
- - - -
-
- Type -
-
- -Object - - -
-
- - - - - - - - - - - - - -

getPublicRecord() → {Array}

- - - - - - -
- Returns the bottom leaves of the merkle tree for sending to farmer -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- leaves - Bottom merkle leaves of audit tree -
- - - -
-
- Type -
-
- -Array - - -
-
- - - - - - - - - - - - - -

Events

- - - - - - - -

finish

- - - - - - -
- Triggered when the stream has ended -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/Blacklist.html b/Storj/core/docs/Blacklist.html deleted file mode 100644 index 2ceb0ab..0000000 --- a/Storj/core/docs/Blacklist.html +++ /dev/null @@ -1,484 +0,0 @@ - - - - - JSDoc: Class: Blacklist - - - - - - - - - - -
- -

Class: Blacklist

- - - - - - -
- -
- -

Blacklist()

- - -
- -
-
- - - - - - -

new Blacklist()

- - - - - - -
- Manage a blacklist file containing an object with key value pairs of -nodeids: timestamp -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options.logger - - -Object - - - - Logger instance
options.store - - -Object - - - - The store that blacklist enteries will be -persisted to. This object must be compatible with the API of -abstract-blob-store
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - -
See:
-
- -
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

push(nodeid)

- - - - - - -
- Push node to blacklist -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
nodeid - - -String - - - - Node id to be added to blacklist
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

toObject()

- - - - - - -
- Return list of blacklisted nodeids -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/BridgeClient.html b/Storj/core/docs/BridgeClient.html deleted file mode 100644 index ecab708..0000000 --- a/Storj/core/docs/BridgeClient.html +++ /dev/null @@ -1,6926 +0,0 @@ - - - - - JSDoc: Class: BridgeClient - - - - - - - - - - -
- -

Class: BridgeClient

- - - - - - -
- -
- -

BridgeClient(uriopt, options)

- - -
- -
-
- - - - - - -

new BridgeClient(uriopt, options)

- - - - - - -
- Represents a client interface to a given bridge server -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDefaultDescription
uri - - -String - - - - - - <optional>
- - - - - -
- - https://api.storj.io - - API base URI
options - - -Object - - - - - - - - - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
keyPair - - -KeyPair - - - - - - - - - - KeyPair instance for request signing
logger - - -Object - - - - - - - - - - Logger instance
requestTimeout - - -Object - - - - - - - - - - Timeout when making requests to the -bridge
transferConcurrency - - -Number - - - - - - - - - - Upload concurrency limit
transferRetries - - -Number - - - - - - - - - - Limit number of shard transfer -retries before getting a new contract
basicAuth - - -Object - - - - - - - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
email - - -String - - - - Email address for HTTP basic auth
password - - -String - - - - Password for HTTP basic auth
- -
blacklistFolder - - -String - - - - - - <optional>
- - - - - -
The folder that blacklist -entries will be persisted to if using the default fs-store
store - - -Object - - - - - - <optional>
- - - - - -
The store that blacklist enteries will be -persisted to. This object must be compatible with the API of -abstract-blob-store
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - -
See:
-
- -
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

_shardUploadWorker(task, done)

- - - - - - -
- BridgeClient.prototype._shardUploadWorker - description -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
task - - -type - - - - description
done - - -type - - - - description
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

addPublicKey(pubkey, callback)

- - - - - - -
- Registers a public key for the caller -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
pubkey - - -String - - - - Hex encoded ECDSA (secp256k1) public key
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

addShardToFileStagingFrame(id, shard, options, callback)

- - - - - - -
- Adds the given shard metadata to the file staging frame -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique frame ID
shard - - -Object - - - - The shard metadata
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
retry - - -Number - - - - Retry the request this many times if failed
- -
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

createBucket(data, callback)

- - - - - - -
- Creates a new file bucket -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
data - - -Object - - - - Bucket parameters for creation
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

createExchangeReport(exchangeReport)

- - - - - - -
- Sends an exchange report -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
exchangeReport - - -ExchangeReport - - - - The result of a transfer operation
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

createFileSliceStream(options)

- - - - - - -
- Create a stream for a given slice of a file -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bucket - - -String - - - - The bucket ID
file - - -String - - - - The file ID
start - - -Number - - - - The byte position to start slice
end - - -Number - - - - The byte position to end slice
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

createFileStagingFrame(callback)

- - - - - - -
- Creates a file staging frame -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

createFileStream(bucket, file, optionsopt, callback)

- - - - - - -
- Create a readable stream from the given bucket and file id -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
bucket - - -String - - - - - - - - - - The unique bucket ID
file - - -String - - - - - - - - - - The unique file ID
options - - -Object - - - - - - <optional>
- - - - - -
-
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
exlude - - -Array - - - - - - <optional>
- - - - - -
Exclude these nodeID's from pointers
- -
callback - - -function - - - - - - - - - - Receives (err, stream)
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

createToken(id, operation, callback)

- - - - - - -
- Create bucket token -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique bucket ID
operation - - -String - - - - PUSH or PULL (file operation)
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

createUser(options, callback)

- - - - - - -
- Registers a user account -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
email - - -String - - - - Email address for verification email
password - - -String - - - - Password to register (auto hashed)
redirect - - -String - - - - URL to redirect to after verification
pubkey - - -String - - - - Optional ECDSA public key to register
- -
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

destroyBucketById(id, callback)

- - - - - - -
- Removes the bucket -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique bucket ID
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

destroyFileStagingFrameById(id, callback)

- - - - - - -
- Destroy an existing file staging frame -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique frame ID
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

destroyPublicKey(pubkey, callback)

- - - - - - -
- Disassociates the public key from the caller -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
pubkey - - -String - - - - Hex encoded ECDSA (secp256k1) public key
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

destroyUser(options, callback)

- - - - - - -
- Deactivates a user account -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
email - - -String - - - - Email address of user to deactivate
redirect - - -String - - - - URL to redirect after verification
- -
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getBucketById(id, callback)

- - - - - - -
- Returns the bucket information by ID -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique bucket ID
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getBuckets(callback)

- - - - - - -
- Lists the caller's file buckets -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getContactByNodeId(nodeId, callback)

- - - - - - -
- Get the contact information for the given nodeID -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
nodeId - - -String - - - - The nodeID of the contact
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getContactList(options, callback)

- - - - - - -
- Fetches the list of known contacts filtered according to the options -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
page - - -Number - - - - The page number of the contact list to fetch
connected - - -Boolean - - - - Filter results by connection status
- -
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getFileInfo(bucket, file, callback)

- - - - - - -
- Get info about a file (bucket, mimetype, filename, frame, size, id) -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bucket - - -String - - - - bucket id
file - - -String - - - - file id
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getFilePointers(options, callback)

- - - - - - -
- Retrieves a series of file pointers from the bucket -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bucket - - -String - - - - Unique bucket ID
token - - -String - - - - Token from BridgeClient#createToken
file - - -String - - - - The unique file pointer ID
skip - - -Number - - - - The starting index of pointers to resolve
limit - - -Number - - - - The number of pointers to resolve
- -
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getFileStagingFrameById(id, callback)

- - - - - - -
- Fetch an existing file staging frame by it's ID -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique frame ID
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getFileStagingFrames(callback)

- - - - - - -
- List all of the file staging frames -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getFrameFromFile(bucket, file, callback)

- - - - - - -
- Gets the frame by it's ID -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bucket - - -String - - - - Unique bucket ID
file - - -String - - - - Unique file ID
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getInfo(callback)

- - - - - - -
- Get the remote Storj Bridge API documentation and version as JSON -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getPublicKeys(callback)

- - - - - - -
- Returns list of associated public keys -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

listFilesInBucket(id, callback)

- - - - - - -
- Lists the files stored in a bucket -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique bucket ID
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

listMirrorsForFile(id, file, callback)

- - - - - - -
- Returns the established and available mirrors for a given file -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique bucket ID
file - - -String - - - - Unique file ID
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

removeFileFromBucket(id, file, callback)

- - - - - - -
- Removes a file from a bucket -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique bucket ID
file - - -String - - - - ID of the file to remove from bucket
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

replicateFileFromBucket(id, token, file, concurrency, callback)

- - - - - - -
- Instructs the bridge to find N mirroring farmers for redundancy -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique bucket ID
token - - -String - - - - Token from BridgeClient#createToken
file - - -String - - - - Path to file to store
concurrency - - -Number - - - - Upload concurrency
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

resetPassword(options, callback)

- - - - - - -
- Requests a password reset -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
email - - -String - - - - Email address of user to reset password
password - - -String - - - - The cleartext password to reset to
redirect - - -String - - - - URL to redirect adter confirmation
- -
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

resolveFileFromPointers(pointers, muxerOptionsopt, callback)

- - - - - - -
- Open a series of shard transfers based on the returned value of -BridgeClient#getFilePointers to resolve all the shards and -reassemble them together as a binary stream -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
pointers - - -Array - - - - - - - - - - Result of BridgeClient#getFilePointers
muxerOptions - - -Object - - - - - - <optional>
- - - - - -
Optional overrides for the file muxer
callback - - -function - - - - - - - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

storeFileInBucket(id, token, file, callback)

- - - - - - -
- Stores a file in the bucket -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique bucket ID
token - - -String - - - - Token from BridgeClient#createToken
file - - -String - - - - Path to file to store
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

updateBucketById(id, updates, callback)

- - - - - - -
- Updates the bucket -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Unique bucket ID
updates - - -Object - - - - Bucket update parameters
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/Contact.html b/Storj/core/docs/Contact.html deleted file mode 100644 index f94a123..0000000 --- a/Storj/core/docs/Contact.html +++ /dev/null @@ -1,632 +0,0 @@ - - - - - JSDoc: Class: Contact - - - - - - - - - - -
- -

Class: Contact

- - - - - - -
- -
- -

Contact(contact)

- - -
- -
-
- - - - - - -

new Contact(contact)

- - - - - - -
- Represents a Storj contact (or peer) -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
address - - -String - - - - - - - - - - Hostname of IP address
port - - -Number - - - - - - - - - - RPC port number
nodeID - - -String - - - - - - - - - - 160 bit node ID (hex)
hdKey - - -String - - - - - - <optional>
- - - - - -
extended hd public key
hdIndex - - -String - - - - - - <optional>
- - - - - -
derivation index for node
userAgent - - -String - - - - - - <optional>
- - - - - -
User agent identifier
protocol - - -String - - - - - - - - - - Semver tag for compatibility
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

(static) isValidUrl(uri) → {Boolean}

- - - - - - -
- Indicates if URL is valid contact -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
uri - - -String - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/Contract.html b/Storj/core/docs/Contract.html deleted file mode 100644 index 4533c9f..0000000 --- a/Storj/core/docs/Contract.html +++ /dev/null @@ -1,4264 +0,0 @@ - - - - - JSDoc: Class: Contract - - - - - - - - - - -
- -

Class: Contract

- - - - - - -
- -
- -

Contract(contract, criteria)

- - -
- -
-
- - - - - - -

new Contract(contract, criteria)

- - - - - - -
- Represents a storage contract between a renter and a farmer -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contract - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
type - - -String - - - - - - - - - - Unique identifier for the contract
renter_hd_key - - -String - - - - - - <optional>
- - - - - -
Node extended public key in base58
renter_hd_index - - -Number - - - - - - <optional>
- - - - - -
Derivation index for signature
renter_id - - -String - - - - - - - - - - Node ID of the renter
renter_signature - - -String - - - - - - - - - - Renter's cryptographic signature
farmer_id - - -String - - - - - - - - - - Node ID of the farmer
farmer_signature - - -String - - - - - - - - - - Farmer's cryptographic signature
data_size - - -Number - - - - - - - - - - Number of bytes to store
data_hash - - -String - - - - - - - - - - RIPEMD-160 SHA-256 hash of the data
store_begin - - -Number - - - - - - - - - - UNIX timestamp to start contract
store_end - - -Number - - - - - - - - - - UNIX timestamp to end the contract
audit_count - - -Number - - - - - - - - - - Number of audits renter will perform
payment_storage_price - - -Number - - - - - - - - - - Total price for storage
payment_download_price - - -Number - - - - - - - - - - Price per download
payment_destination - - -String - - - - - - - - - - Bitcoin address to send funds
- -
criteria - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
size - - -Number - - - - Criteria degree OPCODE
duration - - -Number - - - - Criteria degree OPCODE
availability - - -Number - - - - Criteria degree OPCODE
speed - - -Number - - - - Criteria degree OPCODE
- -
- - - - - - -
- - -
Version:
-
  • 0
- - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - -

Members

- - - -

(static) CRITERIA

- - - - -
- Defines some default criteria of a Contract -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) DEFAULTS

- - - - -
- Defines some default properties of a Contract -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) MATRIX

- - - - -
- Defines the criteria matrix for a Contract -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) Schema

- - - - -
- Defines the JSON Schema of a Contract -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - -

Methods

- - - - - - - -

(static) compare(c1, c2) → {Boolean}

- - - - - - -
- Compares two contracts against each other -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
c1 - - -Contract - - - - Contract to compare
c2 - - -Contract - - - - Contract to compare
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

(static) createTopic(criteria) → {Buffer}

- - - - - - -
- Create a topical OPCODE byte sequence from the provided criteria -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
criteria - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
size - - -Number - - - - Criteria degree OPCODE
duration - - -Number - - - - Criteria degree OPCODE
availability - - -Number - - - - Criteria degree OPCODE
speed - - -Number - - - - Criteria degree OPCODE
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Buffer - - -
-
- - - - - - - - - - - - - -

(static) diff(c1, c2) → {Array.<String>}

- - - - - - -
- Returns the property names between two contracts that differ -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
c1 - - -Contract - - - - Contract to compare
c2 - - -contract - - - - Contract to compare
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- changedProperties -
- - - -
-
- Type -
-
- -Array.<String> - - -
-
- - - - - - - - - - - - - -

(static) fromBuffer(buffer) → {Contract}

- - - - - - -
- Creates a contract from a Buffer -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
buffer - - -Buffer - - - - Raw binary blob of contract data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Contract - - -
-
- - - - - - - - - - - - - -

(static) fromJSON(json) → {Contract}

- - - - - - -
- Creates a contract from a JSON string -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
json - - -String - - - - JSON encoded contract
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Contract - - -
-
- - - - - - - - - - - - - -

(static) fromObject(object) → {Contract}

- - - - - - -
- Creates a contract from a plain object -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
object - - -Object - - - - Dictionary of contract data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Contract - - -
-
- - - - - - - - - - - - - -

get(field_name) → {String|Number|null}

- - - - - - -
- Returns the value for the given contract property -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
field_name - - -String - - - - Contract property to get
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- value -
- - - -
-
- Type -
-
- -String -| - -Number -| - -null - - -
-
- - - - - - - - - - - - - -

getHash() → {Buffer}

- - - - - - -
- Calculates the SHA-256 hash of the serialized contract -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Buffer - - -
-
- - - - - - - - - - - - - -

getSigningData() → {String}

- - - - - - -
- Returns the string representation of the contract, minus the signature -fields, sorted alphanumerically for signing and verifying -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

getTopicBuffer() → {Buffer}

- - - - - - -
- Return OPCODE byte sequence for contract publication topic -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Buffer - - -
-
- - - - - - - - - - - - - -

getTopicString() → {String}

- - - - - - -
- Return OPCODE byte sequence for contract publication topic as hex string -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

isComplete() → {Boolean}

- - - - - - -
- Checks if the contract is complete -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- completed -
- - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

set(field_name) → {String|Number|null}

- - - - - - -
- Sets the contract property to the given value -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
field_name - - -String - - - - Contract property to get
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- value -
- - - -
-
- Type -
-
- -String -| - -Number -| - -null - - -
-
- - - - - - - - - - - - - -

sign(actor, secret) → {String}

- - - - - - -
- Signs the contract as the given actor -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
actor - - -String - - - - One of 'farmer' or 'renter'
secret - - -Buffer - - - - ECDSA private key
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- signature -
- - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

signExternal(secret) → {String}

- - - - - - -
- Signs the contract with the proved key and returns the signature -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
secret - - -String - - - - ECDSA private key
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- externalSignature -
- - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

toBuffer() → {Buffer}

- - - - - - -
- Converts the contract to Buffer -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Buffer - - -
-
- - - - - - - - - - - - - -

toJSON() → {String}

- - - - - - -
- Converts the contract to JSON string -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

toObject() → {Object}

- - - - - - -
- Converts the contract to a plain object -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Object - - -
-
- - - - - - - - - - - - - -

update(fields) → {Contract}

- - - - - - -
- Applies the provided fields to the contract and validates it -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
fields - - -Object - - - - Contract properties to update
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- self -
- - - -
-
- Type -
-
- -Contract - - -
-
- - - - - - - - - - - - - -

verify(actor, pubkeyhash) → {Boolean}

- - - - - - -
- Verify the contract signature for the given actor -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
actor - - -String - - - - One of 'farmer' or 'renter'
pubkeyhash - - -Buffer - - - - ECDSA nodeID
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- isValidSignature -
- - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

verifyExternal(signature, pubkeyhash) → {Boolean}

- - - - - - -
- Verify the provided signature for the contract -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
signature - - -String - - - - The contract signature to verify
pubkeyhash - - -String - - - - ECDSA nodeID
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- isValidSignature -
- - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/DataCipherKeyIv.html b/Storj/core/docs/DataCipherKeyIv.html deleted file mode 100644 index f5524ae..0000000 --- a/Storj/core/docs/DataCipherKeyIv.html +++ /dev/null @@ -1,722 +0,0 @@ - - - - - JSDoc: Class: DataCipherKeyIv - - - - - - - - - - -
- -

Class: DataCipherKeyIv

- - - - - - -
- -
- -

DataCipherKeyIv(passwordopt, saltopt)

- - -
- -
-
- - - - - - -

new DataCipherKeyIv(passwordopt, saltopt)

- - - - - - -
- Create a new random cipher key and initialization vector -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
password - - -String -| - -Buffer - - - - - - <optional>
- - - - - -
The unique cipher password
salt - - -String -| - -Buffer - - - - - - <optional>
- - - - - -
The unique salt
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

(static) fromObject(object) → {DataCipherKeyIv}

- - - - - - -
- Returns the a DataCipherKeyIv from an object -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
object - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
pass - - -Buffer -| - -String - - - - The unique password
salt - - -Buffer -| - -String - - - - The unique salt
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -DataCipherKeyIv - - -
-
- - - - - - - - - - - - - -

getCipherKeyIv() → {Array}

- - - - - - -
- Returns the cipher key and iv in an array -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Array - - -
-
- - - - - - - - - - - - - -

toObject() → {Array}

- - - - - - -
- Returns the key and iv as an array -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Array - - -
-
- - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/DecryptStream.html b/Storj/core/docs/DecryptStream.html deleted file mode 100644 index 2e0e1ca..0000000 --- a/Storj/core/docs/DecryptStream.html +++ /dev/null @@ -1,424 +0,0 @@ - - - - - JSDoc: Class: DecryptStream - - - - - - - - - - -
- -

Class: DecryptStream

- - - - - - -
- -
- -

DecryptStream(keyiv)

- - -
- -
-
- - - - - - -

new DecryptStream(keyiv)

- - - - - - -
- Represents a duplex stream capable of taking encrypted data as input and -producing output decrypted by a DataCipherKeyIv -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
keyiv - - -DataCipherKeyIv -| - -DeterministicKeyIv - - - - Object to use -for derivation function
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - -
Fires:
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

data

- - - - - - -
- Triggered when some input bytes have become decrypted output bytes -
- - - - - -
Type:
-
    -
  • - -Buffer - - -
  • -
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

end

- - - - - - -
- Triggered when the stream has ended -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/DeterministicKeyIv.html b/Storj/core/docs/DeterministicKeyIv.html deleted file mode 100644 index 9c28887..0000000 --- a/Storj/core/docs/DeterministicKeyIv.html +++ /dev/null @@ -1,878 +0,0 @@ - - - - - JSDoc: Class: DeterministicKeyIv - - - - - - - - - - -
- -

Class: DeterministicKeyIv

- - - - - - -
- -
- -

DeterministicKeyIv(fileKey, fileId)

- - -
- -
-
- - - - - - -

new DeterministicKeyIv(fileKey, fileId)

- - - - - - -
- Create a new deterministic cipher key -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
fileKey - - -String - - - - file key
fileId - - -String - - - - file id
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

(static) fromObject(object) → {DeterministicKeyIv}

- - - - - - -
- Returns the a DeterministicKeyIv from an object -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
object - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
pass - - -Buffer -| - -String - - - - The unique password
salt - - -Buffer -| - -String - - - - The unique salt
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -DeterministicKeyIv - - -
-
- - - - - - - - - - - - - -

(static) getDeterministicKey(seed, id) → {String}

- - - - - - -
- Calculates a deterministic key -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
seed - - -Buffer -| - -String - - - - Deterministic seed or bucket key
id - - -Buffer -| - -String - - - - Unique bucket or file id
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

getCipherKeyIv() → {Array}

- - - - - - -
- Returns the cipher key and iv in an array -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Array - - -
-
- - - - - - - - - - - - - -

toObject() → {Array}

- - - - - - -
- Returns the key and iv as an array -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Array - - -
-
- - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/EmbeddedStorageAdapter.html b/Storj/core/docs/EmbeddedStorageAdapter.html deleted file mode 100644 index 6c87221..0000000 --- a/Storj/core/docs/EmbeddedStorageAdapter.html +++ /dev/null @@ -1,1882 +0,0 @@ - - - - - JSDoc: Class: EmbeddedStorageAdapter - - - - - - - - - - -
- -

Class: EmbeddedStorageAdapter

- - - - - - -
- -
- -

EmbeddedStorageAdapter(storageDirPath)

- - -
- -
-
- - - - - - -

new EmbeddedStorageAdapter(storageDirPath)

- - - - - - -
- Implements an LevelDB/KFS storage adapter interface -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
storageDirPath - - -String - - - - Path to store the level db
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - -

Extends

- - - - - - - - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

createReadStream() → {ReadableStream}

- - - - - - -
- Calls the implemented StorageAdapter#_keys and returns a readable -stream containing each stored item -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -ReadableStream - - -
-
- - - - - - - - - - - - - -

del(key, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_del -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash to delete the data for
callback - - -function - - - - Called with error or StorageItem
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

flush(callback)

- - - - - - -
- Calls the implemented StorageAdapter#_flush -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called with error or null
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

get(key, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_get and validates the result -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash to get metadata for
callback - - -function - - - - Called with error or StorageItem
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

peek(key, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_peek and validates the result -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash to get metadata for
callback - - -function - - - - Called with error or StorageItem
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

put(item, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_put and validates the input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - - Item to write to storage
callback - - -function - - - - Called on complete write
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

size(keyopt, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_size -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
key - - -String - - - - - - <optional>
- - - - - -
Optional file key
callback - - -function - - - - - - - - - - Called with error or number of bytes stored
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

add

- - - - - - -
- Triggered when a new item is added -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - -
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

delete

- - - - - - -
- Triggered when an item is deleted -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - -
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

ready

- - - - - - -
- Triggered when the adapter is ready -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

update

- - - - - - -
- Triggered when an existing item is updated -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
itemBeforeUpdate - - -StorageItem - - - -
itemAfterUpdate - - -StorageItem - - - -
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/EncryptStream.html b/Storj/core/docs/EncryptStream.html deleted file mode 100644 index db50674..0000000 --- a/Storj/core/docs/EncryptStream.html +++ /dev/null @@ -1,424 +0,0 @@ - - - - - JSDoc: Class: EncryptStream - - - - - - - - - - -
- -

Class: EncryptStream

- - - - - - -
- -
- -

EncryptStream(keyiv)

- - -
- -
-
- - - - - - -

new EncryptStream(keyiv)

- - - - - - -
- Represents a duplex stream capable of taking cleartext data as input and -producing output encrypted with DataCipherKeyIv -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
keyiv - - -DataCipherKeyIv -| - -DeterministicKeyIv - - - - Object to use -for derivation function
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - -
Fires:
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

data

- - - - - - -
- Triggered when some input bytes have become encrypted output bytes -
- - - - - -
Type:
-
    -
  • - -Buffer - - -
  • -
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

end

- - - - - - -
- Triggered when the stream has ended -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/ExchangeReport.html b/Storj/core/docs/ExchangeReport.html deleted file mode 100644 index b184612..0000000 --- a/Storj/core/docs/ExchangeReport.html +++ /dev/null @@ -1,751 +0,0 @@ - - - - - JSDoc: Class: ExchangeReport - - - - - - - - - - -
- -

Class: ExchangeReport

- - - - - - -
- -
- -

ExchangeReport(options)

- - -
- -
-
- - - - - - -

new ExchangeReport(options)

- - - - - - -
- Represents a report to a bridge regarding the result of a shard exchange -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
reporterId - - -String - - - - - - - - - -
farmerId - - -String - - - - - - <optional>
- - - - - -
clientId - - -String - - - - - - <optional>
- - - - - -
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

begin(dataHash)

- - - - - - -
- Starts recording duration of exchange -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
dataHash - - -String - - - - The shard hash as reference
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

end(resultCode, resultMessage)

- - - - - - -
- Ends the recording time a set result code and message -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
resultCode - - -Number - - - - Exchange result code
resultMessage - - -String - - - - Exchange result message
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

toObject() → {Object}

- - - - - - -
- Returns a plain report object -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Object - - -
-
- - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/FarmerInterface.html b/Storj/core/docs/FarmerInterface.html deleted file mode 100644 index 6c279ae..0000000 --- a/Storj/core/docs/FarmerInterface.html +++ /dev/null @@ -1,3279 +0,0 @@ - - - - - JSDoc: Class: FarmerInterface - - - - - - - - - - -
- -

Class: FarmerInterface

- - - - - - -
- -
- -

FarmerInterface(options)

- - -
- -
-
- - - - - - -

new FarmerInterface(options)

- - - - - - -
- Creates and a new farmer interface -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDefaultDescription
paymentAddress - - -String - - - - - - - - - - - - Optional payment address
opcodeSubscriptions - - -Array - - - - - - - - - - - - Contract opcodes to farm
maxOfferConcurrency - - -Number - - - - - - - - - - - - Max offers to have pending
contractNegotiator - - -FarmerInterface~negotiator - - - - - - - - - - - -
keyPair - - -KeyPair - - - - - - - - - - - - Node's cryptographic identity
storageManager - - -StorageManager - - - - - - - - - - - - Storage manager backend
bridgeUri - - -String - - - - - - - - - - - - URL for bridge server seed lookup
logger - - -Object - - - - - - - - - - - - Logger instance
seedList - - -Array - - - - - - - - - - - - List of seed URIs to join
rpcAddress - - -String - - - - - - - - - - - - Public node IP or hostname
rpcPort - - -Number - - - - - - - - - - - - Listening port for RPC
doNotTraverseNat - - -Boolean - - - - - - - - - - - - Skip NAT traversal strategies
maxTunnels - - -Number - - - - - - - - - - - - Max number of tunnels to provide
tunnelServerPort - - -Number - - - - - - - - - - - - Port for tunnel server to use
tunnelGatewayRange - - -Object - - - - - - - - - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
min - - -Number - - - - Min port for gateway binding
max - - -Number - - - - Max port for gateway binding
- -
offerBackoffLimit - - -Number - - - - - - <optional>
- - - - - -
- - 4 - - Do not send offers if more -than N transfers are active
renterWhitelist - - -Array.<String> - - - - - - <optional>
- - - - - -
- - Node IDs to offer storage to
joinRetry - - -Object - - - - - - <optional>
- - - - - -
- - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
times - - -Number - - - - - - <optional>
- - - - - -
Times to retry joining net
interval - - -Number - - - - - - <optional>
- - - - - -
MS to wait before retrying
- -
- -
- - - - - - -
Properties:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
keyPair - - -KeyPair - - - -
storageManager - - -StorageManager - - - -
node - - -kad.Node - - - - The underlying DHT node
triggerManager - - -TriggerManager - - - -
bridgeClient - - -BridgeClient - - - -
contact - - -Contact - - - -
transportAdapter - - -Transport - - - -
router - - -kad.Router - - - - The underlying DHT router
dataChannelServer - - -DataChannelServer - - - -
- - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - -
Fires:
- - - - - - - - - - - - - - - - - - -
- - -

Extends

- - - - - - - - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

connect(uri, callback)

- - - - - - -
- Connects to the node at the given URI -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
uri - - -String - - - - The storj protocol URI to connect
callback - - -function - - - - Called on connection or error
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getPaymentAddress() → {String}

- - - - - - -
- Returns the payment address supplied or the derived one from keypair -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

join(callback)

- - - - - - -
- Wraps the super call to Network#join to listen for contract after -successfully establishing a connection to the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on successful join
- - - - - - -
- - - - - - - - -
Overrides:
-
- - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

leave(callback)

- - - - - - -
- Disconnects from the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called when successful disconnect
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

ping(neighbor, callback)

- - - - - - -
- Will ping a neighbor -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
neighbor - - -String - - - - A contact
callback - - -function - - - - Called on connection or error
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

publish(topic, contents, options)

- - - - - - -
- Publishes a topic with content to the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
topic - - -String - - - - The serialized opcode topic
contents - - -Object - - - - Arbitrary publication contents
options - - -Object - - - - Options to pass to kad-quasar
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

subscribe(topic, handler)

- - - - - - -
- Subscribes to a topic on the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
topic - - -String - - - - The serialized opcode topic
handler - - -Object - - - - Function to handle received publications
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -

Type Definitions

- - - - - - - -

negotiator(contract) → {Boolean}

- - - - - - -
- Called when a contract is found that meets subscription criteria and allows -us to modify the contract terms if we desire and then uses the return value -to determine if we should send the renter an offer -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contract - - -Contract - - - - The contract object to negotiate
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - -

Events

- - - - - - - -

connected

- - - - - - -
- Triggered when the node has entered the overlay network -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

disconnected

- - - - - - -
- Triggered when the node has exited the overlay network -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

error

- - - - - - -
- Triggered when an error occurs -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

ready

- - - - - - -
- Triggered when the transport's network interface is ready -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

unhandledOffer

- - - - - - -
- Triggered when a valid offer is received, but we are not waiting for one -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The farmer contact the offer is from
contract - - -Contract - - - - The complete contract, signed by us and farmer
- - -Protocol~unhandledOfferResolver - - - -
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

unhandledOfferResolved

- - - - - - -
- Triggered when an unhandled offer is handled by the -Network#unhandledOffer listener by calling the event's supplied -Network~unhandledOfferResolver -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The farmer contact the offer is from
contract - - -Contract - - - - The complete contract, signed by us and farmer
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/FileDemuxer.html b/Storj/core/docs/FileDemuxer.html deleted file mode 100644 index 1819260..0000000 --- a/Storj/core/docs/FileDemuxer.html +++ /dev/null @@ -1,819 +0,0 @@ - - - - - JSDoc: Class: FileDemuxer - - - - - - - - - - -
- -

Class: FileDemuxer

- - - - - - -
- -
- -

FileDemuxer(filePath, options)

- - -
- -
-
- - - - - - -

new FileDemuxer(filePath, options)

- - - - - - -
- Takes a single file read stream and outputs several output streams, used for -"shredding" a file and creating muliple out destination interfaces -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
filePath - - -String - - - - Path the file to demultiplex
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
shardSize - - -Number - - - - Size of each shard
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - -
Fires:
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

(static) getOptimalShardSize(fileInfo, accopt) → {Number}

- - - - - - -
- Determine the optimal shard size given an arbitrary file size in bytes -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDefaultDescription
fileInfo - - -Object - - - - - - - - - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
fileSize - - -Number - - - - The number of bytes in the given file
shardConcurrency - - -Number - - - - Num of shards uploaded at once
- -
acc - - -Number - - - - - - <optional>
- - - - - -
- - 1 - - Accumulator (number of recursions)
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- shardSize -
- - - -
-
- Type -
-
- -Number - - -
-
- - - - - - - - - - - - - -

Events

- - - - - - - -

finish

- - - - - - -
- Triggered when the demuxer has finished writing to all shards -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

shard

- - - - - - -
- Triggered when the demuxer has a shard ready to stream -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
shard - - -ReadableStream - - - - The file shard as a readable stream
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/FileMuxer.html b/Storj/core/docs/FileMuxer.html deleted file mode 100644 index 391920d..0000000 --- a/Storj/core/docs/FileMuxer.html +++ /dev/null @@ -1,699 +0,0 @@ - - - - - JSDoc: Class: FileMuxer - - - - - - - - - - -
- -

Class: FileMuxer

- - - - - - -
- -
- -

FileMuxer(options)

- - -
- -
-
- - - - - - -

new FileMuxer(options)

- - - - - - -
- Accepts multiple ordered input sources and exposes them as a single -contiguous readable stream. Used for re-assembly of shards. -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
shards - - -Number - - - - Number of total shards to be multiplexed
length - - -Number - - - - Number of total bytes of input
sourceDrainWait - - -Number - - - - Time to wait for a new input after -all inputs are drained before entire stream is consumed
sourceIdleWait - - -Number - - - - Time to wait for source to make -more data available between next read
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - -
Fires:
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

addInputSource(readable, hash, exchangeReport, bridgeClient)

- - - - - - -
- Adds an additional input stream to the multiplexer -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
readable - - -ReadableStream - - - - Readable input stream from file shard
hash - - -String - - - - Hash of the shard
exchangeReport - - -ExchangeReport - - - - Instance of exchange report
bridgeClient - - -BridgeClient - - - - An instance of bridge client for reporting
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

drain

- - - - - - -
- Triggered when the muxer has drained one of the supplied inputs -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -ReadableStream - - - - The drained input stream
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/KeyPair.html b/Storj/core/docs/KeyPair.html deleted file mode 100644 index 298272b..0000000 --- a/Storj/core/docs/KeyPair.html +++ /dev/null @@ -1,926 +0,0 @@ - - - - - JSDoc: Class: KeyPair - - - - - - - - - - -
- -

Class: KeyPair

- - - - - - -
- -
- -

KeyPair(privateKey)

- - -
- -
-
- - - - - - -

new KeyPair(privateKey)

- - - - - - -
- Represents a ECDSA key pair -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
privateKey - - -String -| - -Buffer -| - -undefined - - - - WIF encoded ECDSA private key
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

getAddress() → {String}

- - - - - - -
- Returns the bitcoin address version of the nodeID -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- address - Base58 encoded address -
- - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

getNodeID() → {String}

- - - - - - -
- Returns the NodeID derived from the public key -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- nodeID - RIPEMD160 hash of public key -
- - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

getPrivateKey() → {String}

- - - - - - -
- Returns the private key -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- key -
- - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

getPublicKey() → {String}

- - - - - - -
- Returns the public key -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- key -
- - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

sign(message, options) → {String}

- - - - - - -
- Signs the supplied message with the private key -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
message - - -String -| - -Buffer - - - - The message to sign
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDefaultDescription
compact - - -Boolean - - - - - - <optional>
- - - - - -
- - true - - Compact signature format
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- signature -
- - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/KeyRing.html b/Storj/core/docs/KeyRing.html deleted file mode 100644 index 57007a5..0000000 --- a/Storj/core/docs/KeyRing.html +++ /dev/null @@ -1,2237 +0,0 @@ - - - - - JSDoc: Class: KeyRing - - - - - - - - - - -
- -

Class: KeyRing

- - - - - - -
- -
- -

KeyRing(keyRingDir, passPhraseopt)

- - -
- -
-
- - - - - - -

new KeyRing(keyRingDir, passPhraseopt)

- - - - - - -
- A DataCipherKeyIv factory with file system persistence -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDefaultDescription
keyRingDir - - -String - - - - - - - - - - - - Path to store keyring directory
passPhrase - - -String - - - - - - <optional>
- - - - - -
- - '' - - Passphrase to encrypt/decrypt keyring
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

del(keyId)

- - - - - - -
- Delete the keyring file from disk -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
keyId - - -String - - - - Arbitrary key ID to delete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

deleteDeterministicKey()

- - - - - - -
- Delete deterministic key from disk -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

export(outPath, callback)

- - - - - - -
- Export Keyring to compressed tarball -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
outPath - - -String - - - - Path to keyring to be compressed
callback - - -function - - - - Called when tarball has been written
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

exportMnemonic() → {String|null}

- - - - - - -
- Export mnemonic from KeyRing -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String -| - -null - - -
-
- - - - - - - - - - - - - -

generate(keyId) → {KeyPair}

- - - - - - -
- Returns the stored KeyPair for the given id -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
keyId - - -String - - - - Generate a key for use with the given ID
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -KeyPair - - -
-
- - - - - - - - - - - - - -

generateBucketKey(bucketId) → {String|null}

- - - - - - -
- Retrieve the bucketKey -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bucketId - - -String - - - - bucket id
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String -| - -null - - -
-
- - - - - - - - - - - - - -

generateDeterministicKey()

- - - - - - -
- Generate and save deterministic key to disk -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

generateFileKey(bucketId, fileId) → {DataCipherKeyIv}

- - - - - - -
- Retrieve the fileKey -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bucketId - - -String - - - - bucket id
fileId - - -String - - - - file id
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -DataCipherKeyIv - - -
-
- - - - - - - - - - - - - -

get(keyId) → {DataCipherKeyIv|DeterministicKeyIv|null}

- - - - - - -
- Returns the stored KeyPair for the given id -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
keyId - - -String - - - - Arbitrary key ID to load
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -DataCipherKeyIv -| - -DeterministicKeyIv -| - -null - - -
-
- - - - - - - - - - - - - -

import(inPath, passPhrase, overwriteConflictingIdsopt, callback)

- - - - - - -
- Import to Keyring from compressed tarball -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDefaultDescription
inPath - - -String - - - - - - - - - - - - Path to tarball to be imported
passPhrase - - -String - - - - - - - - - - - - Passphrase used to decrypt the imported tar
overwriteConflictingIds - - -Boolean - - - - - - <optional>
- - - - - -
- - false - - Overwrite conflicting key
callback - - -function - - - - - - - - - - - - Called on import finish
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

importMnemonic(mnemonic)

- - - - - - -
- Import mnemonic into KeyRing -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
mnemonic - - -String - - - - Mnemonic to transfer
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

reset(passPhrase, callback)

- - - - - - -
- Resets the keyring password -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
passPhrase - - -String - - - - New passphrase for keyring
callback - - -function - - - - Called on keyring password reset
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

set(keyId, dataCipherKey)

- - - - - - -
- Returns the stored KeyPair for the given id -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
keyId - - -String - - - - Arbitrary key ID to load
dataCipherKey - - -DataCipherKeyIv -| - -DeterministicKeyIv - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/Monitor.html b/Storj/core/docs/Monitor.html deleted file mode 100644 index 619a3d7..0000000 --- a/Storj/core/docs/Monitor.html +++ /dev/null @@ -1,1353 +0,0 @@ - - - - - JSDoc: Class: Monitor - - - - - - - - - - -
- -

Class: Monitor

- - - - - - -
- -
- -

Monitor(network, options)

- - -
- -
-
- - - - - - -

new Monitor(network, options)

- - - - - - -
- Wraps a Network instance and provides events for gathering -statistics about node operation -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
network - - -Network - - - - The network interface to monitor
options - - -Object - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

(static) getConnectedPeers(source, callback)

- - - - - - -
- Gets the list of currently known Contacts -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
source - - -Network - - - - The network instance to use
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(static) getContractsDetails(source, callback)

- - - - - - -
- Gets the total contracts stored -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
source - - -Network - - - - The network instance to use
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(static) getDiskUtilization(source, callback)

- - - - - - -
- Gets the amount of used space compared to amount shared -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
source - - -Network - - - - The network instance to use
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(static) getPaymentAddressBalances(source, callback)

- - - - - - -
- Gets the balance of SJCX/SJCT from a FarmerInterface -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
source - - -Network - - - - The network instance to use
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getSnapshot() → {Object}

- - - - - - -
- Returns the current snapshot -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- snapshot -
- - - -
-
- Type -
-
- -Object - - -
-
- - - - - - - - - - - - - -

start() → {Monitor}

- - - - - - -
- Starts the network monitor -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Monitor - - -
-
- - - - - - - - - - - - - -

stop() → {Monitor}

- - - - - - -
- Stops the network monitor -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Monitor - - -
-
- - - - - - - - - - - - - -

Events

- - - - - - - -

update

- - - - - - -
- Triggered when a valid offer is received, but we are not waiting for one -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
stats - - -Object - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/Network.html b/Storj/core/docs/Network.html deleted file mode 100644 index 3802ce6..0000000 --- a/Storj/core/docs/Network.html +++ /dev/null @@ -1,2795 +0,0 @@ - - - - - JSDoc: Class: Network - - - - - - - - - - -
- -

Class: Network

- - - - - - -
- -
- -

Network(options)

- - -
- -
-
- - - - - - -

new Network(options)

- - - - - - -
- Storj network interface -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
hdKey - - -String - - - - - - <optional>
- - - - - -
Extended SIP32 private key at 'group index'
hdIndex - - -Number - - - - - - <optional>
- - - - - -
Derivation index for hdKey
keyPair - - -KeyPair - - - - - - <optional>
- - - - - -
Node's cryptographic identity
storageManager - - -StorageManager - - - - - - - - - - Storage manager backend
bridgeUri - - -String - - - - - - - - - - URL for bridge server seed lookup
logger - - -Object - - - - - - - - - - Logger instance
seedList - - -Array - - - - - - - - - - List of seed URIs to join
rpcAddress - - -String - - - - - - - - - - Public node IP or hostname
rpcPort - - -Number - - - - - - - - - - Listening port for RPC
listenPort - - -Number - - - - - - - - - - Optional different listening port for RPC to bind to
doNotTraverseNat - - -Boolean - - - - - - - - - - Skip NAT traversal strategies
maxTunnels - - -Number - - - - - - - - - - Max number of tunnels to provide
maxConnections - - -Number - - - - - - - - - - Max concurrent connections
tunnelGatewayRange - - -Object - - - - - - - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
min - - -Number - - - - Min port for gateway bind
max - - -Number - - - - Max port for gateway bind
- -
joinRetry - - -Object - - - - - - <optional>
- - - - - -
-
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
times - - -Number - - - - - - <optional>
- - - - - -
Times to retry joining net
interval - - -Number - - - - - - <optional>
- - - - - -
MS to wait before retrying
- -
- -
- - - - - - -
Properties:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
keyPair - - -KeyPair - - - -
storageManager - - -StorageManager - - - -
node - - -kad.Node - - - - The underlying DHT node
triggerManager - - -TriggerManager - - - -
bridgeClient - - -BridgeClient - - - -
contact - - -Contact - - - -
transportAdapter - - -Transport - - - -
router - - -kad.Router - - - - The underlying DHT router
shardServer - - -ShardServer - - - -
offerManager - - -OfferManager - - - -
- - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - -
Fires:
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

connect(uri, callback)

- - - - - - -
- Connects to the node at the given URI -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
uri - - -String - - - - The storj protocol URI to connect
callback - - -function - - - - Called on connection or error
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

join(callback)

- - - - - - -
- Opens the connection to the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on successful network join
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

leave(callback)

- - - - - - -
- Disconnects from the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called when successful disconnect
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

ping(neighbor, callback)

- - - - - - -
- Will ping a neighbor -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
neighbor - - -String - - - - A contact
callback - - -function - - - - Called on connection or error
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

publish(topic, contents, options)

- - - - - - -
- Publishes a topic with content to the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
topic - - -String - - - - The serialized opcode topic
contents - - -Object - - - - Arbitrary publication contents
options - - -Object - - - - Options to pass to kad-quasar
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

subscribe(topic, handler)

- - - - - - -
- Subscribes to a topic on the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
topic - - -String - - - - The serialized opcode topic
handler - - -Object - - - - Function to handle received publications
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

connected

- - - - - - -
- Triggered when the node has entered the overlay network -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

disconnected

- - - - - - -
- Triggered when the node has exited the overlay network -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

error

- - - - - - -
- Triggered when an error occurs -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

ready

- - - - - - -
- Triggered when the transport's network interface is ready -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

unhandledOffer

- - - - - - -
- Triggered when a valid offer is received, but we are not waiting for one -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The farmer contact the offer is from
contract - - -Contract - - - - The complete contract, signed by us and farmer
- - -Protocol~unhandledOfferResolver - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

unhandledOfferResolved

- - - - - - -
- Triggered when an unhandled offer is handled by the -Network#unhandledOffer listener by calling the event's supplied -Network~unhandledOfferResolver -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The farmer contact the offer is from
contract - - -Contract - - - - The complete contract, signed by us and farmer
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/OfferManager.html b/Storj/core/docs/OfferManager.html deleted file mode 100644 index b91c676..0000000 --- a/Storj/core/docs/OfferManager.html +++ /dev/null @@ -1,607 +0,0 @@ - - - - - JSDoc: Class: OfferManager - - - - - - - - - - -
- -

Class: OfferManager

- - - - - - -
- -
- -

OfferManager()

- - -
- -
-
- - - - - - -

new OfferManager()

- - - - - - -
- Simple management of a collection of OfferStreams that are keyable -by their associated Contract's data hash -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

addStream(offerStream)

- - - - - - -
- Adds the offer stream to the manager -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
offerStream - - -OfferStream - - - - The OfferStream to manage
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getStream(dataHash) → {OfferStream|null}

- - - - - - -
- Returns the stream at the given key -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
dataHash - - -String - - - - The hash of the contract's data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -OfferStream -| - -null - - -
-
- - - - - - - - - - - - - -

removeStream(dataHash)

- - - - - - -
- Removes the stream at the given key -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
dataHash - - -String - - - - The hash of the contract's data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/OfferStream.html b/Storj/core/docs/OfferStream.html deleted file mode 100644 index 00fbbd7..0000000 --- a/Storj/core/docs/OfferStream.html +++ /dev/null @@ -1,1068 +0,0 @@ - - - - - JSDoc: Class: OfferStream - - - - - - - - - - -
- -

Class: OfferStream

- - - - - - -
- -
- -

OfferStream(contract, optionsopt)

- - -
- -
-
- - - - - - -

new OfferStream(contract, optionsopt)

- - - - - - -
- Manages a stream of offers for a given storage contract publication -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
contract - - -Contract - - - - - - - - - - Storage contract published to network
options - - -Object - - - - - - <optional>
- - - - - -
-
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
maxOffers - - -Number - - - - - - <optional>
- - - - - -
Maximum number of offers to process
farmerBlacklist - - -Array.<String> - - - - - - <optional>
- - - - - -
Reject offers from nodeID
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

addOfferToQueue(contact, contract) → {Boolean}

- - - - - - -
- Adds the offer to the internal queue if there is room -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The sending farmer for the offer
contract - - -Contract - - - - The received offer contract
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- didAddOfferToQueue -
- - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

destroy()

- - - - - - -
- Tears down listeners and ends the stream -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

data

- - - - - - -
- Triggered when an offer is received -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
data - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The sending farmer for the offer
contract - - -Contract - - - - The received offer contract
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

end

- - - - - - -
- Triggered when the maximum number of offers are received and processed -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

error

- - - - - - -
- Triggered if an error occurs -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
error - - -Error - - - - The error object with message
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/ProofStream.html b/Storj/core/docs/ProofStream.html deleted file mode 100644 index 03d4913..0000000 --- a/Storj/core/docs/ProofStream.html +++ /dev/null @@ -1,356 +0,0 @@ - - - - - JSDoc: Class: ProofStream - - - - - - - - - - -
- -

Class: ProofStream

- - - - - - -
- -
- -

ProofStream(merkleLeaves, hexChallenge)

- - -
- -
-
- - - - - - -

new ProofStream(merkleLeaves, hexChallenge)

- - - - - - -
- Provides interface for proving possession of a file for an -AuditStream -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
merkleLeaves - - -Array - - - - Bottom leaves of the audit merkle tree
hexChallenge - - -String - - - - The challenge data in hex to prepend to shard
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

getProofResult() → {Array}

- - - - - - -
- Returns the generated proof structure -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Array - - -
-
- - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/Protocol.html b/Storj/core/docs/Protocol.html deleted file mode 100644 index 7ca02d5..0000000 --- a/Storj/core/docs/Protocol.html +++ /dev/null @@ -1,5070 +0,0 @@ - - - - - JSDoc: Class: Protocol - - - - - - - - - - -
- -

Class: Protocol

- - - - - - -
- -
- -

Protocol(options)

- - -
- -
-
- - - - - - -

new Protocol(options)

- - - - - - -
- Defines the Storj protocol methods and mounts on a Network instance -to handle Storj protocol messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
network - - -Network - - - - Network instance to bind to
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

getRouteMap() → {Object}

- - - - - - -
- Returns bound references to the protocol handlers -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- handlers -
- - - -
-
- Type -
-
- -Object - - -
-
- - - - - - - - - - - - - -

handleAudit(params, callback)

- - - - - - -
- Handles AUDIT messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - Sender contact information
audits - - -Array.<Object> - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
data_hash - - -String - - - - Shard data hash to audit
challenge - - -String - - - - Challenge string for audit
- -
- -
callback - - -Protocol~handleAuditCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleConsign(params, callback)

- - - - - - -
- Handles CONSIGN messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - Sender contact information
data_hash - - -String - - - - Shard data hash (contract key)
audit_tree - - -Array.<String> - - - - Bottom leaves of audit merkle tree
- -
callback - - -Protocol~handleConsignCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleFindTunnel(params, callback)

- - - - - - -
- Handles FIND_TUNNEL messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - Sender contact information
relayers - - -Array.<Contact> - - - - List of contacts who have already -relayed the FIND_TUNNEL request
- -
callback - - -Protocol~handleFindTunnelCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleMirror(params, callback)

- - - - - - -
- Handles MIRROR messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - Sender contact information
data_hash - - -String - - - - Shard hash to mirror
token - - -String - - - - Data channel authorization token
farmer - - -Contact - - - - The farmer to transfer data from
- -
callback - - -Protocol~handleMirrorCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleOffer(params, callback)

- - - - - - -
- Handles OFFER messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - Sender contact information
contract - - -Contract - - - - Serialized contract data
- -
callback - - -Protocol~handleOfferCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - -
Fires:
- - - - - - - - - - - - - - - - - - - - - - - -

handleOpenTunnel(params, callback)

- - - - - - -
- Handles OPEN_TUNNEL messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - Sender contact information
- -
callback - - -Protocol~handleOpenTunnelCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleProbe(params, callback)

- - - - - - -
- Handles PROBE messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - Sender contact information
- -
callback - - -Protocol~handleProbeCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleRenew(params, callback)

- - - - - - -
- Handles RENEW messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - Sender contact information
renter_id - - -String - - - - Renter nodeID of the original contract
renter_signature - - -String - - - - Contract signature from original -node ID
contract - - -Object - - - - Updated contract data
- -
callback - - -Protocol~handleRenewCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - -
See:
-
- -
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleRetrieve(params, callback)

- - - - - - -
- Handles RETRIEVE messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - Sender contact information
data_hash - - -String - - - - RMD160(SHA256(shard_data))
- -
callback - - -Protocol~handleRetrieveCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleTrigger(params, callback)

- - - - - - -
- Handles TRIGGER messages -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
behavior - - -String - - - - Trigger behavior name to process
contents - - -Object - - - - Trigger content payload
contact - - -Contact - - - - Sender contact information
- -
callback - - -Protocol~handleTriggerCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - -
See:
-
- -
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - -

Type Definitions

- - - - - - - -

handleAuditCallback(err, result)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - -
result - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
proofs - - -Array.<Array> - - - - Mapped list of proof responses
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleConsignCallback(err, result)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - -
result - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
token - - -String - - - - Data channel authorization token
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleFindTunnelCallback(err, result)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - -
result - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
tunnels - - -Array.<Contact> - - - - List of known tunnelers
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleMirrorCallback(err, result)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - -
result - - -Object - - - - Empty acknowledgement
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleOfferCallback(err, result)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - -
result - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contract - - -Contract - - - - Signed contract
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleOpenTunnelCallback(err, result)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - -
result - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
tunnel - - -String - - - - WebSocket URI including auth token
alias - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
address - - -String - - - - Gateway address on the tunneler
port - - -Number - - - - Gateway port on the tunneler
- -
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleProbeCallback(err, result)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - -
result - - -Object - - - - Empty acknowledgement
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleRenewCallback(err, result)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - -
result - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contract - - -Object - - - - Signed updated contract
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleRetrieveCallback(err, result)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - -
result - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
token - - -String - - - - Authorization token for data channel
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

handleTriggerCallback(err, result)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - -
result - - -Object - - - - Arbitrary key-value pairs
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

unhandledOfferResolver(erroropt)

- - - - - - - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
error - - -Error - - - - - - <optional>
- - - - - -
An error if the offer cannot be resolved
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/RAMStorageAdapter.html b/Storj/core/docs/RAMStorageAdapter.html deleted file mode 100644 index cfb6bac..0000000 --- a/Storj/core/docs/RAMStorageAdapter.html +++ /dev/null @@ -1,2259 +0,0 @@ - - - - - JSDoc: Class: RAMStorageAdapter - - - - - - - - - - -
- -

Class: RAMStorageAdapter

- - - - - - -
- -
- -

RAMStorageAdapter()

- - -
- -
-
- - - - - - -

new RAMStorageAdapter()

- - - - - - -
- Implements an in-memory storage adapter -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - -

Extends

- - - - - - - - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

(abstract) _close(callback)

- - - - - - -
- Closes the storage adapter -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(abstract) _open(callback)

- - - - - - -
- Opens the storage adapter -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(abstract) _size(callback)

- - - - - - -
- Returns the number of bytes stored -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - -
Overrides:
-
- - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

createReadStream() → {ReadableStream}

- - - - - - -
- Calls the implemented StorageAdapter#_keys and returns a readable -stream containing each stored item -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -ReadableStream - - -
-
- - - - - - - - - - - - - -

del(key, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_del -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash to delete the data for
callback - - -function - - - - Called with error or StorageItem
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

flush(callback)

- - - - - - -
- Calls the implemented StorageAdapter#_flush -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called with error or null
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

get(key, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_get and validates the result -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash to get metadata for
callback - - -function - - - - Called with error or StorageItem
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

peek(key, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_peek and validates the result -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash to get metadata for
callback - - -function - - - - Called with error or StorageItem
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

put(item, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_put and validates the input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - - Item to write to storage
callback - - -function - - - - Called on complete write
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

size(keyopt, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_size -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
key - - -String - - - - - - <optional>
- - - - - -
Optional file key
callback - - -function - - - - - - - - - - Called with error or number of bytes stored
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

add

- - - - - - -
- Triggered when a new item is added -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - -
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

delete

- - - - - - -
- Triggered when an item is deleted -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - -
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

ready

- - - - - - -
- Triggered when the adapter is ready -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

update

- - - - - - -
- Triggered when an existing item is updated -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
itemBeforeUpdate - - -StorageItem - - - -
itemAfterUpdate - - -StorageItem - - - -
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/RenterInterface.html b/Storj/core/docs/RenterInterface.html deleted file mode 100644 index c0c1878..0000000 --- a/Storj/core/docs/RenterInterface.html +++ /dev/null @@ -1,4698 +0,0 @@ - - - - - JSDoc: Class: RenterInterface - - - - - - - - - - -
- -

Class: RenterInterface

- - - - - - -
- -
- -

RenterInterface(options)

- - -
- -
-
- - - - - - -

new RenterInterface(options)

- - - - - - -
- Creates and a new renter interface -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
hdKey - - -String - - - - - - <optional>
- - - - - -
Extended key at 'group index' as per SIP32
hdIndex - - -Number - - - - - - <optional>
- - - - - -
Derivation index for hdKey
keyPair - - -KeyPair - - - - - - <optional>
- - - - - -
Node's cryptographic identity
storageManager - - -StorageManager - - - - - - - - - - Storage manager backend
bridgeUri - - -String - - - - - - - - - - URL for bridge server seed lookup
logger - - -Object - - - - - - - - - - Logger instance
seedList - - -Array - - - - - - - - - - List of seed URIs to join
rpcAddress - - -String - - - - - - - - - - Public node IP or hostname
rpcPort - - -Number - - - - - - - - - - Listening port for RPC
doNotTraverseNat - - -Boolean - - - - - - - - - - Skip NAT traversal strategies
maxTunnels - - -Number - - - - - - - - - - Max number of tunnels to provide
tunnelServerPort - - -Number - - - - - - - - - - Port for tunnel server to use
tunnelGatewayRange - - -Object - - - - - - - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
min - - -Number - - - - Min port for gateway bind
max - - -Number - - - - Max port for gateway bind
- -
rateLimiterOpts - - -Object - - - - - - - - - - Options for RateLimiter
joinRetry - - -Object - - - - - - <optional>
- - - - - -
-
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
times - - -Number - - - - - - <optional>
- - - - - -
Times to retry joining net
interval - - -Number - - - - - - <optional>
- - - - - -
MS to wait before retrying
- -
- -
- - - - - - -
Properties:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
keyPair - - -KeyPair - - - -
storageManager - - -StorageManager - - - -
node - - -kad.Node - - - - The underlying DHT node
triggerManager - - -TriggerManager - - - -
bridgeClient - - -BridgeClient - - - -
contact - - -Contact - - - -
transportAdapter - - -Transport - - - -
router - - -kad.Router - - - - The underlying DHT router
dataChannelServer - - -DataChannelServer - - - -
- - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - -
Fires:
- - - - - - - - - - - - - - - - - - -
- - -

Extends

- - - - - - - - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

connect(uri, callback)

- - - - - - -
- Connects to the node at the given URI -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
uri - - -String - - - - The storj protocol URI to connect
callback - - -function - - - - Called on connection or error
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getConsignmentPointer(farmer, contract, audit, callback)

- - - - - - -
- Requests a consignment pointer from the given farmer for opening a -DataChannelClient for transferring the the data shard to the farmer -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
farmer - - -Contact - - - - The farmer contact object for requesting token
contract - - -Contract - - - - The storage contract for this consignment
audit - - -AuditStream - - - - The audit object for merkle leaves
callback - - -RenterInterface~getConsignmentPointerCallback - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getMirrorNodes(sources, destinations, callback)

- - - - - - -
- Requests that the given destination farmers mirror the data from the sources -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
sources - - -Array.<Object> - - - - Pointers for each destination
destinations - - -Array.<Contact> - - - - The farmers to replicate to
callback - - -RenterInterface~getMirrorNodesCallback - - - - Results handler
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getOfferStream(contract, offerStreamOptionsopt) → {OfferStream}

- - - - - - -
- Creates a readable stream of offers for the storage contract -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
contract - - -Contract - - - - - - - - - - The storage contract to publish
offerStreamOptions - - -Object - - - - - - <optional>
- - - - - -
Options passed to OfferStream
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- offerStream -
- - - -
-
- Type -
-
- -OfferStream - - -
-
- - - - - - - - - - - - - -

getRetrievalPointer(farmer, contract, callback)

- - - - - - -
- Requests a retrieval token from the given farmer for opening a -DataChannelClient for transferring the data shard from the farmer -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
farmer - - -Contact - - - - The farmer contact object for requesting token
contract - - -Contract - - - - The storage contract for this consignment
callback - - -RenterInterface~getRetrievalPointerCallback - - - - Token handler
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getStorageProof(farmer, item, callback)

- - - - - - -
- Issues an audit request to the given farmer for the data and returns the -ProofStream#getProofResult structure for verification. -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
farmer - - -Contact - - - - Farmer contact from which proof is needed
item - - -StorageItem - - - - The storage item on which to perform the audit
callback - - -RenterInterface~getStorageProofCallback - - - - Proof handler
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

join(callback)

- - - - - - -
- Opens the connection to the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on successful network join
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

leave(callback)

- - - - - - -
- Disconnects from the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called when successful disconnect
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

ping(neighbor, callback)

- - - - - - -
- Will ping a neighbor -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
neighbor - - -String - - - - A contact
callback - - -function - - - - Called on connection or error
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

publish(topic, contents, options)

- - - - - - -
- Publishes a topic with content to the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
topic - - -String - - - - The serialized opcode topic
contents - - -Object - - - - Arbitrary publication contents
options - - -Object - - - - Options to pass to kad-quasar
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

subscribe(topic, handler)

- - - - - - -
- Subscribes to a topic on the network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
topic - - -String - - - - The serialized opcode topic
handler - - -Object - - - - Function to handle received publications
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -

Type Definitions

- - - - - - - -

getConsignmentPointerCallback(err, pointer)

- - - - - - -
- This callback is called upon receipt of a consignment token from -RenterInterface#getConsignmentPointer -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - - If requesting the token failed, an error object
pointer - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
farmer - - -Contact - - - -
hash - - -String - - - -
token - - -String - - - -
operation - - -String - - - -
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getMirrorNodesCallback(err, results)

- - - - - - -
- This callback is called upon acknowledgement of a mirror request -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - - If requesting all mirrors failed, an error object
results - - -Array.<Contact> - - - - The farmers who successfully mirrored
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getRetrievalPointerCallback(err, pointer)

- - - - - - -
- This callback is called upon receipt of a retrieval token from -RenterInterface#getRetrieveToken -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - - If requesting the token failed, an error object
pointer - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
farmer - - -Contact - - - -
hash - - -String - - - -
token - - -String - - - -
operation - - -String - - - -
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getStorageProofCallback(err, proof)

- - - - - - -
- This callback is called upon receipt of an audit proof from -RenterInterface#getStorageProof -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - - If requesting the proof failed, an error object
proof - - -Array - - - - Result from ProofStream#getProofResult
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

connected

- - - - - - -
- Triggered when the node has entered the overlay network -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

disconnected

- - - - - - -
- Triggered when the node has exited the overlay network -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

error

- - - - - - -
- Triggered when an error occurs -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

ready

- - - - - - -
- Triggered when the transport's network interface is ready -
- - - - - - - - - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

unhandledOffer

- - - - - - -
- Triggered when a valid offer is received, but we are not waiting for one -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The farmer contact the offer is from
contract - - -Contract - - - - The complete contract, signed by us and farmer
- - -Protocol~unhandledOfferResolver - - - -
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

unhandledOfferResolved

- - - - - - -
- Triggered when an unhandled offer is handled by the -Network#unhandledOffer listener by calling the event's supplied -Network~unhandledOfferResolver -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The farmer contact the offer is from
contract - - -Contract - - - - The complete contract, signed by us and farmer
- - - - - - -
- - - - - - -
Inherited From:
-
- - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/ShardServer.html b/Storj/core/docs/ShardServer.html deleted file mode 100644 index 1dcf475..0000000 --- a/Storj/core/docs/ShardServer.html +++ /dev/null @@ -1,1615 +0,0 @@ - - - - - JSDoc: Class: ShardServer - - - - - - - - - - -
- -

Class: ShardServer

- - - - - - -
- -
- -

ShardServer(options)

- - -
- -
-
- - - - - - -

new ShardServer(options)

- - - - - - -
- Creates a shard server for sending and receiving consigned file shards -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDefaultDescription
nodeID - - -String - - - - - - - - - - - - The farmer nodeID
storageManager - - -StorageManager - - - - - - - - - - - - Storage manager backend
logger - - -kad.Logger - - - - - - - - - - - - Logger to use from Network
tokenTtl - - -Number - - - - - - <optional>
- - - - - -
- - 1800000 - - Close after idle
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

accept(token, filehash, contact)

- - - - - - -
- Begin accepting data for the given file hash and token -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
token - - -String - - - - The authorization token created for transfer
filehash - - -String - - - - The shard hash to allow for the token
contact - - -Contact - - - - contact that negotiated the token
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

isAuthorized(token, hash)

- - - - - - -
- Validates the given token -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
token - - -String - - - -
hash - - -String - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

reject(token)

- - - - - - -
- Stop accepting data for the given token -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
token - - -String - - - - The authorization token created for transfer
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

routeConsignment(req, req)

- - - - - - -
- Receives the data stream and writes it to storage -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
req - - -http.IncomingMessage - - - -
req - - -http.ServerResponse - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

routeRetrieval(req, res)

- - - - - - -
- Pumps the data through to the client -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
req - - -http.IncomingMessage - - - -
res - - -http.ServerResponse - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

error

- - - - - - -
- Triggered when a error occurs -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
error - - -Error - - - - The error object
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

shardDownloaded

- - - - - - -
- Triggered when a shard has finished downloading from this instance -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - - The item associated with the download
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

shardUploaded

- - - - - - -
- Triggered when a shard has finished uploading to this instance -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - - The item associated with the upload
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/StorageAdapter.html b/Storj/core/docs/StorageAdapter.html deleted file mode 100644 index 6e460c7..0000000 --- a/Storj/core/docs/StorageAdapter.html +++ /dev/null @@ -1,3108 +0,0 @@ - - - - - JSDoc: Class: StorageAdapter - - - - - - - - - - -
- -

Class: StorageAdapter

- - - - - - -
- -
- -

StorageAdapter()

- - -
- -
-
- - - - - - -

new StorageAdapter()

- - - - - - -
- Abstract base class for storage adapter -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

(abstract) _close(callback)

- - - - - - -
- Closes the storage adapter -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(abstract) _del(key, callback)

- - - - - - -
- Delete the shard data at the given key -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(abstract) _flush(key, callback)

- - - - - - -
- Performs lookup and provides an StorageItem to the callback -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(abstract) _get(key, callback)

- - - - - - -
- Performs lookup and provides an StorageItem to the callback -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(abstract) _keys() → {ReadableStream}

- - - - - - -
- Returns the hashes of all shards stored -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -ReadableStream - - -
-
- - - - - - - - - - - - - -

(abstract) _open(callback)

- - - - - - -
- Opens the storage adapter -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(abstract) _peek(key, callback)

- - - - - - -
- Performs lookup and provides an StorageItem to the callback but does -not initialize any shard read/write stream -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(abstract) _put(key, item, callback)

- - - - - - -
- Stores the StorageItem -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash
item - - -Item - - - - Item to store
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(abstract) _size(callback)

- - - - - - -
- Returns the number of bytes stored -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

createReadStream() → {ReadableStream}

- - - - - - -
- Calls the implemented StorageAdapter#_keys and returns a readable -stream containing each stored item -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -ReadableStream - - -
-
- - - - - - - - - - - - - -

del(key, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_del -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash to delete the data for
callback - - -function - - - - Called with error or StorageItem
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

flush(callback)

- - - - - - -
- Calls the implemented StorageAdapter#_flush -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called with error or null
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

get(key, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_get and validates the result -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash to get metadata for
callback - - -function - - - - Called with error or StorageItem
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

peek(key, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_peek and validates the result -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -String - - - - Shard hash to get metadata for
callback - - -function - - - - Called with error or StorageItem
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

put(item, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_put and validates the input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - - Item to write to storage
callback - - -function - - - - Called on complete write
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

size(keyopt, callback)

- - - - - - -
- Calls the implemented StorageAdapter#_size -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
key - - -String - - - - - - <optional>
- - - - - -
Optional file key
callback - - -function - - - - - - - - - - Called with error or number of bytes stored
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

add

- - - - - - -
- Triggered when a new item is added -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

delete

- - - - - - -
- Triggered when an item is deleted -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

ready

- - - - - - -
- Triggered when the adapter is ready -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

update

- - - - - - -
- Triggered when an existing item is updated -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
itemBeforeUpdate - - -StorageItem - - - -
itemAfterUpdate - - -StorageItem - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/StorageItem.html b/Storj/core/docs/StorageItem.html deleted file mode 100644 index 0bf9e9e..0000000 --- a/Storj/core/docs/StorageItem.html +++ /dev/null @@ -1,1399 +0,0 @@ - - - - - JSDoc: Class: StorageItem - - - - - - - - - - -
- -

Class: StorageItem

- - - - - - -
- -
- -

StorageItem(data)

- - -
- -
-
- - - - - - -

new StorageItem(data)

- - - - - - -
- Represents a storage item, including contracts, challenges, the shard itself -along with metadata describing download count, payments, etc -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
data - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
hash - - -String -| - -null - - - - Shard hash to use as storage key
shard - - -Stream -| - -null - - - - Raw binary blob of shard
contracts - - -Object - - - - Dictionary of nodeID:Contract
trees - - -Object - - - - Dictionary of nodeID:merkleLeaves
challenges - - -Object - - - - Dictionary of nodeID:privateAuditData
meta - - -Object - - - - Dictionary of arbitrary nodeID:metadata
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

addAuditRecords(contact, audit)

- - - - - - -
- Adds the trees and challenges to the item keyed by nodeID -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The contact associated with the trees
audit - - -Audit -| - -AuditStream - - - - The audit or challenge generator
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

addContract(contact, contract)

- - - - - - -
- Adds the contract data keyed by nodeID and hdKey -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The contact associated with the trees
contract - - -Contract - - - - The storage contract instance
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

addMetaData(contact, meta)

- - - - - - -
- Adds the meta data keyed by nodeID -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The contact associated with the trees
meta - - -Object - - - - Arbitrary metadata about the shard
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getContract(contact, contract) → {Contract|Boolean}

- - - - - - -
- Gets a contract data by a contact based on the hdKey or the nodeID -of the contact. It will return false if the contract is not found for the -contact, which will indicate that the contact is not authorized for -that specific contract. -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The contact associated with the trees
contract - - -Contract - - - - The storage contract instance
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Contract -| - -Boolean - - -
-
- - - - - - - - - - - - - -

removeContract(contact) → {Boolean}

- - - - - - -
- Deletes the contract for the given contact -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- didRemoveContract -
- - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

toObject()

- - - - - - -
- Returns a plain object representation of the item -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

updateTimestamp()

- - - - - - -
- Updates the timestamp for the item -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/StorageManager.html b/Storj/core/docs/StorageManager.html deleted file mode 100644 index f7fee4f..0000000 --- a/Storj/core/docs/StorageManager.html +++ /dev/null @@ -1,1115 +0,0 @@ - - - - - JSDoc: Class: StorageManager - - - - - - - - - - -
- -

Class: StorageManager

- - - - - - -
- -
- -

StorageManager(storage, options)

- - -
- -
-
- - - - - - -

new StorageManager(storage, options)

- - - - - - -
- Interface for managing contracts, shards, and audits -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
storage - - -StorageAdapter - - - - Storage adapter to use
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
disableReaper - - -Boolean - - - - - - - - - - Don't perform periodic reaping of -stale contracts
logger - - -Object - - - - - - <optional>
- - - - - -
Logger to use for debugging
maxCapacity - - -Number - - - - - - - - - - Max number of bytes to allow in storage
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - -

Extends

- - - - -
    -
  • EventEmitter
  • -
- - - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

clean(callback)

- - - - - - -
- Enumerates all storage contracts and reaps stale data -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

close(callback)

- - - - - - -
- Closes the underlying storage adapter -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

load(hash, callback)

- - - - - - -
- Loads the storage Item at the given key -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
hash - - -String - - - - Shard hash to load data for
callback - - -function - - - - Called with error or StorageItem
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

open(callback)

- - - - - - -
- Opens the underlying storage adapter -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

save(item, callback)

- - - - - - -
- Saves the storage StorageItem at the given key -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item - - -StorageItem - - - - The StorageItem to store
callback - - -function - - - - Called on complete
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/StorageMigration.html b/Storj/core/docs/StorageMigration.html deleted file mode 100644 index d97b66a..0000000 --- a/Storj/core/docs/StorageMigration.html +++ /dev/null @@ -1,425 +0,0 @@ - - - - - JSDoc: Class: StorageMigration - - - - - - - - - - -
- -

Class: StorageMigration

- - - - - - -
- -
- -

StorageMigration(source, target)

- - -
- -
-
- - - - - - -

new StorageMigration(source, target)

- - - - - - -
- Migrates data stored with one StorageAdapter to another -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
source - - -StorageAdapter - - - - The source adapter
target - - -StorageAdapter - - - - The migration destination
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

start()

- - - - - - -
- Starts the migration process -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

stop()

- - - - - - -
- Stops the migration process -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/Transport.html b/Storj/core/docs/Transport.html deleted file mode 100644 index f23765f..0000000 --- a/Storj/core/docs/Transport.html +++ /dev/null @@ -1,943 +0,0 @@ - - - - - JSDoc: Class: Transport - - - - - - - - - - -
- -

Class: Transport

- - - - - - -
- -
- -

Transport(contact, options)

- - -
- -
-
- - - - - - -

new Transport(contact, options)

- - - - - - -
- Custom HTTP transport adapter -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -kad.Contact - - - - Contact object to binding to port
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
logger - - -Logger - - - - Logger for diagnositcs
maxTunnels - - -Number - - - - Number of tunnels to provide to network
doNotTraverseNat - - -Boolean - - - - Do not try to punch out of NAT
tunnelGatewayRange - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
min - - -Number - - - - Min port for gateway bind
max - - -Number - - - - Max port for gateway bind
- -
listenPort - - -Number - - - - Different port for the server to listen on (optional)
storageManager - - -StorageManager - - - -
bridgeClient - - -BridgeClient - - - -
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

createPortMapping(port, callback)

- - - - - - -
- Creates a port mapping with UPnP -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
port - - -Number - - - - The port to forward
callback - - -function - - - - Callback function
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

send(contact, message, callback)

- - - - - - -
- Sends the RPC message to the given contact -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - -
message - - -kad.Message - - - -
callback - - -function - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

connectionLimitReached

- - - - - - -
- Triggered when the max connections limit is reached -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/TriggerManager.html b/Storj/core/docs/TriggerManager.html deleted file mode 100644 index 11cd963..0000000 --- a/Storj/core/docs/TriggerManager.html +++ /dev/null @@ -1,1275 +0,0 @@ - - - - - JSDoc: Class: TriggerManager - - - - - - - - - - -
- -

Class: TriggerManager

- - - - - - -
- -
- -

TriggerManager()

- - -
- -
-
- - - - - - -

new TriggerManager()

- - - - - - -
- Implements behavior triggers as described in SIP-0003 -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • AGPL-3.0
- - - - - -
Source:
-
- - - - - -
See:
-
- -
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

add(nodeID, behaviors)

- - - - - - -
- Adds a trigger handler for the given nodeID and behavior -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
nodeID - - -String -| - -Array - - - - The nodeID(s) to authorize for the trigger -(supports `*` wildcard)
behaviors - - -Object - - - - Behavior name to {TriggerManager~triggerHandler}s
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

process(messageParams, callback)

- - - - - - -
- Process a received trigger message -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
messageParams - - -Object - - - - The received message params
callback - - -TriggerManager~processCallback - - - - Result of trigger process
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

remove(nodeID, behaviors)

- - - - - - -
- Removes a trigger handler for the given nodeID and behavior -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
nodeID - - -String -| - -Array - - - - The nodeID(s) to deauthorize for the trigger
behaviors - - -String -| - -Array - - - - Behavior name to unregister
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -

Type Definitions

- - - - - - - -

destroyTrigger()

- - - - - - -
- Optionally called from trigger handler to unregister the trigger handler -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

processCallback(err, params)

- - - - - - -
- Called upon the processing of a trigger message -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - - Optional error resulting from processing
params - - -Object - - - - Response parameters to send back
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

replyToSender(err, params)

- - - - - - -
- Passed to the trigger handler for replying to the message -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
err - - -Error -| - -null - - - - Optional error to respond with
params - - -Object - - - - Response parameters to return
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

triggerHandler(messageParams, replyToSender, destroyTrigger)

- - - - - - -
- Called when a trigger is received from authorized source -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
messageParams - - -Object - - - - The RPC message parameters
replyToSender - - -TriggerManager~replyToSender - - - - Respond to the trigger
destroyTrigger - - -TriggerManager~destroyTrigger - - - - Unregisters trigger
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/UploadState.html b/Storj/core/docs/UploadState.html deleted file mode 100644 index 3112556..0000000 --- a/Storj/core/docs/UploadState.html +++ /dev/null @@ -1,570 +0,0 @@ - - - - - JSDoc: Class: UploadState - - - - - - - - - - -
- -

Class: UploadState

- - - - - - -
- -
- -

UploadState(options)

- - -
- -
-
- - - - - - -

new UploadState(options)

- - - - - - -
- Internal state machine used by BridgeClient -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - - Bucket ID for the upload state
file - - -String - - - - Path to the file to track
numShards - - -Number - - - - The number of shards to transfer
concurrency - - -Number - - - - The number shards to transfer at once
worker - - -function - - - - The queue task processor function
onComplete - - -function - - - - Reference to callback after complete
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

cleanup()

- - - - - - -
- Unlinks the referenced tmp files -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Events

- - - - - - - -

killed

- - - - - - -
- Triggered when the upload queue has been killed -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/Verification.html b/Storj/core/docs/Verification.html deleted file mode 100644 index 2810a89..0000000 --- a/Storj/core/docs/Verification.html +++ /dev/null @@ -1,408 +0,0 @@ - - - - - JSDoc: Class: Verification - - - - - - - - - - -
- -

Class: Verification

- - - - - - -
- -
- -

Verification(proof)

- - -
- -
-
- - - - - - -

new Verification(proof)

- - - - - - -
- Interface for verifying the result of an audit proof -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
proof - - -Array - - - - The result of ProofStream#getProofResult
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
License:
-
  • LGPL-3.0
- - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

verify(merkleRoot, totalDepth) → {Array}

- - - - - - -
- Verifies the proof given the merkle root and tree depth -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
merkleRoot - - -String - - - - Merkle root
totalDepth - - -Number - - - - Depth of merkle tree
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- result - Array with expected result and verified result -
- - - -
-
- Type -
-
- -Array - - -
-
- - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/assets/tunneling-diagram b/Storj/core/docs/assets/tunneling-diagram deleted file mode 100644 index 1213e26..0000000 --- a/Storj/core/docs/assets/tunneling-diagram +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/Storj/core/docs/assets/tunneling.png b/Storj/core/docs/assets/tunneling.png deleted file mode 100644 index 7058f86de840bdff148facaa1f9ee4d91a4e6df5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41277 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 diff --git a/Storj/core/docs/fonts/OpenSans-Bold-webfont.svg b/Storj/core/docs/fonts/OpenSans-Bold-webfont.svg deleted file mode 100644 index 3ed7be4..0000000 --- a/Storj/core/docs/fonts/OpenSans-Bold-webfont.svg +++ /dev/null @@ -1,1830 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Storj/core/docs/fonts/OpenSans-Bold-webfont.woff b/Storj/core/docs/fonts/OpenSans-Bold-webfont.woff deleted file mode 100644 index 1205787b0ed50db71ebd4f8a7f85d106721ff258..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22432 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 ig3W - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Storj/core/docs/fonts/OpenSans-BoldItalic-webfont.woff b/Storj/core/docs/fonts/OpenSans-BoldItalic-webfont.woff deleted file mode 100644 index ed760c0628b6a0026041f5b8bba466a0471fd2e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23048 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Storj/core/docs/fonts/OpenSans-Italic-webfont.woff b/Storj/core/docs/fonts/OpenSans-Italic-webfont.woff deleted file mode 100644 index ff652e64356b538c001423b6aedefcf1ee66cd17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23188 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 diff --git a/Storj/core/docs/fonts/OpenSans-Light-webfont.svg b/Storj/core/docs/fonts/OpenSans-Light-webfont.svg deleted file mode 100644 index 11a472c..0000000 --- a/Storj/core/docs/fonts/OpenSans-Light-webfont.svg +++ /dev/null @@ -1,1831 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Storj/core/docs/fonts/OpenSans-Light-webfont.woff b/Storj/core/docs/fonts/OpenSans-Light-webfont.woff deleted file mode 100644 index e786074813a27d0a7a249047832988d5bf0fe756..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22248 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 diff --git a/Storj/core/docs/fonts/OpenSans-LightItalic-webfont.eot b/Storj/core/docs/fonts/OpenSans-LightItalic-webfont.eot deleted file mode 100644 index 8f445929ffb03b50e98c2a2f7d831a0cb1b276a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20535 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 Z%0#`NexefPFV?Xj51H#Y#AC7WXn+Jg($4?@ diff --git a/Storj/core/docs/fonts/OpenSans-LightItalic-webfont.svg b/Storj/core/docs/fonts/OpenSans-LightItalic-webfont.svg deleted file mode 100644 index 431d7e3..0000000 --- a/Storj/core/docs/fonts/OpenSans-LightItalic-webfont.svg +++ /dev/null @@ -1,1835 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Storj/core/docs/fonts/OpenSans-LightItalic-webfont.woff b/Storj/core/docs/fonts/OpenSans-LightItalic-webfont.woff deleted file mode 100644 index 43e8b9e6cc061ff17fd2903075cbde12715512b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23400 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
- -

Home

- - - - - - - - -

- - - - - - - - - - - - - - - -
-

Storj

-

Build Status -Coverage Status -NPM -License

-

This package exposes a module that provides all of the tools needed to -integrate with the Storj network. You must have Node.js v6.9.1, Python v2.x.x, -and Git installed. Complete documentation can be found here.

-
npm install storj-lib --save
-
-
-

If you want access to the Storj CLI, -you must install it separately or use the storj -metapackage to install both the core library and command line interface.

-
-

Usage Examples

- -

License

-

Storj Core - Implementation of the Storj protocol for Node.js -Copyright (C) 2016 Storj Labs, Inc

-

This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published -by the Free Software Foundation, either version 3 of the License, or -(at your option) any later version.

-

Certain parts of this program are licensed under the GNU Lesser General -Public License as published by the Free Software Foundation. You can -redistribute it and/or modify it under the terms either version 3 of the -License, or (at your option) any later version.

-

This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details.

-

You should have received a copy of the GNU Affero General Public License -along with this program. If not, see -http://www.gnu.org/licenses/.

-
- - - - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/index.js.html b/Storj/core/docs/index.js.html deleted file mode 100644 index 725a0b3..0000000 --- a/Storj/core/docs/index.js.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - JSDoc: Source: index.js - - - - - - - - - - -
- -

Source: index.js

- - - - - - -
-
-
/**
- * @module storj
- * @license (AGPL-3.0 AND LGPL-3.0)
- */
-
-'use strict';
-
-require('./lib/patches')(); // NB: Apply any monkey patches
-
-/** {@link Network} */
-exports.Network = require('./lib/network');
-
-/** {@link Protocol} */
-exports.Protocol = require('./lib/network/protocol');
-
-/** {@link Renter} */
-exports.Renter = require('./lib/network/renter');
-
-/** {@link Farmer} */
-exports.Farmer = require('./lib/network/farmer');
-
-/** {@link Monitor} */
-exports.Monitor = require('./lib/network/monitor');
-
-/** {@link Transport} */
-exports.Transport = require('./lib/network/transport');
-
-/** {@link ShardServer} */
-exports.ShardServer = require('./lib/network/shard-server');
-
-/** {@link Contact} */
-exports.Contact = require('./lib/network/contact');
-
-/** {@link EncryptStream} */
-exports.EncryptStream = require('./lib/crypto-tools/encrypt-stream');
-
-/** {@link DecryptStream} */
-exports.DecryptStream = require('./lib/crypto-tools/decrypt-stream');
-
-/** {@link FileMuxer} */
-exports.FileMuxer = require('./lib/file-handling/file-muxer');
-
-/** {@link FileDemuxer} */
-exports.FileDemuxer = require('./lib/file-handling/file-demuxer');
-
-/** {@link Contract} */
-exports.Contract = require('./lib/contract');
-
-/** {@link OfferStream} */
-exports.OfferStream = require('./lib/contract/offer-stream');
-
-/** {@link OfferManager} */
-exports.OfferManager = require('./lib/contract/offer-manager');
-
-/** {@link AuditStream} */
-exports.AuditStream = require('./lib/audit-tools/audit-stream');
-
-/** {@link ProofStream} */
-exports.ProofStream = require('./lib/audit-tools/proof-stream');
-
-/** {@link Verification} */
-exports.Verification = require('./lib/audit-tools/verification');
-
-/** {@link StorageManager} */
-exports.StorageManager = require('./lib/storage/manager');
-
-/** {@link StorageAdapter} */
-exports.StorageAdapter = require('./lib/storage/adapter');
-
-/** {@link StorageMigration} */
-exports.StorageMigration = require('./lib/storage/migration');
-
-/** {@link EmbeddedStorageAdapter} */
-exports.EmbeddedStorageAdapter = require('./lib/storage/adapters/embedded');
-
-/** {@link RAMStorageAdapter} */
-exports.RAMStorageAdapter = require('./lib/storage/adapters/ram');
-
-/** {@link StorageItem} */
-exports.StorageItem = require('./lib/storage/item');
-
-/** {@link DataCipherKeyIv} */
-exports.DataCipherKeyIv = require('./lib/crypto-tools/cipher-key-iv');
-
-/** {@link DeterministicKeyIv} */
-exports.DeterministicKeyIv = require('./lib/crypto-tools/deterministic-key-iv');
-
-/** {@link KeyPair} */
-exports.KeyPair = require('./lib/crypto-tools/keypair');
-
-/** {@link KeyRing} */
-exports.KeyRing = require('./lib/crypto-tools/keyring');
-
-/** {@link BridgeClient} */
-exports.BridgeClient = require('./lib/bridge-client');
-
-/** {@link module:storj/version} */
-exports.version = require('./lib/version');
-
-/** {@link module:storj/constants} */
-exports.constants = require('./lib/constants');
-
-/** {@link module:storj/utils} */
-exports.utils = require('./lib/utils');
-
-/** {@link module:storj/deps} */
-exports.deps = require('./lib/deps');
-
-/** {@link module:storj/sips} */
-exports.sips = require('./lib/sips');
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_audit-tools_audit-stream.js.html b/Storj/core/docs/lib_audit-tools_audit-stream.js.html deleted file mode 100644 index e3f68a1..0000000 --- a/Storj/core/docs/lib_audit-tools_audit-stream.js.html +++ /dev/null @@ -1,223 +0,0 @@ - - - - - JSDoc: Source: lib/audit-tools/audit-stream.js - - - - - - - - - - -
- -

Source: lib/audit-tools/audit-stream.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var crypto = require('crypto');
-var constants = require('../constants');
-var MerkleTree = require('mtree');
-var utils = require('../utils');
-var stream = require('readable-stream');
-var inherits = require('util').inherits;
-
-/**
- * Represents a streaming audit challenge generator
- * @constructor
- * @license LGPL-3.0
- * @param {Number} audits - Total number of challenges to generate
- * @emits AuditStream#finish
- */
-function AuditStream(audits) {
-  if (!(this instanceof AuditStream)) {
-    return new AuditStream(audits);
-  }
-
-  assert(typeof audits === 'number', 'Invalid number of audits supplied');
-  assert(!Number.isNaN(audits), 'Invalid number of audits supplied');
-  assert(Number.isFinite(audits), 'Invalid number of audits supplied');
-
-  this._audits = audits;
-  this._finished = false;
-  this._challenges = [];
-  this._inputs = this._prepareChallenges();
-
-  stream.Writable.call(this);
-  this.on('finish', this._generateTree.bind(this));
-}
-
-/**
- * Triggered when the stream has ended
- * @event AuditStream#finish
- */
-
-inherits(AuditStream, stream.Writable);
-
-/**
- * Returns the bottom leaves of the merkle tree for sending to farmer
- * @returns {Array} leaves - Bottom merkle leaves of audit tree
- */
-AuditStream.prototype.getPublicRecord = function() {
-  assert(this._finished, 'Challenge generation is not finished');
-
-  return this._tree.level(this._tree.levels() - 1)
-    .map((i) => i.toString('hex'));
-};
-
-/**
- * Returns the challenges, the tree depth, and merkle root
- * @returns {Object} challenge - Private audit record with challenges
- */
-AuditStream.prototype.getPrivateRecord = function() {
-  assert(this._finished, 'Challenge generation is not finished');
-
-  return {
-    root: this._tree.root(),
-    depth: this._tree.levels(),
-    challenges: this._challenges.map((i) => i.toString('hex'))
-  };
-};
-
-/**
- * Implements the underlying write method
- * @private
- */
-AuditStream.prototype._write = function(bytes, encoding, next) {
-  var self = this;
-
-  this._inputs.forEach(function(input, i) {
-    if (i < self._audits) {
-      input.update(bytes);
-    }
-  });
-  next();
-};
-
-/**
- * Prepares the challenge hasher instances
- * @private
- */
-AuditStream.prototype._prepareChallenges = function() {
-  var iterations = 0;
-  var inputs = [];
-
-  while (iterations < this._audits) {
-    var challenge = this._generateChallenge();
-    var input = this._createResponseInput(challenge);
-
-    this._challenges.push(challenge);
-    inputs.push(input);
-
-    iterations++;
-  }
-
-  while (iterations < utils.getNextPowerOfTwo(this._audits)) {
-    inputs.push(utils.rmd160sha256b(''));
-    iterations++;
-  }
-
-  return inputs;
-};
-
-/**
- * Generate the audit merkle tree from a series of challenges
- * @private
- */
-AuditStream.prototype._generateTree = function() {
-  var self = this;
-
-  this._finished = true;
-
-  this._tree = new MerkleTree(this._inputs.map(function(input, i) {
-    if (i >= self._audits) {
-      return input;
-    } else {
-      const rmd1 = crypto.createHash('rmd160').update(input.digest()).digest();
-      const sha = crypto.createHash('sha256').update(rmd1).digest();
-      const rmd2 = crypto.createHash('rmd160').update(sha).digest();
-      return rmd2;
-    }
-  }), utils.rmd160sha256b);
-};
-
-/**
- * Generate a random challenge buffer
- * @private
- * @returns {String} Hex encoded random bytes
- */
-AuditStream.prototype._generateChallenge = function() {
-  return crypto.randomBytes(constants.AUDIT_BYTES);
-};
-
-/**
- * Create a challenge response input to merkle tree
- * @private
- */
-AuditStream.prototype._createResponseInput = function(challenge) {
-  return crypto.createHash('sha256').update(challenge);
-};
-
-/**
- * Returns a new instance from the predefined challenges and tree
- * @param {Array} challenges - The precomputed challenges
- * @param {Array} tree - The bottom leaves of the existing merkle tree
- * @returns {AuditStream}
- */
-AuditStream.fromRecords = function(challenges, tree) {
-  assert(Array.isArray(challenges), 'Invalid challenges supplied');
-  assert(Array.isArray(tree), 'Invalid tree supplied');
-  assert(
-    tree.length === utils.getNextPowerOfTwo(challenges.length),
-    'Challenges and tree do not match'
-  );
-
-  tree = tree.map((i) => Buffer.from(i, 'hex'));
-
-  var auditor = new AuditStream(challenges.length);
-
-  auditor._challenges = challenges;
-  auditor._tree = new MerkleTree(tree, utils.rmd160sha256b);
-  auditor._finished = true;
-
-  return auditor;
-};
-
-module.exports = AuditStream;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_audit-tools_proof-stream.js.html b/Storj/core/docs/lib_audit-tools_proof-stream.js.html deleted file mode 100644 index 288c665..0000000 --- a/Storj/core/docs/lib_audit-tools_proof-stream.js.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - JSDoc: Source: lib/audit-tools/proof-stream.js - - - - - - - - - - -
- -

Source: lib/audit-tools/proof-stream.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var MerkleTree = require('mtree');
-var utils = require('../utils');
-var inherits = require('util').inherits;
-var stream = require('readable-stream');
-var crypto = require('crypto');
-
-/**
- * Provides interface for proving possession of a file for an
- * {@link AuditStream}
- * @constructor
- * @license LGPL-3.0
- * @param {Array} merkleLeaves - Bottom leaves of the audit merkle tree
- * @param {String} hexChallenge - The challenge data in hex to prepend to shard
- */
-function ProofStream(leaves, challenge) {
-  if (!(this instanceof ProofStream)) {
-    return new ProofStream(leaves, challenge);
-  }
-
-  assert(Array.isArray(leaves), 'Merkle leaves must be an array');
-  assert.ok(challenge, 'Invalid challenge supplied');
-
-  this._tree = new MerkleTree(this._generateLeaves(leaves),
-                              utils.rmd160sha256b);
-  if (!Buffer.isBuffer(challenge)) {
-    this._challenge = Buffer.from(challenge, 'hex');
-  } else {
-    this._challenge = challenge;
-  }
-  this._hasher = crypto.createHash('sha256').update(this._challenge);
-  this._proof = null;
-
-  stream.Transform.call(this, { objectMode: true });
-}
-
-inherits(ProofStream, stream.Transform);
-
-/**
- * Returns the generated proof structure
- * @return {Array}
- */
-ProofStream.prototype.getProofResult = function() {
-  assert(Array.isArray(this._proof), 'Proof generation is not complete');
-
-  return this._proof;
-};
-
-/**
- * Handles writing the shard data to the proof stream
- * @private
- */
-ProofStream.prototype._transform = function(chunk, encoding, next) {
-  this._hasher.update(chunk, encoding);
-  next();
-};
-
-/**
- * Generates the proof from the read data
- * @private
- */
-ProofStream.prototype._flush = function(done) {
-  try {
-    this._generateProof();
-  } catch (err) {
-    return done(err);
-  }
-
-  this.push(this.getProofResult());
-  done();
-};
-
-ProofStream.prototype._findMatchIndex = function(leaves, leaf) {
-  var challengenum = -1;
-  for (let i = 0; i < leaves.length; i++) {
-    if (Buffer.compare(leaves[i], leaf) === 0) {
-      challengenum = i;
-      break;
-    }
-  }
-  return challengenum;
-}
-
-/**
- * Calculate audit response
- * @private
- * @param {String} challenge - Challenge string sent by auditor
- * @returns {Array} result - Challenge response
- */
-ProofStream.prototype._generateProof = function() {
-
-  var response = utils.rmd160b(this._hasher.digest());
-  var leaves = this._tree.level(this._tree.levels() - 1);
-
-  const leaf = utils.rmd160sha256b(response);
-
-  var challengenum = this._findMatchIndex(leaves, leaf);
-
-  assert(challengenum !== -1, 'Failed to generate proof');
-
-  var branches = [response];
-
-  for (var i = (this._tree.levels() - 1); i > 0; i--) {
-    var level = this._tree.level(i);
-
-    if (challengenum % 2 === 0) {
-      branches = [branches, level[challengenum + 1]];
-    } else {
-      branches = [level[challengenum - 1], branches];
-    }
-
-    challengenum = Math.floor(challengenum / 2);
-  }
-
-  this._proof = branches;
-};
-
-/**
- * Generates the bottom leaves of the tree to the next power of two
- * @private
- * @param {Array} leaves
- */
-ProofStream.prototype._generateLeaves = function(leaves) {
-  var numEmpty = utils.getNextPowerOfTwo(leaves.length) - leaves.length;
-  var emptyLeaves = [];
-
-  for (var i = 0; i < numEmpty; i++) {
-    emptyLeaves.push(utils.rmd160sha256b(''));
-  }
-
-  leaves = leaves.map((i) => Buffer.from(i, 'hex'))
-
-  return leaves.concat(emptyLeaves);
-};
-
-module.exports = ProofStream;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_audit-tools_verification.js.html b/Storj/core/docs/lib_audit-tools_verification.js.html deleted file mode 100644 index 79feea2..0000000 --- a/Storj/core/docs/lib_audit-tools_verification.js.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - JSDoc: Source: lib/audit-tools/verification.js - - - - - - - - - - -
- -

Source: lib/audit-tools/verification.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var utils = require('../utils');
-
-/**
- * Interface for verifying the result of an audit proof
- * @constructor
- * @license LGPL-3.0
- * @param {Array} proof - The result of {@link ProofStream#getProofResult}
- */
-function Verification(proof) {
-  if (!(this instanceof Verification)) {
-    return new Verification(proof);
-  }
-
-  assert(Array.isArray(proof), 'Proof must be an array');
-
-  this._proof = proof;
-}
-
-/**
- * Extracts the challenge response from the proof
- * @private
- * @param {Array} response - Challenge response received from farmer
- * @returns {String} leaf
- */
-Verification.prototype._getChallengeResponse = function(tuple) {
-  var data = tuple || this._proof;
-
-  if (data.length === 1) {
-    return utils.rmd160sha256b(data[0]);
-  }
-
-  if (Array.isArray(data[0])) {
-    return this._getChallengeResponse(data[0]);
-  } else {
-    return this._getChallengeResponse(data[1]);
-  }
-};
-
-/**
- * Verifies the proof given the merkle root and tree depth
- * @param {String} merkleRoot - Merkle root
- * @param {Number} totalDepth - Depth of merkle tree
- * @returns {Array} result - Array with expected result and verified result
- */
-Verification.prototype.verify = function(root, totaldepth) {
-  function _collapse(proof, leaf, depth) {
-    if (depth === 0) {
-      assert(proof.length === 1, 'Invalid proof structure');
-      const proofhash = utils.rmd160sha256b(proof[0]);
-      assert(Buffer.compare(proofhash, leaf) === 0, 'Invalid proof value');
-      return leaf;
-    }
-
-    var hashL, hashR;
-
-    if (Array.isArray(proof[0])) {
-      hashL = _collapse(proof[0], leaf, depth - 1);
-    } else {
-      hashL = proof[0];
-    }
-
-    if (Array.isArray(proof[1])) {
-      hashR = _collapse(proof[1], leaf, depth - 1);
-    } else {
-      hashR = proof[1];
-    }
-
-    return utils.rmd160sha256b(Buffer.concat([hashL, hashR]));
-  }
-
-  return [
-    _collapse(this._proof, this._getChallengeResponse(), totaldepth - 1),
-    root
-  ];
-};
-
-module.exports = Verification;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_bridge-client_blacklist.js.html b/Storj/core/docs/lib_bridge-client_blacklist.js.html deleted file mode 100644 index f362f15..0000000 --- a/Storj/core/docs/lib_bridge-client_blacklist.js.html +++ /dev/null @@ -1,213 +0,0 @@ - - - - - JSDoc: Source: lib/bridge-client/blacklist.js - - - - - - - - - - -
- -

Source: lib/bridge-client/blacklist.js

- - - - - - -
-
-
'use strict';
-
-var concat = require('concat-stream');
-var once = require('once');
-
-/**
- * Manage a blacklist file containing an object with key value pairs of
- * nodeids: timestamp
- * @constructor
- * @license LGPL-3.0
- * @see https://github.com/storj/bridge
- * @param {Object} options.logger - Logger instance
- * @param {Object} options.store - The store that blacklist enteries will be
- * persisted to. This object must be compatible with the API of
- * {@link https://github.com/maxogden/abstract-blob-store|abstract-blob-store}
- */
-function Blacklist(options) {
-  if (!(this instanceof Blacklist)) {
-    return new Blacklist(options);
-  }
-
-  this.blacklistKey = '.blacklist';
-  this._store = options.store;
-  this._logger = options.logger;
-  // creating queue to prevent race conditions;
-  // only write one json object at a time
-  this._next = [];
-  this._writing = [];
-}
-
-Blacklist.TTL = 86400000;
-
-Blacklist.prototype._queueForWriting = function(cb) {
-  cb = cb || function() {};
-
-  if (this._writing.length > 0) {
-    return this._next.push(cb);
-  }
-  this._writing.push(cb);
-  this._saveToStore(this._doneWriting.bind(this));
-};
-
-Blacklist.prototype._doneWriting = function(e) {
-  this._writing.forEach(function(cb) {
-    cb(e);
-  });
-
-  this._writing = this._next;
-  this._next = [];
-  if (this._writing.length > 0) {
-    this._saveToStore(this._doneWriting.bind(this));
-  }
-};
-
-/**
- * Push node to blacklist
- * @param {String} nodeid - Node id to be added to blacklist
- */
-Blacklist.prototype.push = function(nodeid, cb) {
-  var self = this;
-  self._logger.info('Adding NodeID %s to blacklist', nodeid);
-  self._getBlacklist(function() {
-    self.blacklist[nodeid] = Date.now();
-    self._queueForWriting(cb);
-  });
-};
-
-/**
- * Lazy load blacklist
- * @private
- */
-Blacklist.prototype._getBlacklist = function(cb) {
-  var self = this;
-
-  // If we already have a blacklist, return it
-  if (self.blacklist !== undefined) {
-    return cb(null, self.blacklist);
-  }
-
-  // Otherwise load it from the store
-  return self._loadFromStore(function() {
-    return cb(null, self.blacklist);
-  });
-};
-
-/**
- * Save blacklist to Store
- * @private
- */
-Blacklist.prototype._saveToStore = function(cb) {
-  cb = once(cb);
-  var ws = this._store.createWriteStream(this.blacklistKey);
-  ws.on('error', cb)
-  ws.end(JSON.stringify(this.blacklist), cb);
-};
-
-/**
- * Read blacklist from Store and Reap old nodeids
- * @private
- */
-Blacklist.prototype._loadFromStore = function(cb) {
-  var self = this;
-  cb = once(cb);
-  var rs = self._store.createReadStream(self.blacklistKey);
-  // If the file doesn't exist, return an empty object.
-  rs.on('error', function() {
-    self.blacklist = {};
-    cb(null, self.blacklist);
-  });
-
-  // Get the stream as a string
-  var cs = concat({encoding: 'string'}, function(data) {
-    // default to an empty object
-    self.blacklist = {};
-    // If the file was empty, return our default. This prevents an error from
-    // being displayed to the user.
-    if (data === '') {
-      return cb(null, self.blacklist);
-    }
-
-    try {
-      self.blacklist = JSON.parse(data);
-    } catch (e) {
-      self._logger.warn('Corrupt blacklist data, using a fresh object.');
-    }
-
-    // Cleanup stale references and return the file
-    return cb(null, self._reap(self.blacklist));
-  });
-  cs.on('error', cb);
-  rs.pipe(cs);
-};
-
-/**
-  * Reap old nodeids from blacklist
-  * @private
-  */
-Blacklist.prototype._reap = function(blacklist) {
-  var now = Date.now();
-
-  for (var nodeid in blacklist) {
-    if ((now - blacklist[nodeid]) > Blacklist.TTL) {
-      delete blacklist[nodeid];
-    }
-  }
-
-  this.blacklist = blacklist;
-
-  return blacklist;
-};
-
-/**
- * Return list of blacklisted nodeids
- */
-Blacklist.prototype.toObject = function(cb) {
-  var self = this;
-  self._getBlacklist(function() {
-    return cb(null, Object.keys(self._reap(self.blacklist)));
-  });
-};
-
-module.exports = Blacklist;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_bridge-client_exchange-report.js.html b/Storj/core/docs/lib_bridge-client_exchange-report.js.html deleted file mode 100644 index a2d9eaf..0000000 --- a/Storj/core/docs/lib_bridge-client_exchange-report.js.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - JSDoc: Source: lib/bridge-client/exchange-report.js - - - - - - - - - - -
- -

Source: lib/bridge-client/exchange-report.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-
-/**
- * Represents a report to a bridge regarding the result of a shard exchange
- * @constructor
- * @param {Object} options
- * @param {String} options.reporterId
- * @param {String} [options.farmerId]
- * @param {String} [options.clientId]
- */
-function ExchangeReport(options = {}) {
-  /* eslint complexity: [2, 7] */
-  if (!(this instanceof ExchangeReport)) {
-    return new ExchangeReport(options);
-  }
-
-  assert(options.reporterId, 'Invalid reporterId');
-
-  this._r = {
-    dataHash: options.dataHash || null,
-    reporterId: options.reporterId,
-    farmerId: options.farmerId,
-    clientId: options.clientId,
-    exchangeStart: options.exchangeStart || null,
-    exchangeEnd: options.exchangeEnd || null,
-    exchangeResultCode: options.exchangeResultCode || null,
-    exchangeResultMessage: options.exchangeResultMessage || null
-  };
-}
-
-ExchangeReport.SUCCESS = 1000;
-ExchangeReport.FAILURE = 1100;
-
-/**
- * Starts recording duration of exchange
- * @param {String} dataHash - The shard hash as reference
- */
-ExchangeReport.prototype.begin = function(dataHash) {
-  assert(dataHash, 'You must supply a dataHash to begin an exchange report');
-  this._r.dataHash = dataHash;
-  this._r.exchangeStart = Date.now();
-};
-
-/**
- * Ends the recording time a set result code and message
- * @param {Number} resultCode - Exchange result code
- * @param {String} resultMessage - Exchange result message
- */
-ExchangeReport.prototype.end = function(resultCode, resultMessage) {
-  assert(resultCode, 'You must supply a result code');
-  assert(resultMessage, 'You must supply a result message');
-  this._r.exchangeEnd = Date.now();
-  this._r.exchangeResultCode = resultCode;
-  this._r.exchangeResultMessage = resultMessage;
-};
-
-/**
- * Returns a plain report object
- * @returns {Object}
- */
-ExchangeReport.prototype.toObject = function() {
-  return JSON.parse(JSON.stringify(this._r));
-};
-
-module.exports = ExchangeReport;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_bridge-client_index.js.html b/Storj/core/docs/lib_bridge-client_index.js.html deleted file mode 100644 index 85a8d80..0000000 --- a/Storj/core/docs/lib_bridge-client_index.js.html +++ /dev/null @@ -1,1396 +0,0 @@ - - - - - JSDoc: Source: lib/bridge-client/index.js - - - - - - - - - - -
- -

Source: lib/bridge-client/index.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var fs = require('fs');
-var querystring = require('querystring');
-var request = require('request');
-var utils = require('../utils');
-var FileDemuxer = require('../file-handling/file-demuxer');
-var FileMuxer = require('../file-handling/file-muxer');
-var AuditStream = require('../audit-tools/audit-stream');
-var Contact = require('../network/contact');
-var crypto = require('crypto');
-var path = require('path');
-var mime = require('mime');
-var uuid = require('node-uuid');
-var merge = require('merge');
-var Logger = require('kad-logger-json');
-var EventEmitter = require('events').EventEmitter;
-var UploadState = require('./upload-state');
-var Blacklist = require('./blacklist');
-var stream = require('readable-stream');
-var async = require('async');
-var ExchangeReport = require('./exchange-report');
-var FsBlobStore = require('fs-blob-store');
-var once = require('once');
-
-/**
- * Represents a client interface to a given bridge server
- * @constructor
- * @license LGPL-3.0
- * @see https://github.com/storj/bridge
- * @see https://storj.io/api.html
- * @param {String} [uri=https://api.storj.io] - API base URI
- * @param {Object} options
- * @param {KeyPair} options.keyPair - KeyPair instance for request signing
- * @param {Object} options.logger - Logger instance
- * @param {Object} options.requestTimeout - Timeout when making requests to the
- * bridge
- * @param {Number} options.transferConcurrency - Upload concurrency limit
- * @param {Number} options.transferRetries - Limit number of shard transfer
- * retries before getting a new contract
- * @param {Object} options.basicAuth
- * @param {String} options.basicAuth.email - Email address for HTTP basic auth
- * @param {String} options.basicAuth.password - Password for HTTP basic auth
- * @param {String} [options.blacklistFolder] - The folder that blacklist
- * entries will be persisted to if using the default fs-store
- * @param {Object} [options.store] - The store that blacklist enteries will be
- * persisted to. This object must be compatible with the API of
- * {@link https://github.com/maxogden/abstract-blob-store|abstract-blob-store}
- */
-function BridgeClient(uri, options) {
-  if (!(this instanceof BridgeClient)) {
-    return new BridgeClient(uri, options);
-  }
-
-  this._options = this._checkOptions(uri, options);
-  this._blacklist = new Blacklist(this._options);
-  this._logger = this._options.logger;
-  this._transferConcurrency = this._options.transferConcurrency;
-  this._store = this._options.store;
-}
-
-BridgeClient.DEFAULTS = {
-  baseURI: 'https://api.storj.io',
-  logger: new Logger(0),
-  transferConcurrency: 3,
-  transferRetries: 0,
-  requestTimeout: 30000,
-  retryThrottle: 500
-};
-
-/**
- * Check the options supplied to the constructor
- * @private
- */
-BridgeClient.prototype._checkOptions = function(uri, options) {
-  options = options || {
-    baseURI: uri || process.env.STORJ_BRIDGE || BridgeClient.DEFAULTS.baseURI
-  };
-  options.baseURI = options.baseURI || uri;
-  options = merge(Object.create(BridgeClient.DEFAULTS), options);
-  assert.ok(utils.validateLogger(options.logger), 'Invalid logger supplied');
-
-  return this._configureBlacklist(options);
-};
-
-/**
- * Setup the store for our blacklist
- * @private
- */
-BridgeClient.prototype._configureBlacklist = function(options) {
-  // If we were not given a store, STORJ_TEMP or os.tmpdir. This is
-  // intentionally left out of BridgeClient.DEFAULTS since utils.tmpdir()
-  // accesses the filesystem, breaking storj-lib's compatibility with browsers
-  if (options.store === undefined) {
-    if (options.blacklistFolder === undefined) {
-      options.blacklistFolder = utils.tmpdir();
-    }
-    options.store = new FsBlobStore(options.blacklistFolder);
-  }
-
-  // Only test for the parts of abstract-blob-store that we need
-  assert.ok(typeof options.store.createWriteStream === 'function',
-    'Supplied store must implement abstract-blob-store');
-
-  assert.ok(typeof options.store.createReadStream === 'function',
-    'Supplied store must implement abstract-blob-store');
-
-  assert.ok(typeof options.store.exists === 'function',
-    'Supplied store must implement abstract-blob-store');
-
-  return options;
-};
-
-/**
- * Get the remote Storj Bridge API documentation and version as JSON
- * @param {Function} callback
- */
-BridgeClient.prototype.getInfo = function(callback) {
-  return this._request('GET', '/', {}, callback);
-};
-
-/**
- * Fetches the list of known contacts filtered according to the options
- * @param {Object} options
- * @param {Number} options.page - The page number of the contact list to fetch
- * @param {Boolean} options.connected - Filter results by connection status
- * @param {Function} callback
- */
-BridgeClient.prototype.getContactList = function(options, callback) {
-  return this._request('GET', '/contacts', options, callback);
-};
-
-/**
- * Get the contact information for the given nodeID
- * @param {String} nodeId - The nodeID of the contact
- * @param {Function} callback
- */
-BridgeClient.prototype.getContactByNodeId = function(nodeId, callback) {
-  return this._request('GET', '/contacts/' + nodeId, {}, callback);
-};
-
-/**
- * Registers a user account
- * @param {Object} options
- * @param {String} options.email - Email address for verification email
- * @param {String} options.password - Password to register (auto hashed)
- * @param {String} options.redirect - URL to redirect to after verification
- * @param {String} options.pubkey - Optional ECDSA public key to register
- * @param {Function} callback
- */
-BridgeClient.prototype.createUser = function(options, callback) {
-  return this._request('POST', '/users', {
-    email: options.email,
-    password: utils.sha256(options.password, 'utf8'),
-    redirect: options.redirect,
-    pubkey: options.pubkey
-  }, callback);
-};
-
-/**
- * Deactivates a user account
- * @param {Object} options
- * @param {String} options.email - Email address of user to deactivate
- * @param {String} options.redirect - URL to redirect after verification
- * @param {Function} callback
- */
-BridgeClient.prototype.destroyUser = function(options, callback) {
-  return this._request('DELETE', '/users/' + options.email, {
-    redirect: options.redirect
-  }, callback);
-};
-
-/**
- * Requests a password reset
- * @param {Object} options
- * @param {String} options.email - Email address of user to reset password
- * @param {String} options.password - The cleartext password to reset to
- * @param {String} options.redirect - URL to redirect adter confirmation
- * @param {Function} callback
- */
-BridgeClient.prototype.resetPassword = function(options, callback) {
-  return this._request('PATCH', '/users/' + options.email, {
-    password: utils.sha256(options.password, 'utf8'),
-    redirect: options.redirect
-  }, callback);
-};
-
-/**
- * Returns list of associated public keys
- * @param {Function} callback
- */
-BridgeClient.prototype.getPublicKeys = function(callback) {
-  return this._request('GET', '/keys', {}, callback);
-};
-
-/**
- * Registers a public key for the caller
- * @param {String} pubkey - Hex encoded ECDSA (secp256k1) public key
- * @param {Function} callback
- */
-BridgeClient.prototype.addPublicKey = function(pubkey, callback) {
-  return this._request('POST', '/keys', { key: pubkey }, callback);
-};
-
-/**
- * Disassociates the public key from the caller
- * @param {String} pubkey - Hex encoded ECDSA (secp256k1) public key
- * @param {Function} callback
- */
-BridgeClient.prototype.destroyPublicKey = function(pubkey, callback) {
-  return this._request('DELETE', '/keys/' + pubkey, {}, callback);
-};
-
-/**
- * Lists the caller's file buckets
- * @param {Function} callback
- */
-BridgeClient.prototype.getBuckets = function(callback) {
-  return this._request('GET', '/buckets', {}, callback);
-};
-
-/**
- * Returns the bucket information by ID
- * @param {String} id - Unique bucket ID
- * @param {Function} callback
- */
-BridgeClient.prototype.getBucketById = function(id, callback) {
-  return this._request('GET', '/buckets/' + id, {}, callback);
-};
-
-/**
- * Creates a new file bucket
- * @param {Object} data - Bucket parameters for creation
- * @param {Function} callback
- */
-BridgeClient.prototype.createBucket = function(data, callback) {
-  return this._request('POST', '/buckets', data, callback);
-};
-
-/**
- * Removes the bucket
- * @param {String} id - Unique bucket ID
- * @param {Function} callback
- */
-BridgeClient.prototype.destroyBucketById = function(id, callback) {
-  return this._request('DELETE', '/buckets/' + id, {}, callback);
-};
-
-/**
- * Updates the bucket
- * @param {String} id - Unique bucket ID
- * @param {Object} updates - Bucket update parameters
- * @param {Function} callback
- */
-BridgeClient.prototype.updateBucketById = function(id, updates, callback) {
-  return this._request('PATCH', '/buckets/' + id, updates, callback);
-};
-
-/**
- * Lists the files stored in a bucket
- * @param {String} id - Unique bucket ID
- * @param {Function} callback
- */
-BridgeClient.prototype.listFilesInBucket = function(id, callback) {
-  return this._request('GET', '/buckets/' + id + '/files', {}, callback);
-};
-
-/**
- * Create bucket token
- * @param {String} id - Unique bucket ID
- * @param {String} operation - PUSH or PULL (file operation)
- * @param {Function} callback
- */
-BridgeClient.prototype.createToken = function(id, operation, callback) {
-  return this._request('POST', '/buckets/' + id + '/tokens', {
-    operation: operation
-  }, callback);
-};
-
-/**
- * Removes a file from a bucket
- * @param {String} id - Unique bucket ID
- * @param {String} file - ID of the file to remove from bucket
- * @param {Function} callback
- */
-BridgeClient.prototype.removeFileFromBucket = function(id, file, callback) {
-  return this._request(
-    'DELETE',
-    '/buckets/' + id + '/files/' + file,
-    {},
-    callback
-  );
-};
-
-/**
- * Creates a file staging frame
- * @param {Function} callback
- */
-BridgeClient.prototype.createFileStagingFrame = function(callback) {
-  return this._request('POST', '/frames', {}, callback);
-};
-
-/**
- * List all of the file staging frames
- * @param {Function} callback
- */
-BridgeClient.prototype.getFileStagingFrames = function(callback) {
-  return this._request('GET', '/frames', {}, callback);
-};
-
-/**
- * Get info about a file (bucket, mimetype, filename, frame, size, id)
- * @param {String} bucket - bucket id
- * @param {String} file - file id
- * @param {Function} callback
- */
-BridgeClient.prototype.getFileInfo = function(bucket, file, callback) {
-  var path = '/buckets/' + bucket + '/files/' + file + '/info';
-  return this._request('GET', path, {}, callback);
-};
-
-/**
- * Gets the frame by it's ID
- * @param {String} bucket - Unique bucket ID
-  * @param {String} file - Unique file ID
- * @param {Function} callback
- */
-BridgeClient.prototype.getFrameFromFile = function(bucket, file, callback) {
-  var self = this;
-
-  self.getFileInfo(bucket, file, function(err, file) {
-    if (err) {
-      return callback(err);
-    }
-
-    function _extractFrame(err, frame) {
-      if (err) {
-        return callback(err);
-      }
-
-      callback(null, frame);
-    }
-
-    return self.getFileStagingFrameById(file.frame, _extractFrame);
-  });
-};
-
-/**
- * Fetch an existing file staging frame by it's ID
- * @param {String} id - Unique frame ID
- * @param {Function} callback
- */
-BridgeClient.prototype.getFileStagingFrameById = function(id, callback) {
-  return this._request('GET', '/frames/' + id, {}, callback);
-};
-
-/**
- * Destroy an existing file staging frame
- * @param {String} id - Unique frame ID
- * @param {Function} callback
- */
-BridgeClient.prototype.destroyFileStagingFrameById = function(id, callback) {
-  return this._request('DELETE', '/frames/' + id, {}, callback);
-};
-
-/**
- * Adds the given shard metadata to the file staging frame
- * @param {String} id - Unique frame ID
- * @param {Object} shard - The shard metadata
- * @param {Object} options
- * @param {Number} options.retry - Retry the request this many times if failed
- * @param {Function} callback
- */
-BridgeClient.prototype.addShardToFileStagingFrame = function(f, s, opt, cb) {
-  var self = this;
-  var retries = 0;
-  var pendingReq = null;
-
-  if (typeof arguments[2] === 'function') {
-    cb = opt;
-    opt = { retry: 24 };
-  }
-
-  function _addShard() {
-    self._logger.info(
-      'Querying bridge for contract for %s (retry: %s)',
-      s.hash,
-      retries
-    );
-
-    pendingReq = self._request('PUT', '/frames/' + f, s, function(err, result) {
-      if (err) {
-        if (opt.retry > retries) {
-          retries++;
-          return _addShard();
-        }
-
-        return cb(err);
-      }
-
-      cb(null, result);
-    });
-  }
-
-  _addShard();
-
-  return {
-    cancel: function() {
-      opt.retry = 0;
-      pendingReq.abort();
-    }
-  };
-};
-
-/**
- * Instructs the bridge to find N mirroring farmers for redundancy
- * @param {String} id - Unique bucket ID
- * @param {String} token - Token from {@link BridgeClient#createToken}
- * @param {String} file - Path to file to store
- * @param {Number} concurrency - Upload concurrency
- * @param {Function} callback
- */
-BridgeClient.prototype.replicateFileFromBucket = function(id, file, n, cb) {
-  if (typeof n === 'function') {
-    cb = n;
-    n = undefined;
-  }
-
-  return this._request('POST', '/buckets/' + id + '/mirrors', {
-    file: file,
-    redundancy: n
-  }, cb);
-};
-
-/**
- * Returns the established and available mirrors for a given file
- * @param {String} id - Unique bucket ID
- * @param {String} file - Unique file ID
- * @param {Function} callback
- */
-BridgeClient.prototype.listMirrorsForFile = function(id, file, cb) {
-  return this._request(
-    'GET',
-    '/buckets/' + id + '/files/' + file + '/mirrors',
-    {},
-    cb
-  );
-};
-
-/**
- * Stores a file in the bucket
- * @param {String} id - Unique bucket ID
- * @param {String} token - Token from {@link BridgeClient#createToken}
- * @param {String} file - Path to file to store
- * @param {Function} callback
- */
-// eslint-disable-next-line max-params
-BridgeClient.prototype.storeFileInBucket = function(id, token, file, opts, cb) {
-  assert(typeof file === 'string' || file.readable,
-    'File name must be a string or readable stream.'
-  );
-  var self = this;
-  if (typeof opts === 'function') {
-    cb = opts;
-    opts = {};
-  }
-  cb = once(cb);
-
-  var fileName = opts.fileName;
-  var fileSize = opts.fileSize || 0;
-
-  if (file.constructor === String) {
-    fileName = path.basename(file).split('.crypt')[0];
-    fileSize = fs.statSync(file).size;
-    file = fs.createReadStream(file);
-  }
-
-  self._startDemuxing({
-    file: file,
-    fileName: fileName,
-    fileSize: fileSize,
-    id: id,
-    token: token
-  }, cb);
-};
-
-BridgeClient.prototype._startDemuxing = function(options, cb) {
-  var self = this;
-  const {file, fileSize, fileName, id} = options;
-
-  if (fileSize <= 0) {
-    return cb(new Error(fileSize +' bytes is not a supported file size.'));
-  }
-
-  var shardSize = FileDemuxer.getOptimalShardSize(
-    {
-      fileSize: fileSize,
-      shardConcurrency: this._transferConcurrency
-    }
-  );
-
-  var uploadState = new UploadState({
-    id: id,
-    file: file,
-    fileName: fileName,
-    onComplete: cb,
-    worker: this._shardUploadWorker.bind(this),
-    numShards: Math.ceil(fileSize / shardSize),
-    concurrency: this._transferConcurrency
-  });
-
-  function _createFileStagingFrame() {
-    self._logger.info('Creating file staging frame');
-    self.createFileStagingFrame(function(err, frame) {
-      if (err) {
-        self._logger.error(err.message);
-        return cb(err);
-      }
-
-      var demuxer = new FileDemuxer(uploadState.file, {
-        shardSize: shardSize,
-        fileSize: fileSize
-      });
-
-      demuxer.on('shard', function(shardStream, index) {
-        self._handleShardStream({
-          shardStream: shardStream,
-          index: index,
-          frame: frame,
-          uploadState: uploadState
-        });
-      }).on('error', cb);
-    });
-  }
-  return _createFileStagingFrame();
-};
-
-/**
- * BridgeClient.prototype._shardUploadWorker - description
- *
- * @param  {type} task description
- * @param  {type} done description
- */
-BridgeClient.prototype._shardUploadWorker = function(task, done) {
-  var self = this;
-
-  self._logger.info(
-    'Trying to upload shard %s index %s',
-    task.meta.tmpName,
-    task.meta.index
-  );
-
-  task.state.cleanQueue.push({store: self._store, key: task.meta.tmpName});
-
-  task.shard.on('data', function(data) {
-    task.meta.size += data.length;
-    task.meta.hasher.update(data);
-    task.tmpFile.write(data);
-  }).resume();
-
-  task.shard.on('end', function() {
-    task.tmpFile.end()
-  });
-
-  task.tmpFile.on('finish', function() {
-    task.meta.hash = task.meta.hasher.digest();
-    self._handleShardTmpFileFinish(task.state, task.meta, done);
-  });
-};
-
-/**
- * Handles a demuxed shard and writes it to tmp and updates the state
- * @private
- * @param {Object} options - Pass in configuration vars to this function
- * @param {stream.Readable} options.shardStream - Shard stream
- * @param {Number} options.index  - Index of the demuxed shard
- * @param {Object} options.frame - Frame object returned from bridge
- * @param {UploadState} options.uploadState - The upload state machine
- */
-BridgeClient.prototype._handleShardStream = function(options) {
-  var self = this;
-  const {shardStream, index, frame, uploadState} = options;
-
-  var tmpName = crypto.randomBytes(6).toString('hex')
-  var tmpFile = self._store.createWriteStream(tmpName)
-
-  this._blacklist.toObject(function(err, blacklist){
-    var meta = {
-      frame: frame,
-      tmpName: tmpName,
-      size: 0,
-      index: index,
-      hasher: crypto.createHash('sha256'),
-      hash: null,
-      excludeFarmers: blacklist,
-      transferRetries: 0
-    };
-
-    var passthrough = new stream.PassThrough();
-
-    passthrough.pause();
-
-    uploadState.queue.push({
-      state: uploadState,
-      tmpFile: tmpFile,
-      meta: meta,
-      shard: shardStream.pipe(passthrough)
-    });
-  })
-};
-
-/**
- * Generate audits for shard and add to frame
- * @private
- * @param {UploadState} state - The shard upload state machine
- * @param {Object} meta - Shard metadata reference
- * @param {Function} done - To be called on task complete
- */
-BridgeClient.prototype._handleShardTmpFileFinish = function(state, meta, done) {
-  var self = this;
-  var hash = utils.rmd160(meta.hash);
-  var auditGenerator = new AuditStream(3);
-
-  var rs = self._store.createReadStream(meta.tmpName);
-
-  self._logger.info('Hash for this shard is: %s', hash);
-
-  function _handleError(err) {
-    self._logger.warn('Failed to upload shard...');
-    state.cleanup(function(err2){
-      // If there was an error, and we failed to cleanup temporary files, we
-      // propogate the collection of files that failed back to the caller. The
-      // logic is that the upload error isn't as immediately important as
-      // loosing track of files in the user's blobstore (s3, filesystem, etc)
-      return state.callback(err2 || err);
-    });
-  }
-
-  function _teardownAuditListeners() {
-    auditGenerator.removeAllListeners();
-  }
-
-  rs.on('error', _handleError);
-  state.on('killed', _teardownAuditListeners);
-
-  function _getContract(blacklist) {
-    if (state.killed) {
-      return done();
-    }
-
-    if (!meta.challenges && !meta.tree) {
-      meta.challenges = auditGenerator.getPrivateRecord().challenges;
-      meta.tree = auditGenerator.getPublicRecord();
-      self._logger.info('Audit generation for shard done.');
-    }
-
-    self._logger.info('Waiting on a storage offer from the network...');
-
-    var addShardToFrame = self.addShardToFileStagingFrame(meta.frame.id, {
-      hash: hash,
-      size: meta.size,
-      index: meta.index,
-      challenges: meta.challenges,
-      tree: meta.tree,
-      exclude: blacklist,
-    }, function(err, pointer) {
-      if (state.killed) {
-        return done();
-      }
-
-      if (err) {
-        return _handleError(err);
-      }
-
-      self._startTransfer(pointer, state, meta, done);
-    });
-
-    // Only register listener if addShardToFrame succeeds
-    if (addShardToFrame) {
-      state.removeListener('killed', _teardownAuditListeners);
-      state.on('killed', addShardToFrame.cancel);
-    }
-  }
-
-  self._blacklist.toObject(function(e, blacklist) {
-    if (meta.challenges && meta.tree) {
-      _getContract(blacklist);
-    } else {
-      rs.pipe(auditGenerator).on('finish', _getContract, blacklist);
-    }
-  });
-};
-
-/**
- * Starts a retryable shard transfer operation
- * @private
- * @param {Object} pointer - Pointer object returned from bridge
- * @param {UploadState} state - Upload state machine
- * @param {Object} meta - Shard metadata reference
- * @param {Function} done - Task complete callback
- */
-BridgeClient.prototype._startTransfer = function(pointer, state, meta, done) {
-  var self = this;
-  var rs = self._store.createReadStream(meta.tmpName);
-
-  var transferStatus = self._transferShard(
-    new EventEmitter(),
-    rs,
-    pointer,
-    state
-  );
-
-  if (!meta.exchangeReport) {
-    meta.exchangeReport = new ExchangeReport({
-      reporterId: this._getReporterId(),
-      clientId: this._getReporterId(),
-      farmerId: pointer.farmer.nodeID
-    });
-
-    meta.exchangeReport.begin(pointer.hash);
-  }
-
-  state.on('killed', transferStatus.removeAllListeners.bind(transferStatus));
-
-  self._logger.info('Contract negotiated with: %j', pointer.farmer);
-
-  transferStatus.on('retry', function() {
-    if (meta.transferRetries < self._options.transferRetries) {
-      meta.transferRetries++;
-      self._logger.info('Retrying shard transfer, pointer: %j', pointer);
-      setTimeout(function() {
-        self._transferShard(transferStatus, meta.tmpName, pointer, state);
-      }, self._options.retryThrottle);
-    } else {
-      self._logger.info(
-        'Shard transfer failed %s times, getting another contract...',
-        meta.transferRetries
-      );
-      transferStatus.removeAllListeners();
-      meta.exchangeReport.end(ExchangeReport.FAILURE, 'TRANSFER_FAILED');
-      self.createExchangeReport(meta.exchangeReport);
-      meta.exchangeReport = null;
-      meta.transferRetries = 0;
-      self._blacklist.push(pointer.farmer.nodeID, function() {
-        self._handleShardTmpFileFinish(state, meta, done);
-      });
-    }
-  });
-
-  transferStatus.removeAllListeners('finish');
-  transferStatus.once('finish', function() {
-    self._shardTransferComplete(state, meta.frame, done);
-    meta.exchangeReport.end(ExchangeReport.SUCCESS, 'SHARD_UPLOADED');
-    self._logger.info('sending exchange report');
-    self.createExchangeReport(meta.exchangeReport);
-  });
-};
-
-/**
- * Finalizes shard transfer and if all complete adds entry to bucket
- * @private
- * @param {UploadState} state - Shard upload state machine
- * @param {Object} frame - Frame object returned from bridge
- * @param {Function} done - Task completion callback
- */
-BridgeClient.prototype._shardTransferComplete = function(state, frame, done) {
-  var self = this;
-  var retry = 0;
-
-  state.completed++;
-  this._logger.info(
-    'Shard transfer completed! %s remaining...',
-    state.numShards - state.completed
-  );
-
-  if (state.completed !== state.numShards) {
-    return done();
-  }
-
-  function _shardTransferComplete() {
-    self._logger.info('Transfer finished, creating entry.. (retry: %s)', retry);
-    self._request('POST', '/buckets/' + state.bucketId + '/files', {
-      frame: frame.id,
-      mimetype: mime.lookup(state.fileName),
-      filename: state.fileName
-    }, function(err, file) {
-      if (err) {
-
-        if (retry < 6) {
-          retry++;
-          return _shardTransferComplete();
-        }
-
-        self._logger.error(err.message);
-      }
-      state.callback(err, file);
-      return done();
-    });
-  };
-
-  state.cleanup(function(err) {
-    if (err) {
-      return done(err);
-    }
-    return _shardTransferComplete();
-  });
-};
-
-/**
- * Transfers a shard to a specified farmer
- * @private
- * @param {events.EventEmitter} evt - For getting status events
- * @param {String} shardStream - readable stream of the shard
- * @param {Object} p - Short for pointer, farmer Contact information
- * @param {UploadState} state - The upload state machine
- */
-BridgeClient.prototype._transferShard = function(evt, shardStream, p, state) {
-  var self = this;
-
-  var uploader = utils.createShardUploader(
-    new Contact(p.farmer),
-    p.hash,
-    p.token
-  );
-
-  function _handleUploadError(err) {
-    self._logger.warn('Failed to transfer shard, reason: %s', err.message);
-    uploader.removeAllListeners();
-    evt.emit('retry', shardStream, p);
-  }
-
-  function _handleStateKilled() {
-    shardStream.unpipe(uploader);
-    uploader.end();
-    evt.emit('finish');
-    evt.removeAllListeners('finish');
-  }
-
-  function _handleResponse(res) {
-    /* istanbul ignore if */
-    if (res.statusCode === 200) {
-      return;
-    }
-
-    let body = '';
-
-    res.on('data', (data) => body += data.toString());
-    res.on('end', () => {
-      let errMessage = '';
-
-      try {
-        errMessage = JSON.parse(body).result;
-      } catch (err) {
-        errMessage = '¯\_(ツ)_/¯';
-      }
-
-      uploader.emit('error', new Error(errMessage));
-    });
-  }
-
-  state.on('killed', _handleStateKilled);
-  state.uploaders.push(uploader);
-  uploader.on('response', _handleResponse);
-  uploader.on('error', (err) => _handleUploadError(err));
-
-  shardStream.pipe(uploader).on('finish', function() {
-    state.removeListener('killed', _handleStateKilled);
-    evt.emit('finish');
-    evt.removeAllListeners('finish');
-  });
-
-  return evt;
-};
-
-/**
- * Retrieves a series of file pointers from the bucket
- * @param {Object} options
- * @param {String} options.bucket - Unique bucket ID
- * @param {String} options.token - Token from {@link BridgeClient#createToken}
- * @param {String} options.file - The unique file pointer ID
- * @param {Number} options.skip - The starting index of pointers to resolve
- * @param {Number} options.limit - The number of pointers to resolve
- * @param {Function} callback
- */
-BridgeClient.prototype.getFilePointers = function(options, cb) {
-  var self = this;
-
-  function _request(done) {
-    request({
-      method: 'GET',
-      baseUrl: self._options.baseURI,
-      uri: '/buckets/' + options.bucket + '/files/' + options.file,
-      timeout: self._options.requestTimeout,
-      headers: {
-        'x-token': options.token
-      },
-      qs: {
-        skip: options.skip,
-        limit: options.limit,
-        exclude: Array.isArray(options.exclude) ? options.exclude.join() : null
-      },
-      json: true
-    }, function(err, res, body) {
-      self._logger.debug('Response Body: %s', JSON.stringify(body));
-
-      if (err) {
-        return done(err);
-      }
-
-      if (res.statusCode !== 200 && res.statusCode !== 304) {
-        return done(new Error(body.error || body));
-      }
-
-      done(null, body);
-    });
-  }
-
-  async.retry({
-    times: 3,
-    interval: self._options.retryThrottle,
-    errorFilter: (e) => {
-      const shouldRetry = ['ETIMEDOUT'].includes(e.message);
-      self._logger.debug('Request failed, reason: %s - retrying (%s)...',
-                        e.message, shouldRetry);
-      return shouldRetry;
-    }
-  }, _request, cb);
-};
-
-/**
- * Create a readable stream from the supplied file pointer
- * @private
- * @param {Object} pointer
- */
-BridgeClient.prototype._createInputFromPointer = function(pointer) {
-  return utils.createShardDownloader(
-    new Contact(pointer.farmer),
-    pointer.hash,
-    pointer.token
-  );
-};
-
-/**
- * Open a series of shard transfers based on the returned value of
- * {@link BridgeClient#getFilePointers} to resolve all the shards and
- * reassemble them together as a binary stream
- * @param {Array} pointers - Result of {@link BridgeClient#getFilePointers}
- * @param {Object} [muxerOptions] - Optional overrides for the file muxer
- * @param {Function} callback
- */
-BridgeClient.prototype.resolveFileFromPointers = function(pointers, mOpts, cb) {
-  const self = this;
-
-  if (typeof mOpts === 'function') {
-    cb = mOpts;
-    mOpts = {};
-  }
-
-  const muxer = new FileMuxer({
-    shards: mOpts.shards || pointers.length,
-    length: mOpts.length || pointers.reduce(function(a, b) {
-      return { size: a.size + b.size };
-    }, { size: 0 }).size
-  });
-
-  function _addInputToMultiplexer(pointer, onInputAdded) {
-    const inputStream = self._createInputFromPointer(pointer);
-    const exchangeReport = new ExchangeReport({
-      reporterId: self._getReporterId(),
-      clientId: self._getReporterId(),
-      farmerId: pointer.farmer.nodeID
-    });
-
-    inputStream.on('error', muxer.emit.bind(muxer, 'error'));
-    muxer._shards++;
-    muxer.addInputSource(
-      inputStream,
-      pointer.hash,
-      exchangeReport,
-      self
-    );
-    onInputAdded();
-  }
-
-  const queue = async.queue(_addInputToMultiplexer, 1);
-
-  function _addPointerToInputQueue(done) {
-    queue.push(pointers.shift(), done);
-  }
-
-  async.times(
-    pointers.length,
-    function addInputSource(n, next) {
-      _addPointerToInputQueue(next);
-    },
-    function onInputsAdded() {
-      cb(null, muxer, queue);
-    }
-  );
-};
-
-/**
- * Create a readable stream from the given bucket and file id
- * @param {String} bucket - The unique bucket ID
- * @param {String} file - The unique file ID
- * @param {Object} [options]
- * @param {Array} [options.exlude] - Exclude these nodeID's from pointers
- * @param {Function} callback - Receives (err, stream)
- */
-BridgeClient.prototype.createFileStream = function(bucket, file, opt, cb) {
-  var self = this;
-  var skip = -6;
-  var limit = 6;
-  var resolved = false;
-  var bytesExpected = 0;
-
-  if (typeof opt === 'function') {
-    cb = opt;
-    opt = {};
-  }
-
-  function _getFileMetadata(done) {
-    self.getFileInfo(bucket, file, function(err, fileInfo) {
-      if (err) {
-        return done(err);
-      }
-
-      bytesExpected = fileInfo.size;
-      done();
-    });
-  }
-
-  function _getPullToken(done) {
-    self._logger.info('Creating retrieval token...');
-    self.createToken(bucket, 'PULL', function(err, token) {
-      if (err) {
-        return done(err);
-      }
-      opt.encryptionKey = token.encryptionKey;
-      done(null, token.token);
-    });
-  }
-
-  function _getPointerSlice(token, done) {
-    self._logger.info('Resolving %s file pointers...', limit);
-    self.getFilePointers({
-      bucket: bucket,
-      token: token,
-      file: file,
-      skip: skip + limit,
-      limit: limit,
-      exclude: opt.exclude
-    }, function(err, pointers) {
-      if (err) {
-        return done(err);
-      }
-
-      // When erasure encoding is implemented, this can just
-      // become a missing shard that is recovered.
-      for (var i = 0; i < pointers.length; i++) {
-        if (!pointers[i].farmer) {
-          return done(new Error('Missing shard'));
-        }
-      }
-
-      skip += limit;
-      done(null, pointers);
-    });
-  }
-
-  function _createStreamAndQueue(pointers, done) {
-    self.resolveFileFromPointers(pointers, {
-      length: bytesExpected
-    }, function(err, stream, queue) {
-      if (err) {
-        return done(err);
-      }
-
-      done(null, stream, queue);
-    });
-  }
-
-  function _resolveNextSlice(queue, done) {
-    _getPullToken(function(err, token) {
-      if (err) {
-        return done(err);
-      }
-
-      _getPointerSlice(token, function(err, pointers) {
-        if (err) {
-          return done(err);
-        }
-
-        if (pointers.length === 0) {
-          resolved = true;
-          return done();
-        }
-
-        self._logger.info(
-          'Downloading file slice from %s channels.',
-          pointers.length
-        );
-        async.eachSeries(pointers, queue.push.bind(queue), done);
-      });
-    });
-  }
-
-  async.waterfall([
-    _getFileMetadata,
-    _getPullToken,
-    _getPointerSlice,
-    _createStreamAndQueue
-  ], function(err, stream, queue) {
-    if (err) {
-      return cb(err);
-    }
-
-    stream.encryptionKey = opt.encryptionKey;
-    cb(null, stream); // NB: Provide the stream as soon as it is ready
-    async.until(function _pointersAreExhausted() {
-      return resolved;
-    }, _resolveNextSlice.bind(null, queue), function(err) {
-      if (err) {
-        stream.emit('error', err);
-      }
-    });
-  });
-};
-
-/**
- * Create a stream for a given slice of a file
- * @param {Object} options
- * @param {String} options.bucket - The bucket ID
- * @param {String} options.file - The file ID
- * @param {Number} options.start - The byte position to start slice
- * @param {Number} options.end - The byte position to end slice
- */
-BridgeClient.prototype.createFileSliceStream = function(options, callback) {
-  var self = this;
-
-  self.getFrameFromFile(options.bucket, options.file, function(err, frame) {
-    if (err) {
-      return callback(err);
-    }
-
-    var sliceOpts = self._getSliceParams(frame, options.start, options.end);
-
-    self.createToken(options.bucket, 'PULL', function(err, token) {
-      if (err) {
-        return callback(err);
-      }
-
-      self.getFilePointers({
-        bucket: options.bucket,
-        token: token.token,
-        file: options.file,
-        skip: sliceOpts.skip,
-        limit: sliceOpts.limit
-      }, function(err, pointers) {
-        if (err) {
-          return callback(err);
-        }
-
-        self.resolveFileFromPointers(pointers, function(err, stream) {
-          if (err) {
-            return callback(err);
-          }
-
-          callback(null, stream.pipe(utils.createStreamTrimmer(
-            sliceOpts.trimFront,
-            options.end - options.start
-          )));
-        });
-      });
-    });
-  });
-};
-
-/**
- * Sends an exchange report
- * @param {ExchangeReport} exchangeReport - The result of a transfer operation
- */
-BridgeClient.prototype.createExchangeReport = function(report) {
-  assert(report instanceof ExchangeReport, 'Invalid exchangeReport');
-  this._request('POST', '/reports/exchanges', report.toObject(), utils.noop);
-};
-
-/**
- * Sends a request to the storj bridge
- * @private
- * @param {String} method - HTTP verb
- * @param {String} path - Endpoint path
- * @param {Object} params - Request parameters
- * @param {Function} callback - Return the raw response stream?
- */
-BridgeClient.prototype._request = function(method, path, params, callback) {
-  var self = this;
-  var currentRequest = null;
-
-  function _request(done) {
-    var opts = {
-      baseUrl: self._options.baseURI,
-      uri: path,
-      method: method,
-      timeout: self._options.requestTimeout
-    };
-
-    params.__nonce = uuid.v4();
-
-    if (['GET', 'DELETE'].indexOf(method) !== -1) {
-      opts.qs = params;
-      opts.json = true;
-    } else {
-      opts.json = params;
-    }
-
-    self._authenticate(opts);
-    self._logger.debug('Request Options: %s', JSON.stringify(opts));
-
-    currentRequest = request(opts, function(err, res, body) {
-      self._logger.debug('Response Body: %s', JSON.stringify(body));
-
-      if (err) {
-        return done(err);
-      }
-
-      if (res.statusCode >= 400) {
-        return done(new Error(body.error || body));
-      }
-
-      done(null, body);
-    });
-  }
-
-  async.retry({
-    times: 3,
-    interval: self._options.retryThrottle,
-    errorFilter: (e) => {
-      const shouldRetry = ['ETIMEDOUT', 'ESOCKETTIMEDOUT'].includes(e.message);
-      self._logger.warn('Request failed, reason: %s - retrying(%s)...',
-                        e.message, shouldRetry);
-      return shouldRetry;
-    }
-  }, _request, callback);
-
-  return {
-    abort: () => currentRequest.abort()
-  };
-};
-
-/**
- * Returns a "reporter id"
- * @private
- */
-BridgeClient.prototype._getReporterId = function() {
-  if (this._options.keyPair) {
-    return this._options.keyPair.getPublicKey();
-  } else if (this._options.basicAuth) {
-    return this._options.basicAuth.email;
-  } else {
-    return 'anonymous';
-  }
-};
-
-/**
- * Adds authentication headers to request object
- * @private
- * @param {Object} opts - Options parameter passed to request
- * @return {Object}
- */
-BridgeClient.prototype._authenticate = function(opts) {
-  var self = this;
-
-  if (this._options.keyPair) {
-    var payload = ['GET', 'DELETE'].indexOf(opts.method) !== -1 ?
-                  querystring.stringify(opts.qs) :
-                  JSON.stringify(opts.json);
-    var contract = [opts.method, opts.uri, payload].join('\n');
-
-    self._logger.debug(
-      'Parameter for ECDSA signature: %s\\n%s\\n%s',
-      opts.method,
-      opts.uri,
-      payload
-    );
-
-    opts.headers = opts.headers || {};
-    opts.headers['x-pubkey'] = this._options.keyPair.getPublicKey();
-    opts.headers['x-signature'] = this._options.keyPair.sign(contract, {
-      compact: false
-    });
-  } else if (this._options.basicAuth) {
-    opts.auth = {
-      user: this._options.basicAuth.email,
-      pass: utils.sha256(this._options.basicAuth.password, 'utf8')
-    };
-  }
-
-  return opts;
-};
-
-/**
- * Returns the skip/limit params for downloading a file slice
- * @private
- * @param {Object} frame - The frame object from the bridge
- * @param {Number} bytesStart - The starting byte for slice
- * @param {Number} bytesEnd - The ending byte for slice
- */
-BridgeClient.prototype._getSliceParams = function(frame, bytesStart, bytesEnd) {
-  var skip = 0;
-  var limit = 0;
-  var count = 0;
-  var trimFront = 0;
-  var trimBack = 0;
-  var trimFrontSet = false;
-  var trimBackSet = false;
-
-  frame.shards.forEach(function(shard) {
-    count += shard.size;
-
-    if (bytesStart > count) {
-      skip++;
-    } else if (!trimFrontSet) {
-      trimFront = count - bytesStart;
-      trimFrontSet = true;
-    }
-
-    if (bytesEnd > count) {
-      limit++;
-    } else if (!trimBackSet){
-      trimBack = count - bytesEnd;
-      trimBackSet = true;
-    }
-  });
-
-  return {
-    skip: skip,
-    limit: limit,
-    trimFront: trimFront,
-    trimBack: trimBack
-  };
-};
-
-module.exports = BridgeClient;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_bridge-client_upload-state.js.html b/Storj/core/docs/lib_bridge-client_upload-state.js.html deleted file mode 100644 index aaee0d0..0000000 --- a/Storj/core/docs/lib_bridge-client_upload-state.js.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - JSDoc: Source: lib/bridge-client/upload-state.js - - - - - - - - - - -
- -

Source: lib/bridge-client/upload-state.js

- - - - - - -
-
-
'use strict';
-
-var merge = require('merge');
-var inherits = require('util').inherits;
-var EventEmitter = require('events').EventEmitter;
-var async = require('async');
-
-/**
- * Internal state machine used by {@link BridgeClient}
- * @constructor
- * @license LGPL-3.0
- * @param {Object} options
- * @param {String} options.id - Bucket ID for the upload state
- * @param {String} options.file - Path to the file to track
- * @param {Number} options.numShards - The number of shards to transfer
- * @param {Number} options.concurrency - The number shards to transfer at once
- * @param {Function} options.worker - The queue task processor function
- * @param {Function} options.onComplete - Reference to callback after complete
- */
-function UploadState(options) {
-  /* eslint max-statements: [2, 16] */
-  if (!(this instanceof UploadState)) {
-    return new UploadState(options);
-  }
-
-  options = merge(Object.create(UploadState.DEFAULTS), options);
-
-  this.bucketId = options.id;
-  this.file = options.file;
-  this.fileName = options.fileName;
-  this.cleanQueue = [];
-  this.numShards = options.numShards;
-  this.completed = 0;
-  this.callback = options.onComplete;
-  this.concurrency = options.concurrency;
-  this.queue = async.queue(options.worker, this.concurrency);
-  this.killed = false;
-  this.uploaders = [];
-
-  EventEmitter.call(this);
-  this.setMaxListeners(0);
-}
-
-inherits(UploadState, EventEmitter);
-
-/**
- * Triggered when the upload queue has been killed
- * @event UploadState#killed
- */
-
-UploadState.DEFAULTS = {
-  concurrency: 6
-};
-
-/**
- * Unlinks the referenced tmp files
- */
-UploadState.prototype.cleanup = function(cb) {
-  this.killed = true;
-
-  async.each(this.cleanQueue, function(options, cb) {
-    options.store.exists(options.key, function(err, exists) {
-      if (!exists) {
-        return cb();
-      }
-      return options.store.remove(options.key, cb);
-    })
-  }, cb);
-
-  this.uploaders.forEach(function(channel) {
-    channel.end();
-  });
-
-  this.queue.kill();
-  this.emit('killed');
-  this.removeAllListeners();
-};
-
-module.exports = UploadState;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_constants.js.html b/Storj/core/docs/lib_constants.js.html deleted file mode 100644 index eb6c292..0000000 --- a/Storj/core/docs/lib_constants.js.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - JSDoc: Source: lib/constants.js - - - - - - - - - - -
- -

Source: lib/constants.js

- - - - - - -
-
-
/**
- * @module storj/constants
- * @license LGPL-3.0
- */
-
-'use strict';
-
-module.exports = {
-  /** @constant {String} CIPHER_ALG - Cipher/Decipher algorithm */
-  CIPHER_ALG: 'aes-256-ctr',
-  /** @constant {Number} PREFIX - NodeID prefix (same as bitcoin) */
-  PREFIX: 0x00,
-  /** @constant {Number} NONCE_EXPIRE - Time to honor a signed message */
-  NONCE_EXPIRE: 15000,
-  /** @constant {Number} RPC_TIMEOUT - Max wait time for a RPC response */
-  RPC_TIMEOUT: 15000,
-  /** @constant {Number} PUBLISH_TTL - Max time for publication relay */
-  PUBLISH_TTL: 6,
-  /** @constant {Number} NET_REENTRY - Max wait time before re-entering net */
-  NET_REENTRY: 600000,
-  /** @constant {Number} AUDIT_BYTES - Number of bytes for audit challenge */
-  AUDIT_BYTES: 32,
-  /** @constant {Number} CLEAN_INTERVAL - Interval for reaping stale shards */
-  CLEAN_INTERVAL: 86400000,
-  /** @constant {Number} CONSIGN_THRESHOLD - Threshold for consign time */
-  CONSIGN_THRESHOLD: 86400000,
-  /** @constant {Number} TOKEN_EXPIRE - Reject datachannl token after time */
-  TOKEN_EXPIRE: 1800000,
-  /** @constant {Number} TUNNEL_ANNOUNCE_INTERVAL - Announce tunnel state */
-  TUNNEL_ANNOUNCE_INTERVAL: 900000,
-  /** @constant {Number} OFFER_TIMEOUT - Max wait time for storage offer */
-  OFFER_TIMEOUT: 15000,
-  /** @constant {Number} ROUTER_CLEAN_INTERVAL - Drop bad contacts */
-  ROUTER_CLEAN_INTERVAL: 60000,
-  /** @constant {Number} OPCODE_TUNRPC_PREFIX - Opcode for tunnel rpc message */
-  OPCODE_TUNRPC_PREFIX: 0x0c,
-  /** @constant {Number} OPCODE_TUNDCX_PREFIX - Opcode for tunnel datachannel */
-  OPCODE_TUNDCX_PREFIX: 0x0d,
-  /** @constant {Number} OPCODE_TUNNELER_PREFIX - Prefix opcode for tunneler */
-  OPCODE_TUNNELER_PREFIX: 0x0e,
-  /** @constant {Number} OPCODE_CONTRACT_PREFIX - Prefix opcode for contracts */
-  OPCODE_CONTRACT_PREFIX: 0x0f,
-  /** @constant {Number} OPCODE_DEG_NULL - Opcode for null criteria degree */
-  OPCODE_DEG_NULL: 0x00,
-  /** @constant {Number} OPCODE_DEG_LOW - Opcode for low criteria degree */
-  OPCODE_DEG_LOW: 0x01,
-  /** @constant {Number} OPCODE_DEG_MED - Opcode for medium criteria degree */
-  OPCODE_DEG_MED: 0x02,
-  /** @constant {Number} OPCODE_DEG_HIGH - Opcode for medium criteria degree */
-  OPCODE_DEG_HIGH: 0x03,
-  /** @constant {Number} MAX_CONCURRENT_OFFERS - Number of concurrent offers */
-  MAX_CONCURRENT_OFFERS: 3,
-  /** @constant {Number} MAX_CONCURRENT_AUDITS - Number of concurrent audits */
-  MAX_CONCURRENT_AUDITS: 3,
-  /** @constant MAX_FIND_TUNNEL_RELAYS - Max times to relay FIND_TUNNEL */
-  MAX_FIND_TUNNEL_RELAYS: 2,
-  /** @constant MAX_NODE_INDEX - Maximum node index */
-  MAX_NODE_INDEX: 0x7fffffff,
-  /** @constant HD_KEY_DERIVATION_PATH - Key derivation path for HD keys */
-  HD_KEY_DERIVATION_PATH: 'm/3000\'/0\''
-};
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_contract_index.js.html b/Storj/core/docs/lib_contract_index.js.html deleted file mode 100644 index 9ed381f..0000000 --- a/Storj/core/docs/lib_contract_index.js.html +++ /dev/null @@ -1,514 +0,0 @@ - - - - - JSDoc: Source: lib/contract/index.js - - - - - - - - - - -
- -

Source: lib/contract/index.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var crypto = require('crypto');
-var merge = require('merge');
-var JSONSchema = require('jsen');
-var stringify = require('json-stable-stringify');
-var bitcore = require('bitcore-lib');
-var constants = require('../constants');
-var Message = require('bitcore-message');
-var ms = require('ms');
-
-/**
- * Represents a storage contract between a renter and a farmer
- * @constructor
- * @license AGPL-3.0
- * @version 0
- * @param {Object} contract
- * @param {String} contract.type - Unique identifier for the contract
- * @param {String} [contract.renter_hd_key] - Node extended public key in base58
- * @param {Number} [contract.renter_hd_index] - Derivation index for signature
- * @param {String} contract.renter_id - Node ID of the renter
- * @param {String} contract.renter_signature - Renter's cryptographic signature
- * @param {String} contract.farmer_id - Node ID of the farmer
- * @param {String} contract.farmer_signature - Farmer's cryptographic signature
- * @param {Number} contract.data_size - Number of bytes to store
- * @param {String} contract.data_hash - RIPEMD-160 SHA-256 hash of the data
- * @param {Number} contract.store_begin - UNIX timestamp to start contract
- * @param {Number} contract.store_end - UNIX timestamp to end the contract
- * @param {Number} contract.audit_count - Number of audits renter will perform
- * @param {Number} contract.payment_storage_price - Total price for storage
- * @param {Number} contract.payment_download_price - Price per download
- * @param {String} contract.payment_destination - Bitcoin address to send funds
- * @param {Object} criteria
- * @param {Number} criteria.size - Criteria degree OPCODE
- * @param {Number} criteria.duration - Criteria degree OPCODE
- * @param {Number} criteria.availability - Criteria degree OPCODE
- * @param {Number} criteria.speed - Criteria degree OPCODE
- */
-
-function Contract(contract, criteria) {
-  if (!(this instanceof Contract)) {
-    return new Contract(contract, criteria);
-  }
-
-  this._properties = merge(Object.create(Contract.DEFAULTS), contract);
-  this._criteria = this._inferCriteria(criteria);
-
-  this._clean();
-  assert.ok(this._validate(), 'Invalid contract specification was supplied');
-}
-
-/**
- * Defines the JSON Schema of a {@link Contract}
- * @static
- */
-Contract.Schema = require('./schema.json');
-Contract.validate = JSONSchema(Contract.Schema);
-
-/**
- * Defines some default properties of a {@link Contract}
- * @static
- */
-Contract.DEFAULTS = {
-  version: 0,
-  renter_hd_key: false,
-  renter_hd_index: false,
-  renter_id: null,
-  renter_signature: null,
-  farmer_id: null,
-  farmer_signature: null,
-  data_size: 1234,
-  data_hash: null,
-  store_begin: 2000000000,
-  store_end: 3000000000,
-  audit_count: 10,
-  payment_storage_price: 0,
-  payment_download_price: 0,
-  payment_destination: null
-};
-
-/**
- * Defines some default criteria of a {@link Contract}
- * @static
- */
-Contract.CRITERIA = {
-  size: constants.OPCODE_DEG_MED,
-  duration: constants.OPCODE_DEG_MED,
-  availability: constants.OPCODE_DEG_MED,
-  speed: constants.OPCODE_DEG_MED
-};
-
-/**
- * Defines the criteria matrix for a {@link Contract}
- * @static
- */
-Contract.MATRIX = {
-  size: function(size) {
-    if (size > 0 && size <= (32 * 1024 * 1024)) {
-      return constants.OPCODE_DEG_LOW;
-    }
-
-    if (size > (32 * 1024 * 1024) && size <= (512 * 1024 * 1024)) {
-      return constants.OPCODE_DEG_MED;
-    }
-
-    if (size > (512 * 1024 * 1024) && size <= (4096 * 1024 * 1024)) {
-      return constants.OPCODE_DEG_HIGH;
-    }
-
-    return constants.OPCODE_DEG_HIGH;
-  },
-  duration: function(duration) {
-    if (duration > 0 && duration <= ms('30d')) {
-      return constants.OPCODE_DEG_LOW;
-    }
-
-    if (duration > ms('30d') && duration <= ms('90d')) {
-      return constants.OPCODE_DEG_MED;
-    }
-
-    if (duration > ms('90d') && duration <= ms('320d')) {
-      return constants.OPCODE_DEG_HIGH;
-    }
-
-    return constants.OPCODE_DEG_HIGH;
-  },
-  availability: function(availability) {
-    if (availability >= 0.5 && availability <= 0.7) {
-      return constants.OPCODE_DEG_LOW;
-    }
-
-    if (availability > 0.7 && availability <= 0.9) {
-      return constants.OPCODE_DEG_MED;
-    }
-
-    if (availability > 0.9 && availability <= 1) {
-      return constants.OPCODE_DEG_HIGH;
-    }
-
-    return constants.OPCODE_DEG_HIGH;
-  },
-  speed: function(speed) {
-    if (speed > 0 && speed <= 6) {
-      return constants.OPCODE_DEG_LOW;
-    }
-
-    if (speed > 6 && speed <= 12) {
-      return constants.OPCODE_DEG_MED;
-    }
-
-    if (speed > 12 && speed <= 32) {
-      return constants.OPCODE_DEG_HIGH;
-    }
-
-    return constants.OPCODE_DEG_HIGH;
-  }
-};
-
-/**
- * Removes all properties not in the schema from contract
- * @private
- * @param {Object} criteria - Criteria degree opcodes
- * @returns {Object}
- */
-Contract.prototype._inferCriteria = function(criteria) {
-  var opcodes = Object.create(Contract.CRITERIA);
-
-  opcodes.size = Contract.MATRIX.size(this.get('data_size'));
-  opcodes.duration = Contract.MATRIX.duration(
-    this.get('store_end') - this.get('store_begin')
-  );
-  // NB: Do not try to infer availability or speed, should be explicit
-
-  return merge(opcodes, criteria);
-};
-
-/**
- * Removes all properties not in the schema from contract
- * @private
- * @returns {Contract} self
- */
-Contract.prototype._clean = function() {
-  var keys = Object.keys(Contract.Schema.properties);
-
-  for (var field in this._properties) {
-    if (keys.indexOf(field) === -1) {
-      delete this._properties[field];
-    }
-  }
-
-  return this;
-};
-
-/**
- * Validates the contract specification
- * @private
- * @returns {Boolean} validity
- */
-Contract.prototype._validate = function() {
-  return Contract.validate(this._properties);
-};
-
-/**
- * Checks if the contract is complete
- * @returns {Boolean} completed
- */
-Contract.prototype.isComplete = function() {
-  for (var prop in this._properties) {
-    if (this._properties[prop] === null) {
-      return false;
-    }
-  }
-
-  return true;
-};
-
-/**
- * Returns the string representation of the contract, minus the signature
- * fields, sorted alphanumerically for signing and verifying
- * @returns {String}
- */
-Contract.prototype.getSigningData = function() {
-  var sorted = this.toObject();
-
-  delete sorted.renter_signature;
-  delete sorted.farmer_signature;
-
-  return stringify(sorted);
-};
-
-/**
- * Signs the contract as the given actor
- * @param {String} actor - One of 'farmer' or 'renter'
- * @param {Buffer} secret - ECDSA private key
- * @returns {String} signature
- */
-Contract.prototype.sign = function(actor, secret) {
-  return this.set(actor + '_signature', this.signExternal(secret));
-};
-
-/**
- * Verify the contract signature for the given actor
- * @param {String} actor - One of 'farmer' or 'renter'
- * @param {Buffer} pubkeyhash - ECDSA nodeID
- * @returns {Boolean} isValidSignature
- */
-Contract.prototype.verify = function(actor, pubkeyhash) {
-  return this.verifyExternal(
-    this.get(actor + '_signature'),
-    pubkeyhash
-  );
-};
-
-/**
- * Signs the contract with the proved key and returns the signature
- * @param {String} secret - ECDSA private key
- * @returns {String} externalSignature
- */
-Contract.prototype.signExternal = function(secret) {
-  var message = Message(this.getSigningData());
-  return message.sign(bitcore.PrivateKey.fromString(secret));
-};
-
-/**
- * Verify the provided signature for the contract
- * @param {String} signature - The contract signature to verify
- * @param {String} pubkeyhash - ECDSA nodeID
- * @returns {Boolean} isValidSignature
- */
-Contract.prototype.verifyExternal = function(signature, pubkeyhash) {
-  if (!pubkeyhash) {
-    return false;
-  }
-
-  var message = Message(this.getSigningData());
-  var address = bitcore.Address.fromPublicKeyHash(Buffer(pubkeyhash, 'hex'));
-
-  try {
-    return message.verify(address, signature);
-  } catch (err) {
-    return false;
-  }
-};
-
-/**
- * Applies the provided fields to the contract and validates it
- * @param {Object} fields - Contract properties to update
- * @returns {Contract} self
- */
-Contract.prototype.update = function(fields) {
-  for (var prop in fields) {
-    this.set(prop, fields[prop]);
-  }
-
-  return this;
-};
-
-/**
- * Returns the value for the given contract property
- * @param {String} field_name - Contract property to get
- * @returns {String|Number|null} value
- */
-Contract.prototype.get = function(field_name) {
-  return this._properties[field_name];
-};
-
-/**
- * Sets the contract property to the given value
- * @param {String} field_name - Contract property to get
- * @returns {String|Number|null} value
- */
-Contract.prototype.set = function(field_name, field_value) {
-  this._properties[field_name] = field_value;
-
-  this._clean();
-  assert.ok(this._validate(), 'Invalid contract property supplied');
-
-  return this._properties[field_name];
-};
-
-/**
- * Calculates the SHA-256 hash of the serialized contract
- * @returns {Buffer}
- */
-Contract.prototype.getHash = function() {
-  return crypto.createHash('sha256').update(this.toBuffer()).digest();
-};
-
-/**
- * Return OPCODE byte sequence for contract publication topic
- * @returns {Buffer}
- */
-Contract.prototype.getTopicBuffer = function() {
-  return Contract.createTopic(this._criteria);
-};
-
-/**
- * Return OPCODE byte sequence for contract publication topic as hex string
- * @returns {String}
- */
-Contract.prototype.getTopicString = function() {
-  return this.getTopicBuffer().toString('hex');
-};
-
-/**
- * Converts the contract to a plain object
- * @returns {Object}
- */
-Contract.prototype.toObject = function() {
-  return JSON.parse(this.toJSON());
-};
-
-/**
- * Converts the contract to JSON string
- * @returns {String}
- */
-Contract.prototype.toJSON = function() {
-  return stringify(this._properties);
-};
-
-/**
- * Converts the contract to Buffer
- * @returns {Buffer}
- */
-Contract.prototype.toBuffer = function() {
-  return new Buffer(this.toJSON(), 'utf8');
-};
-
-/**
- * Creates a contract from a plain object
- * @param {Object} object - Dictionary of contract data
- * @returns {Contract}
- */
-Contract.fromObject = function(object) {
-  return new Contract(object);
-};
-
-/**
- * Creates a contract from a JSON string
- * @param {String} json - JSON encoded contract
- * @returns {Contract}
- */
-Contract.fromJSON = function(json) {
-  return new Contract(JSON.parse(json));
-};
-
-/**
- * Creates a contract from a Buffer
- * @param {Buffer} buffer - Raw binary blob of contract data
- * @returns {Contract}
- */
-Contract.fromBuffer = function(buffer) {
-  return new Contract(JSON.parse(buffer.toString('utf8')));
-};
-
-/**
- * Create a topical OPCODE byte sequence from the provided criteria
- * @param {Object} criteria
- * @param {Number} criteria.size - Criteria degree OPCODE
- * @param {Number} criteria.duration - Criteria degree OPCODE
- * @param {Number} criteria.availability - Criteria degree OPCODE
- * @param {Number} criteria.speed - Criteria degree OPCODE
- * @returns {Buffer}
- */
-Contract.createTopic = function(criteria) {
-  criteria = merge(Object.create(Contract.CRITERIA), criteria);
-
-  return new Buffer([
-    constants.OPCODE_CONTRACT_PREFIX,
-    criteria.size,
-    criteria.duration,
-    criteria.availability,
-    criteria.speed
-  ]);
-};
-
-/**
- * Compares two contracts against each other
- * @param {Contract} c1 - Contract to compare
- * @param {Contract} c2 - Contract to compare
- * @returns {Boolean}
- */
-Contract.compare = function(c1, c2) {
-  var contract1 = c1.toObject();
-  var contract2 = c2.toObject();
-  var ignored = [
-    'renter_id',
-    'renter_signature',
-    'farmer_id',
-    'farmer_signature',
-    'payment_destination'
-  ];
-
-  ignored.forEach(function(prop) {
-    delete contract1[prop];
-    delete contract2[prop];
-  });
-
-  return JSON.stringify(contract1) === JSON.stringify(contract2);
-};
-
-/**
- * Returns the property names between two contracts that differ
- * @param {Contract} c1 - Contract to compare
- * @param {contract} c2 - Contract to compare
- * @returns {String[]} changedProperties
- */
-Contract.diff = function(c1, c2) {
-  var differs = [];
-  var contract1 = c1.toObject();
-  var contract2 = c2.toObject();
-
-  for (var prop in contract1) {
-    if (contract1[prop] !== contract2[prop]) {
-      differs.push(prop);
-    }
-  }
-
-  return differs;
-};
-
-module.exports = Contract;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_contract_offer-manager.js.html b/Storj/core/docs/lib_contract_offer-manager.js.html deleted file mode 100644 index 548c960..0000000 --- a/Storj/core/docs/lib_contract_offer-manager.js.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - JSDoc: Source: lib/contract/offer-manager.js - - - - - - - - - - -
- -

Source: lib/contract/offer-manager.js

- - - - - - -
-
-
'use strict';
-
-var OfferStream = require('./offer-stream');
-var assert = require('assert');
-
-/**
- * Simple management of a collection of {@link OfferStream}s that are keyable
- * by their associated {@link Contract}'s data hash
- * @constructor
- */
-function OfferManager() {
-  if (!(this instanceof OfferManager)) {
-    return new OfferManager();
-  }
-
-  this._offerStreams = {};
-}
-
-/**
- * Returns the stream at the given key
- * @param {String} dataHash - The hash of the contract's data
- * @returns {OfferStream|null}
- */
-OfferManager.prototype.getStream = function(dataHash) {
-  return this._offerStreams[dataHash] || null;
-};
-
-/**
- * Removes the stream at the given key
- * @param {String} dataHash - The hash of the contract's data
- */
-OfferManager.prototype.removeStream = function(dataHash) {
-  delete this._offerStreams[dataHash];
-};
-
-/**
- * Adds the offer stream to the manager
- * @param {OfferStream} offerStream - The {@link OfferStream} to manage
- */
-OfferManager.prototype.addStream = function(offerStream) {
-  assert(offerStream instanceof OfferStream, 'Invalid offer stream supplied');
-
-  var key = offerStream._contract.get('data_hash');
-  this._offerStreams[key] = offerStream;
-
-  offerStream.on('end', this.removeStream.bind(this, key));
-  offerStream.on('error', this.removeStream.bind(this, key));
-  offerStream.on('destroy', this.removeStream.bind(this, key));
-};
-
-module.exports = OfferManager;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_contract_offer-stream.js.html b/Storj/core/docs/lib_contract_offer-stream.js.html deleted file mode 100644 index 9e25035..0000000 --- a/Storj/core/docs/lib_contract_offer-stream.js.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - JSDoc: Source: lib/contract/offer-stream.js - - - - - - - - - - -
- -

Source: lib/contract/offer-stream.js

- - - - - - -
-
-
'use strict';
-
-var Contact = require('../network/contact');
-var Contract = require('./index');
-var ReadableStream = require('readable-stream');
-var inherits = require('util').inherits;
-var assert = require('assert');
-var merge = require('merge');
-
-/**
- * Manages a stream of offers for a given storage contract publication
- * @constructor
- * @param {Contract} contract - Storage contract published to network
- * @param {Object} [options]
- * @param {Number} [options.maxOffers] - Maximum number of offers to process
- * @param {Array.<String>} [options.farmerBlacklist] - Reject offers from nodeID
- */
-function OfferStream(contract, options) {
-  if (!(this instanceof OfferStream)) {
-    return new OfferStream(contract, options);
-  }
-
-  ReadableStream.call(this, { objectMode: true });
-  assert(contract instanceof Contract, 'Invalid contract supplied');
-
-  this.options = merge(Object.create(OfferStream.DEFAULTS), options);
-
-  this._contract = contract;
-  this._queue = [];
-  this._offersQueued = 0;
-  this._offersProccessed = 0;
-  this._farmersDidOffer = [];
-  this._isDestroyed = false;
-}
-
-inherits(OfferStream, ReadableStream);
-
-OfferStream.DEFAULTS = {
-  maxOffers: 12,
-  farmerBlacklist: [],
-};
-
-/**
- * Triggered when an offer is received
- * @event OfferStream#data
- * @param {Object} data
- * @param {Contact} data.contact - The sending farmer for the offer
- * @param {Contract} data.contract - The received offer contract
- */
-
-/**
- * Triggered when the maximum number of offers are received and processed
- * @event OfferStream#end
- */
-
-/**
- * Triggered if an error occurs
- * @event OfferStream#error
- * @param {Error} error - The error object with message
- */
-
-/**
- * Implements the underlying stream
- * @private
- */
-OfferStream.prototype._read = function() {
-  var self = this;
-
-  if (this._offersProccessed === this.options.maxOffers) {
-    return this.push(null);
-  }
-
-  function _push() {
-    self._offersProccessed++;
-    self.push(self._queue.shift());
-  }
-
-  if (this._queue.length > 0) {
-    return setImmediate(_push);
-  }
-
-  this.once('_offerAddedToQueue', _push);
-};
-
-/**
- * Adds the offer to the internal queue if there is room
- * @param {Contact} contact - The sending farmer for the offer
- * @param {Contract} contract - The received offer contract
- * @returns {Boolean} didAddOfferToQueue
- */
-OfferStream.prototype.addOfferToQueue = function(contact, contract) {
-  assert(contact instanceof Contact, 'Invalid contact supplied');
-  assert(contract instanceof Contract, 'Invalid contract supplied');
-
-  var isDestroyed = this._isDestroyed;
-  var farmerSentOffer = this._farmersDidOffer.indexOf(
-    contact.nodeID
-  ) !== -1;
-  var contractIncomplete = !contract.isComplete();
-  var maxReached = this._offersQueued === this.options.maxOffers;
-
-  if (isDestroyed || farmerSentOffer || contractIncomplete || maxReached) {
-    return false;
-  }
-
-  this._farmersDidOffer.push(contact.nodeID);
-  this._queue.push({ contact: contact, contract: contract });
-  this._offersQueued++;
-  this.emit('_offerAddedToQueue');
-
-  return true;
-};
-
-/**
- * Tears down listeners and ends the stream
- */
-OfferStream.prototype.destroy = function() {
-  this._queue = [];
-  this._isDestroyed = true;
-
-  setImmediate(this.removeAllListeners.bind(this));
-  this.emit('destroy');
-};
-
-module.exports = OfferStream;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_crypto-tools_cipher-key-iv.js.html b/Storj/core/docs/lib_crypto-tools_cipher-key-iv.js.html deleted file mode 100644 index f0b4f31..0000000 --- a/Storj/core/docs/lib_crypto-tools_cipher-key-iv.js.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - JSDoc: Source: lib/crypto-tools/cipher-key-iv.js - - - - - - - - - - -
- -

Source: lib/crypto-tools/cipher-key-iv.js

- - - - - - -
-
-
'use strict';
-
-var crypto = require('crypto');
-var utils = require('../utils');
-
-/**
- * Create a new random cipher key and initialization vector
- * @constructor
- * @license LGPL-3.0
- * @param {String|Buffer} [password] - The unique cipher password
- * @param {String|Buffer} [salt] - The unique salt
- */
-function DataCipherKeyIv(pass, salt) {
-  if (!(this instanceof DataCipherKeyIv)) {
-    return new DataCipherKeyIv(pass, salt);
-  }
-
-  if (!pass && !salt) {
-    pass = crypto.randomBytes(DataCipherKeyIv.PASS_BYTES);
-    salt = crypto.randomBytes(DataCipherKeyIv.SALT_BYTES);
-  }
-
-  this._pass = Buffer.isBuffer(pass) ? pass : Buffer(pass, 'hex');
-  this._salt = Buffer.isBuffer(salt) ? salt : Buffer(salt, 'hex');
-  this._pbkdf2 = crypto.pbkdf2Sync(
-    this._pass,
-    this._salt,
-    25000,
-    512,
-    'sha512'
-  );
-}
-
-DataCipherKeyIv.PASS_BYTES = 512;
-DataCipherKeyIv.SALT_BYTES = 32;
-
-/**
- * Returns the cipher key and iv in an array
- * @returns {Array}
- */
-DataCipherKeyIv.prototype.getCipherKeyIv = function() {
-  return [
-    Buffer(utils.sha256(this._pbkdf2), 'hex'),
-    Buffer(utils.rmd160(this._salt), 'hex').slice(0, 16)
-  ];
-};
-
-/**
- * Returns the key and iv as an array
- * @returns {Array}
- */
-DataCipherKeyIv.prototype.toObject = function() {
-  return {
-    pass: this._pass.toString('hex'),
-    salt: this._salt.toString('hex')
-  };
-};
-
-/**
- * Returns the a {@link DataCipherKeyIv} from an object
- * @param {Object} object
- * @param {Buffer|String} object.pass - The unique password
- * @param {Buffer|String} object.salt - The unique salt
- * @returns {DataCipherKeyIv}
- */
-DataCipherKeyIv.fromObject = function(object) {
-  return new DataCipherKeyIv(object.pass, object.salt);
-};
-
-module.exports = DataCipherKeyIv;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_crypto-tools_decrypt-stream.js.html b/Storj/core/docs/lib_crypto-tools_decrypt-stream.js.html deleted file mode 100644 index 3d96ce9..0000000 --- a/Storj/core/docs/lib_crypto-tools_decrypt-stream.js.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - JSDoc: Source: lib/crypto-tools/decrypt-stream.js - - - - - - - - - - -
- -

Source: lib/crypto-tools/decrypt-stream.js

- - - - - - -
-
-
'use strict';
-
-var constants = require('../constants');
-var inherits = require('util').inherits;
-var assert = require('assert');
-var crypto = require('crypto');
-var stream = require('readable-stream');
-var DataCipherKeyIv = require('../crypto-tools/cipher-key-iv');
-var DeterministicKeyIv = require('../crypto-tools/deterministic-key-iv');
-
-/**
- * Represents a duplex stream capable of taking encrypted data as input and
- * producing output decrypted by a {@link DataCipherKeyIv}
- * @constructor
- * @license LGPL-3.0
- * @param {DataCipherKeyIv|DeterministicKeyIv} keyiv - Object to use
- * for derivation function
- * @emits DecryptStream#data
- * @emits DecryptStream#end
- */
-function DecryptStream(keyiv) {
-  if (!(this instanceof DecryptStream)) {
-    return new DecryptStream(keyiv);
-  }
-
-  assert(
-    keyiv instanceof DataCipherKeyIv || keyiv instanceof DeterministicKeyIv,
-    'Invalid cipher object supplied'
-  );
-
-  this._decipher = crypto.createDecipheriv.apply(
-    this,
-    [constants.CIPHER_ALG].concat(keyiv.getCipherKeyIv())
-  );
-
-  stream.Transform.call(this);
-}
-
-inherits(DecryptStream, stream.Transform);
-
-/**
- * Writes to the underlying decipher
- * @private
- */
-DecryptStream.prototype._transform = function(chunk, enc, callback) {
-  this._decipher.write(chunk);
-  callback(null, this._decipher.read());
-};
-
-/**
- * Ensures there is no more data to be read from decipher
- * @private
- */
-DecryptStream.prototype._flush = function(callback) {
-  callback(null, this._decipher.read());
-};
-
-/**
- * Triggered when some input bytes have become decrypted output bytes
- * @event DecryptStream#data
- * @type {Buffer}
- */
-
-/**
- * Triggered when the stream has ended
- * @event DecryptStream#end
- */
-
-module.exports = DecryptStream;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_crypto-tools_deterministic-key-iv.js.html b/Storj/core/docs/lib_crypto-tools_deterministic-key-iv.js.html deleted file mode 100644 index 38b215f..0000000 --- a/Storj/core/docs/lib_crypto-tools_deterministic-key-iv.js.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - JSDoc: Source: lib/crypto-tools/deterministic-key-iv.js - - - - - - - - - - -
- -

Source: lib/crypto-tools/deterministic-key-iv.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var utils = require('../utils');
-
-/**
- * Create a new deterministic cipher key
- * @constructor
- * @license LGPL-3.0
- * @param {String} fileKey - file key
- * @param {String} fileId - file id
- */
-function DeterministicKeyIv(fileKey, fileId) {
-  if (!(this instanceof DeterministicKeyIv)) {
-    return new DeterministicKeyIv(fileKey, fileId);
-  }
-
-  this._pass = fileKey;
-  this._salt = fileId;
-}
-
-/**
- * Calculates a deterministic key
- * @param {Buffer|String} seed - Deterministic seed or bucket key
- * @param {Buffer|String} id - Unique bucket or file id
- * @returns {String}
- */
-DeterministicKeyIv.getDeterministicKey = function(key, id){
-  if (!Buffer.isBuffer(key)) {
-    assert(utils.isHexaString(key),
-           'key is expected to be a buffer or hex string');
-    key = Buffer.from(key, 'hex');
-  }
-  if (!Buffer.isBuffer(id)) {
-    assert(utils.isHexaString(id),
-           'id is expected to be a buffer or hex string');
-    id = Buffer.from(id, 'hex');
-  }
-  var buffer = utils.sha512(Buffer.concat([key, id]));
-  return buffer.toString('hex').substring(0, 64);
-};
-
-/**
- * Returns the cipher key and iv in an array
- * @returns {Array}
- */
-DeterministicKeyIv.prototype.getCipherKeyIv = function() {
-  return [
-    Buffer(utils.sha256(this._pass), 'hex'),
-    Buffer(utils.rmd160(this._salt), 'hex').slice(0, 16)
-  ];
-};
-
-/**
- * Returns the key and iv as an array
- * @returns {Array}
- */
-DeterministicKeyIv.prototype.toObject = function() {
-  return {
-    type: 'DeterministicKeyIv',
-    pass: this._pass,
-    salt: this._salt
-  };
-};
-
-/**
- * Returns the a {@link DeterministicKeyIv} from an object
- * @param {Object} object
- * @param {Buffer|String} object.pass - The unique password
- * @param {Buffer|String} object.salt - The unique salt
- * @returns {DeterministicKeyIv}
- */
-DeterministicKeyIv.fromObject = function(object) {
-  return new DeterministicKeyIv(object.pass, object.salt);
-};
-
-module.exports = DeterministicKeyIv;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_crypto-tools_encrypt-stream.js.html b/Storj/core/docs/lib_crypto-tools_encrypt-stream.js.html deleted file mode 100644 index 0228ce7..0000000 --- a/Storj/core/docs/lib_crypto-tools_encrypt-stream.js.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - JSDoc: Source: lib/crypto-tools/encrypt-stream.js - - - - - - - - - - -
- -

Source: lib/crypto-tools/encrypt-stream.js

- - - - - - -
-
-
'use strict';
-
-var constants = require('../constants');
-var assert = require('assert');
-var crypto = require('crypto');
-var stream = require('readable-stream');
-var inherits = require('util').inherits;
-var DataCipherKeyIv = require('../crypto-tools/cipher-key-iv');
-var DeterministicKeyIv = require('../crypto-tools/deterministic-key-iv');
-
-/**
- * Represents a duplex stream capable of taking cleartext data as input and
- * producing output encrypted with {@link DataCipherKeyIv}
- * @constructor
- * @license LGPL-3.0
- * @param {DataCipherKeyIv|DeterministicKeyIv} keyiv - Object to use
- * for derivation function
- * @emits EncryptStream#data
- * @emits EncryptStream#end
- */
-function EncryptStream(keyiv) {
-  if (!(this instanceof EncryptStream)) {
-    return new EncryptStream(keyiv);
-  }
-
-  assert(
-    keyiv instanceof DataCipherKeyIv || keyiv instanceof DeterministicKeyIv,
-    'Invalid cipher object supplied'
-  );
-
-  this._cipher = crypto.createCipheriv.apply(
-    this,
-    [constants.CIPHER_ALG].concat(keyiv.getCipherKeyIv())
-  );
-
-  stream.Transform.call(this);
-}
-
-inherits(EncryptStream, stream.Transform);
-
-/**
- * Writes to the internal cipheriv
- * @private
- */
-EncryptStream.prototype._transform = function(chunk, enc, callback) {
-  this._cipher.write(chunk);
-  callback(null, this._cipher.read());
-};
-
-/**
- * Ensures that there is no remaining bytes to be read from cipher
- * @private
- */
-EncryptStream.prototype._flush = function(callback) {
-  callback(null, this._cipher.read());
-};
-
-/**
- * Triggered when some input bytes have become encrypted output bytes
- * @event EncryptStream#data
- * @type {Buffer}
- */
-
-/**
- * Triggered when the stream has ended
- * @event EncryptStream#end
- */
-
-module.exports = EncryptStream;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_crypto-tools_keypair.js.html b/Storj/core/docs/lib_crypto-tools_keypair.js.html deleted file mode 100644 index fa66c8c..0000000 --- a/Storj/core/docs/lib_crypto-tools_keypair.js.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - - JSDoc: Source: lib/crypto-tools/keypair.js - - - - - - - - - - -
- -

Source: lib/crypto-tools/keypair.js

- - - - - - -
-
-
'use strict';
-
-var bitcore = require('bitcore-lib');
-var crypto = require('crypto');
-var merge = require('merge');
-var Message = require('bitcore-message');
-var curve = bitcore.deps.elliptic.curves.secp256k1;
-var ecdsa = new bitcore.deps.elliptic.ec(curve);
-
-/**
- * Represents a ECDSA key pair
- * @constructor
- * @license LGPL-3.0
- * @param {String|Buffer|undefined} privateKey - WIF encoded ECDSA private key
- */
-function KeyPair(privkey) {
-  if (!(this instanceof KeyPair)) {
-    return new KeyPair(privkey);
-  }
-
-  if (privkey) {
-    this._privkey = bitcore.PrivateKey.fromString(privkey);
-  } else {
-    this._privkey = bitcore.PrivateKey.fromRandom();
-  }
-
-  this._pubkey = this._privkey.toPublicKey();
-}
-
-/**
- * Returns the private key
- * @returns {String} key
- */
-KeyPair.prototype.getPrivateKey = function() {
-  return this._privkey.toString();
-};
-
-/**
- * Returns the public key
- * @returns {String} key
- */
-KeyPair.prototype.getPublicKey = function() {
-  return this._pubkey.toString();
-};
-
-/**
- * Returns the NodeID derived from the public key
- * @returns {String} nodeID - RIPEMD160 hash of public key
- */
-KeyPair.prototype.getNodeID = function() {
-  return bitcore.crypto.Hash.sha256ripemd160(
-    this._pubkey.toBuffer()
-  ).toString('hex');
-};
-
-/**
- * Returns the bitcoin address version of the nodeID
- * @returns {String} address - Base58 encoded address
- */
-KeyPair.prototype.getAddress = function() {
-  return bitcore.Address.fromPublicKeyHash(
-    new Buffer(this.getNodeID(), 'hex')
-  ).toString();
-};
-
-/**
- * Signs the supplied message with the private key
- * @param {String|Buffer} message - The message to sign
- * @param {Object} options
- * @param {Boolean} [options.compact=true] - Compact signature format
- * @returns {String} signature
- */
-KeyPair.prototype.sign = function(message, options) {
-  var sign = null;
-  var opts = merge({ compact: true }, options);
-
-  if (opts.compact) {
-    sign = Message(message).sign(this._privkey);
-  } else {
-    if (!Buffer.isBuffer(message)) {
-      message = new Buffer(message, 'utf8');
-    }
-
-    sign = ecdsa.sign(
-      crypto.createHash('sha256').update(message).digest('hex'),
-      this.getPrivateKey()
-    ).toDER('hex');
-  }
-
-  return sign;
-};
-
-module.exports = KeyPair;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_crypto-tools_keyring.js.html b/Storj/core/docs/lib_crypto-tools_keyring.js.html deleted file mode 100644 index 0cfd9ac..0000000 --- a/Storj/core/docs/lib_crypto-tools_keyring.js.html +++ /dev/null @@ -1,439 +0,0 @@ - - - - - JSDoc: Source: lib/crypto-tools/keyring.js - - - - - - - - - - -
- -

Source: lib/crypto-tools/keyring.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var fs = require('fs');
-var DataCipherKeyIv = require('../crypto-tools/cipher-key-iv');
-var DeterministicKeyIv = require('../crypto-tools/deterministic-key-iv');
-var crypto = require('crypto');
-var path = require('path');
-var targz = require('node-tar.gz');
-var os = require('os');
-var utils = require('../utils');
-var constants = require('../constants');
-var Mnemonic = require('bitcore-mnemonic');
-
-/**
- * A {@link DataCipherKeyIv} factory with file system persistence
- * @constructor
- * @license LGPL-3.0
- * @param {String} keyRingDir - Path to store keyring directory
- * @param {String} [passPhrase=''] - Passphrase to encrypt/decrypt keyring
- */
-function KeyRing(filePath, passPhrase) {
-  if (!(this instanceof KeyRing)) {
-    return new KeyRing(filePath, passPhrase);
-  }
-
-  assert(typeof filePath === 'string', 'Invalid path supplied to keyring');
-
-  this._keyFolder = path.join(filePath, 'key.ring');
-  this._pass = passPhrase || '';
-  this._deterministicKeyFile = path.join(this._keyFolder, '.deterministic_key');
-  this._mnemonic = null;
-
-  if (!utils.existsSync(this._keyFolder)) {
-    fs.mkdirSync(this._keyFolder);
-  }
-
-  this._verify();
-  this._migrateOld(path.join(filePath, 'keyring'));
-  this._readDeterministicKey();
-}
-
-KeyRing.DEFAULTS = {
-  algorithm: constants.CIPHER_ALG
-};
-
-/**
-  * Verify the password supplied is correct for the previously created keys.
-  * @private
-  */
-KeyRing.prototype._verify = function() {
-  if (!utils.existsSync(path.join(this._keyFolder, '.verify'))) {
-    this.generate('.verify');
-  }
-
-  try {
-    this.get('.verify');
-  } catch (err) {
-    throw new Error('Invalid passphrase was supplied to KeyRing');
-  }
-};
-
-/**
-  * Migrate the old keyring to new key.ring folder
-  * @private
-  * @param {String} oldPath - path to the old keyring
-  */
-KeyRing.prototype._migrateOld = function(oldPath) {
-  if (utils.existsSync(oldPath)) {
-    var oldKeyRing;
-
-    try {
-      oldKeyRing = JSON.parse(
-        this._decrypt(fs.readFileSync(oldPath).toString())
-      );
-    } catch (err) {
-      return fs.unlinkSync(oldPath);
-    }
-
-    for (var key in oldKeyRing) {
-      var file = path.join(this._keyFolder, key);
-
-      if (!utils.existsSync(file)) {
-        fs.writeFileSync(
-          file,
-          this._encrypt(JSON.stringify(oldKeyRing[key]))
-        );
-      }
-    }
-
-    fs.unlinkSync(oldPath);
-  }
-};
-
-/**
- * Export Keyring to compressed tarball
- * @param {String} outPath - Path to keyring to be compressed
- * @param {Function} callback - Called when tarball has been written
- */
-KeyRing.prototype.export = function(tar, callback) {
-  var read = targz().createReadStream(this._keyFolder);
-  var write = fs.createWriteStream(tar);
-
-  read.pipe(write).on('finish', callback).on('error', callback);
-};
-
-/**
- * Import to Keyring from compressed tarball
- * @param {String} inPath - Path to tarball to be imported
- * @param {String} passPhrase - Passphrase used to decrypt the imported tar
- * @param {Boolean} [overwriteConflictingIds=false] - Overwrite conflicting key
- * @param {Function} callback - Called on import finish
- */
-KeyRing.prototype.import = function(tar, passphrase, writeflag, callback) {
-  var self = this;
-  var read = fs.createReadStream(tar);
-  var parse = targz().createParseStream();
-
-  if (typeof writeflag === 'function') {
-    callback = writeflag;
-    writeflag = false;
-  }
-
-  function worker(entry, done) {
-    var key = path.basename(entry.path);
-    var keyPath = path.join(self._keyFolder, key);
-
-    if (!utils.existsSync(keyPath) || writeflag === true) {
-      var buf = '';
-
-      entry.on('data', function(data) {
-        buf += data;
-      });
-
-      entry.resume();
-
-      entry.on('end', function() {
-        var decrypted;
-
-        if (key === 'key.ring' || key === '.DS_Store') {
-          return entry.abort();
-        }
-
-        try {
-          decrypted = self._encrypt(
-            KeyRing.prototype._decrypt.call({ _pass: passphrase }, buf)
-          );
-        } catch (err) {
-          parse.removeAllListeners('end');
-          return callback(new Error('Failed to decrypt keyring'));
-        }
-
-        fs.writeFileSync(keyPath, decrypted, done);
-      });
-    }
-  }
-
-  parse.on('entry', worker).on('end', callback);
-  read.pipe(parse);
-};
-
-/**
- * Returns the stored {@link KeyPair} for the given id
- * @param {String} keyId - Arbitrary key ID to load
- * @returns {DataCipherKeyIv|DeterministicKeyIv|null}
- */
-KeyRing.prototype.get = function(id, bucket) {
-  var file = path.join(this._keyFolder, id);
-
-  if (!utils.existsSync(file)) {
-    if (!this._mnemonic) {
-      return null;
-    }
-    return this.generateFileKey(bucket, id);
-  }
-
-  var fileData = this._decrypt(fs.readFileSync(file).toString());
-  var keyObject = JSON.parse(fileData);
-  if (keyObject.type === 'DeterministicKeyIv') {
-    return DeterministicKeyIv.fromObject(keyObject);
-  }
-  return DataCipherKeyIv.fromObject(keyObject);
-};
-
-/**
- * Returns the stored {@link KeyPair} for the given id
- * @param {String} keyId - Generate a key for use with the given ID
- * @returns {KeyPair}
- */
-KeyRing.prototype.generate = function(id) {
-  return this.set(id, DataCipherKeyIv());
-};
-
-/**
- * Returns the stored {@link KeyPair} for the given id
- * @param {String} keyId - Arbitrary key ID to load
- * @param {DataCipherKeyIv|DeterministicKeyIv} dataCipherKey
- */
-KeyRing.prototype.set = function(id, cipherKeyIv) {
-  this._saveKeyToDisk(id, cipherKeyIv.toObject());
-
-  return cipherKeyIv;
-};
-
-/**
- * Saves the keyring file to disk
- * @private
- */
-KeyRing.prototype._saveKeyToDisk = function(id, cipherKeyIv) {
-  return fs.writeFileSync(
-    path.join(this._keyFolder, id),
-    this._encrypt(JSON.stringify(cipherKeyIv))
-  );
-};
-
-/**
- * Delete the keyring file from disk
- * @param {String} keyId - Arbitrary key ID to delete
- */
-KeyRing.prototype.del = function(id) {
-  var key = path.join(this._keyFolder, id);
-
-  if (utils.existsSync(key)) {
-    return fs.unlinkSync(key);
-  }
-};
-
-/**
- * Resets the keyring password
- * @param {String} passPhrase - New passphrase for keyring
- * @param {Function} callback - Called on keyring password reset
- */
-KeyRing.prototype.reset = function(newpass, callback) {
-  var self = this;
-  var tmp = os.tmpdir();
-  var tarball = path.join(tmp, 'keyring.bak.' + Date.now() + '.tgz');
-  var oldpass = this._pass;
-
-  if (!newpass || !newpass.length) {
-    return callback(new Error('Your Password cannot be blank!'));
-  }
-
-  this.export(tarball, function(err) {
-    if (err) {
-      return callback(err);
-    }
-
-    self._pass = newpass;
-    self.del('.verify');
-
-    self.import(tarball, oldpass, true, function(err) {
-      callback(err);
-      fs.unlinkSync(tarball);
-    });
-  });
-};
-
-
-/**
- * Encrypts the data with the passphrase
- * @private
- * @param {String} data - Data to encrypt
- */
-KeyRing.prototype._encrypt = function(data) {
-  var cipher = crypto.createCipher(KeyRing.DEFAULTS.algorithm, this._pass);
-  var enc = cipher.update(data, 'utf8', 'hex');
-
-  enc += cipher.final('hex');
-
-  return enc;
-};
-
-/**
- * Decrypts the data with the passphrase
- * @private
- * @param {String|Buffer} data - Data to encrypt
- */
-KeyRing.prototype._decrypt = function(data) {
-  var decipher = crypto.createDecipher(KeyRing.DEFAULTS.algorithm, this._pass);
-  var dec = decipher.update(data, 'hex', 'utf8');
-
-  dec += decipher.final('utf8');
-
-  return JSON.parse(dec) && dec;
-};
-
-/**
- * Retrieve the bucketKey
- * @param {String} bucketId - bucket id
- * @returns {String|null}
- */
-KeyRing.prototype.generateBucketKey = function(bucketId) {
-  if (!this._mnemonic || !bucketId) {
-    return null;
-  }
-  return DeterministicKeyIv.getDeterministicKey(
-    this._mnemonic.toSeed(),
-    Buffer.from(bucketId, 'hex')
-  );
-};
-
-/**
- * Retrieve the fileKey
- * @param {String} bucketId - bucket id
- * @param {String} fileId - file id
- * @returns {DataCipherKeyIv}
- */
-KeyRing.prototype.generateFileKey = function(bucketId, fileId) {
-  var self = this;
-
-  var bucketKey = self.generateBucketKey(bucketId);
-  if (!bucketKey) {
-    return DataCipherKeyIv();
-  }
-
-  var fileKey = DeterministicKeyIv.getDeterministicKey(
-    Buffer.from(bucketKey, 'hex'),
-    Buffer.from(fileId, 'hex')
-  );
-  return new DeterministicKeyIv(fileKey, fileId);
-};
-
-/**
- * Read a deterministic key from disk
- * @private
- */
-KeyRing.prototype._readDeterministicKey = function() {
-  if (!utils.existsSync(this._deterministicKeyFile)) {
-    return;
-  }
-  var enc = fs.readFileSync(this._deterministicKeyFile).toString();
-  this._mnemonic = new Mnemonic(JSON.parse(this._decrypt(enc)).mnemonic);
-};
-
-/**
- * Generate and save deterministic key to disk
- */
-KeyRing.prototype.generateDeterministicKey = function() {
-
-  assert(
-    !utils.existsSync(this._deterministicKeyFile),
-    'Deterministic key already exists'
-  );
-
-  this._mnemonic = new Mnemonic(Mnemonic.Words.ENGLISH);
-  this._saveKeyToDisk('.deterministic_key', {
-    mnemonic: this._mnemonic.toString()
-  });
-};
-
-/**
- * Import mnemonic into KeyRing
- * @param {String} mnemonic - Mnemonic to transfer
- */
-KeyRing.prototype.importMnemonic = function(mnemonic) {
-
-  assert(
-    !utils.existsSync(this._deterministicKeyFile),
-    'Deterministic key already exists'
-  );
-
-  assert(Mnemonic.isValid(mnemonic), 'Mnemonic is invalid');
-
-  this._mnemonic = new Mnemonic(mnemonic);
-  this._saveKeyToDisk('.deterministic_key', {
-    mnemonic: this._mnemonic.toString()
-  });
-};
-
-/**
- * Export mnemonic from KeyRing
- * @returns {String|null}
- */
-KeyRing.prototype.exportMnemonic = function() {
-  if (!this._mnemonic) {
-    return null;
-  }
-  return this._mnemonic.toString();
-};
-
-/**
- * Delete deterministic key from disk
- */
-KeyRing.prototype.deleteDeterministicKey = function() {
-  this.del('.deterministic_key');
-};
-
-module.exports = KeyRing;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_deps.js.html b/Storj/core/docs/lib_deps.js.html deleted file mode 100644 index 55f140e..0000000 --- a/Storj/core/docs/lib_deps.js.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - - JSDoc: Source: lib/deps.js - - - - - - - - - - -
- -

Source: lib/deps.js

- - - - - - -
-
-
/**
- * @module storj/deps
- */
-
-'use strict';
-
-/**
- * Kademlia inspired local file store based on LevelDB
- * @see http://bookch.in/kfs
- */
-exports.kfs = require('kfs');
-
-/**
- * Implementation of the Kademlia distributed hash table
- * @see http://kadtools.github.io/
- */
-exports.kad = require('kad');
-exports.kad.Quasar = require('kad-quasar');
-
-/**
- * A modular node for Bitcoin and blockchain-based apps
- * @see https://bitcore.io/
- */
-exports.bitcore = require('bitcore-lib');
-exports.bitcore.ECIES = require('bitcore-ecies');
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_file-handling_file-demuxer.js.html b/Storj/core/docs/lib_file-handling_file-demuxer.js.html deleted file mode 100644 index 12f4e81..0000000 --- a/Storj/core/docs/lib_file-handling_file-demuxer.js.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - - JSDoc: Source: lib/file-handling/file-demuxer.js - - - - - - - - - - -
- -

Source: lib/file-handling/file-demuxer.js

- - - - - - -
-
-
'use strict';
-
-var inherits = require('util').inherits;
-var assert = require('assert');
-var stream = require('readable-stream');
-var fs = require('fs');
-var EventEmitter = require('events').EventEmitter;
-var merge = require('merge');
-var utils = require('../utils');
-var os = require('os');
-var timers = require('timers');
-
-/**
- * Takes a single file read stream and outputs several output streams, used for
- * "shredding" a file and creating muliple out destination interfaces
- * @constructor
- * @license LGPL-3.0
- * @param {String} filePath - Path the file to demultiplex
- * @param {Object} options
- * @param {Number} options.shardSize - Size of each shard
- * @fires FileDemuxer#shard
- */
-function FileDemuxer(filePath, options) {
-  if (!(this instanceof FileDemuxer)) {
-    return new FileDemuxer(filePath, options);
-  }
-
-  options = merge(Object.create(FileDemuxer.DEFAULTS), options);
-
-  //turn filePath into a readable Stream
-  if (typeof filePath === 'string') {
-    assert(
-      utils.existsSync(filePath),
-      'File does not exist at the supplied path'
-    );
-    options.fileSize = fs.statSync(filePath).size;
-    filePath = fs.createReadStream(filePath).on('error',
-      this.emit.bind(this, 'error'));
-  }
-
-  this._fileSize = options.fileSize;
-  this._filePosition = 0;
-  this._shardSize = options.shardSize;
-
-  // at this point node and browser converge to a readable stream _source
-  this._source = filePath;
-  this._currentShardIndex = 0;
-
-  EventEmitter.call(this);
-  timers.setImmediate(this._openStream.bind(this));
-}
-
-FileDemuxer.SHARD_MULTIPLES_BACK = 4;
-FileDemuxer.DEFAULTS = {
-  shardSize: 1024 * 1024 * 8
-};
-
-/**
- * Triggered when the demuxer has a shard ready to stream
- * @event FileDemuxer#shard
- * @param {ReadableStream} shard - The file shard as a readable stream
- */
-
-/**
- * Triggered when the demuxer has finished writing to all shards
- * @event FileDemuxer#finish
- */
-
-inherits(FileDemuxer, EventEmitter);
-
-/**
- * Opens the underyling readable stream
- * @private
- */
-FileDemuxer.prototype._openStream = function() {
-  if (this._fileSize === 0) {
-    this._currentOutput = new stream.Readable({ read: utils.noop });
-    return this.emit('error', new Error('File size cannot be 0 Bytes.'));
-  }
-  
-  this._source.on('data', this._handleSourceBytes.bind(this));
-  this._source.on('end', this._handleSourceEnded.bind(this));
-};
-
-/**
- * Handles incoming data from the source stream
- * @private
- */
-FileDemuxer.prototype._handleSourceBytes = function(chunk) {
-  if (!this._currentOutput) {
-    this._currentOutput = new stream.Readable({ read: utils.noop });
-
-    this.emit('shard', this._currentOutput, this._currentShardIndex);
-  }
-
-  if (this._needsNewOutputStream()) {
-    this._closeCurrentOutput();
-
-    this._currentOutput = new stream.Readable({ read: utils.noop });
-
-    this.emit('shard', this._currentOutput, ++this._currentShardIndex);
-  }
-
-  this._pushBytesToOutput(chunk);
-};
-
-/**
- * Closes the current output source and emits a finish event
- * @private
- */
-FileDemuxer.prototype._handleSourceEnded = function() {
-  timers.setImmediate(this._closeCurrentOutput.bind(this));
-  this.emit('finish');
-};
-
-/**
- * Simply pushes the given bytes to the current output
- * @private
- */
-FileDemuxer.prototype._pushBytesToOutput = function(bytes) {
-  if (bytes) {
-    this._filePosition += bytes.length;
-  }
-
-  this._currentOutput.push(bytes);
-};
-
-/**
- * Simply closes the output stream
- * @private
- */
-FileDemuxer.prototype._closeCurrentOutput = function() {
-  this._pushBytesToOutput(null);
-};
-
-/**
- * Returns a boolean indicating if we should create a new shard stream
- * @private
- */
-FileDemuxer.prototype._needsNewOutputStream = function() {
-  var expectedIndex = Math.floor(this._filePosition / this._shardSize);
-
-  return this._currentShardIndex < expectedIndex;
-};
-
-/**
- * Determine the optimal shard size given an arbitrary file size in bytes
- * @param {Object} fileInfo
- * @param {Number} fileInfo.fileSize - The number of bytes in the given file
- * @param {Number} fileInfo.shardConcurrency - Num of shards uploaded at once
- * @param {Number} [acc=1] - Accumulator (number of recursions)
- * @returns {Number} shardSize
- */
-FileDemuxer.getOptimalShardSize = function(fileInfo, acc) {
-  var accumulator = typeof acc === 'undefined' ? 0 : acc;
-
-  // Determine hops back by accumulator
-  var hops = (accumulator - FileDemuxer.SHARD_MULTIPLES_BACK) < 0 ?
-                 0 :
-                 accumulator - FileDemuxer.SHARD_MULTIPLES_BACK;
-
-  // Calculate bytemultiple shard size by hops back
-  var shardSize = function(hops) {
-    return (8 * (1024 * 1024)) * Math.pow(2, hops);
-  };
-
-  var byteMultiple = shardSize(accumulator);
-  var check = fileInfo.fileSize / byteMultiple;
-
-  // Determine if bytemultiple is highest bytemultiple that is still <= fileSize
-  if (check > 0 && check <= 1) {
-
-    // Certify the number of concurrency * shardSize doesn't exceed freemem
-    while (
-      hops > 0 &&
-      (os.freemem() / shardSize(hops) <= fileInfo.shardConcurrency)
-    ) {
-      hops = hops - 1 <= 0 ? 0 : hops - 1;
-    }
-
-    return shardSize(hops);
-  }
-
-  return this.getOptimalShardSize(fileInfo, ++accumulator);
-};
-
-module.exports = FileDemuxer;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_file-handling_file-muxer.js.html b/Storj/core/docs/lib_file-handling_file-muxer.js.html deleted file mode 100644 index 882afdc..0000000 --- a/Storj/core/docs/lib_file-handling_file-muxer.js.html +++ /dev/null @@ -1,230 +0,0 @@ - - - - - JSDoc: Source: lib/file-handling/file-muxer.js - - - - - - - - - - -
- -

Source: lib/file-handling/file-muxer.js

- - - - - - -
-
-
'use strict';
-
-var crypto = require('crypto');
-var assert = require('assert');
-var stream = require('readable-stream');
-var inherits = require('util').inherits;
-var merge = require('merge');
-var utils = require('../utils');
-var ExchangeReport = require('../bridge-client/exchange-report');
-
-/**
- * Accepts multiple ordered input sources and exposes them as a single
- * contiguous readable stream. Used for re-assembly of shards.
- * @constructor
- * @license LGPL-3.0
- * @param {Object} options
- * @param {Number} options.shards - Number of total shards to be multiplexed
- * @param {Number} options.length - Number of total bytes of input
- * @param {Number} options.sourceDrainWait - Time to wait for a new input after
- * all inputs are drained before entire stream is consumed
- * @param {Number} options.sourceIdleWait - Time to wait for source to make
- * more data available between next read
- * @fires FileMuxer#drain
- */
-function FileMuxer(options) {
-  if (!(this instanceof FileMuxer)) {
-    return new FileMuxer(options);
-  }
-
-  this._checkOptions(options);
-
-  this._hasher = crypto.createHash('sha256');
-  this._shards = options.shards;
-  this._length = options.length;
-  this._inputs = [];
-  this._bytesRead = 0;
-  this._added = 0;
-  this._options = merge(Object.create(FileMuxer.DEFAULTS), options);
-
-  stream.Readable.call(this);
-}
-
-FileMuxer.DEFAULTS = {
-  sourceDrainWait: 8000,
-  sourceIdleWait: 50
-};
-
-/**
- * Triggered when the muxer has drained one of the supplied inputs
- * @event FileMuxer#drain
- * @param {ReadableStream} input - The drained input stream
- */
-
-inherits(FileMuxer, stream.Readable);
-
-/**
- * Checks the options supplied to the constructor
- * @private
- */
-FileMuxer.prototype._checkOptions = function(options) {
-  var shards = options.shards;
-  var length = options.length;
-
-  assert(typeof shards === 'number', 'You must supply a shards parameter');
-  assert(shards > 0, 'Cannot multiplex a 0 shard stream');
-  assert(typeof length === 'number', 'You must supply a length parameter');
-  assert(length > 0, 'Cannot multiplex a 0 length stream');
-};
-
-/**
- * Implements the underlying read method
- * @private
- */
-FileMuxer.prototype._read = function() {
-  var self = this;
-
-  function _waitForSourceAvailable() {
-    self.once('sourceAdded', self._read.bind(self));
-
-    self._sourceDrainTimeout = setTimeout(function() {
-      self.removeAllListeners('sourceAdded');
-      self.emit('error', new Error('Unexpected end of source stream'));
-    }, self._options.sourceDrainWait);
-  }
-
-  function _mux(bytes) {
-    self._bytesRead += bytes.length;
-
-    if (self._length < self._bytesRead) {
-      return self.emit('error', new Error('Input exceeds expected length'));
-    }
-
-    self._hasher.update(bytes);
-    self.push(bytes);
-  }
-
-  function _readFromSource() {
-    var bytes = self._inputs[0] ? self._inputs[0].read() : null;
-
-    if (bytes !== null) {
-      return _mux(bytes);
-    }
-
-    setTimeout(_readFromSource, self._options.sourceIdleWait);
-  }
-
-  if (this._sourceDrainTimeout) {
-    clearTimeout(this._sourceDrainTimeout);
-  }
-
-  if (this._bytesRead === this._length) {
-    return this.push(null);
-  }
-
-  if (!this._inputs[0]) {
-    return _waitForSourceAvailable();
-  }
-
-  _readFromSource();
-};
-
-/**
- * Adds an additional input stream to the multiplexer
- * @param {ReadableStream} readable - Readable input stream from file shard
- * @param {String} hash - Hash of the shard
- * @param {ExchangeReport} - Instance of exchange report
- * @param {BridgeClient} - An instance of bridge client for reporting
- */
-FileMuxer.prototype.addInputSource = function(readable,
-                                              hash,
-                                              exchangeReport,
-                                              bridgeClient) {
-
-  assert(typeof readable.pipe === 'function', 'Invalid input stream supplied');
-  assert(this._added < this._shards, 'Inputs exceed defined number of shards');
-
-  var self = this;
-  var input = readable.pipe(stream.PassThrough()).pause();
-
-  input.once('readable', function() {
-    exchangeReport.begin(hash);
-  });
-
-  input.on('end', function() {
-    var inputHash = utils.rmd160(self._hasher.digest());
-    self._hasher = crypto.createHash('sha256');
-
-    self._inputs.splice(self._inputs.indexOf(input), 1);
-
-    if (inputHash !== hash) {
-      // Send the bridge a failure report
-      exchangeReport.end(ExchangeReport.FAILURE, 'FAILED_INTEGRITY');
-      bridgeClient.createExchangeReport(exchangeReport);
-
-      self.emit('error', new Error('Shard failed integrity check'));
-    } else {
-      // Send the bridge a success report
-      exchangeReport.end(ExchangeReport.SUCCESS, 'SHARD_DOWNLOADED');
-      bridgeClient.createExchangeReport(exchangeReport);
-    }
-
-    self.emit('drain', input);
-  });
-
-  readable.on('error', function(err) {
-    // Send the bridge a failure report
-    exchangeReport.end(ExchangeReport.FAILURE, 'DOWNLOAD_ERROR');
-    bridgeClient.createExchangeReport(exchangeReport);
-    self.emit('error', err);
-  });
-
-  this._added++;
-  this._inputs.push(input);
-  this.emit('sourceAdded');
-
-  return this;
-};
-
-module.exports = FileMuxer;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_network_contact.js.html b/Storj/core/docs/lib_network_contact.js.html deleted file mode 100644 index 6925840..0000000 --- a/Storj/core/docs/lib_network_contact.js.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - JSDoc: Source: lib/network/contact.js - - - - - - - - - - -
- -

Source: lib/network/contact.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var kad = require('kad');
-var inherits = require('util').inherits;
-var version = require('../version');
-var utils = require('../utils');
-var url = require('url');
-
-/**
-* Represents a Storj contact (or peer)
-* @constructor
-* @license LGPL-3.0
-* @param {Object} contact
-* @param {String} contact.address - Hostname of IP address
-* @param {Number} contact.port - RPC port number
-* @param {String} contact.nodeID - 160 bit node ID (hex)
-* @param {String} [contact.hdKey] - extended hd public key
-* @param {String} [contact.hdIndex] - derivation index for node
-* @param {String} [contact.userAgent] - User agent identifier
-* @param {String} contact.protocol - Semver tag for compatibility
-*/
-function Contact(options) {
-  if (!(this instanceof Contact)) {
-    return new Contact(options);
-  }
-
-  this.userAgent = options.userAgent || version.software;
-  this.protocol = options.protocol || version.protocol;
-
-  if (options.hdKey) {
-    assert(utils.isValidHDNodeKey(options.hdKey),
-           'hdKey is expected to be extended public key');
-    assert(utils.isValidNodeIndex(options.hdIndex),
-           'hdIndex is expected to be a non-hardened index');
-    this.hdKey = options.hdKey;
-    this.hdIndex = options.hdIndex;
-  } else {
-    this.hdKey = undefined;
-    this.hdIndex = undefined;
-  }
-
-  kad.contacts.AddressPortContact.call(this, options);
-}
-
-inherits(Contact, kad.contacts.AddressPortContact);
-
-/**
- * Indicates if URL is valid contact
- * @param {String}
- * @returns {Boolean}
- */
-Contact.isValidUrl = function(uri) {
-  let contact = null;
-
-  try {
-    contact = url.parse(uri);
-    assert(contact.protocol === 'storj:', 'Invalid protocol');
-    assert(
-      Buffer.from(contact.path.substr(1), 'hex').length * 8 === 160,
-      'Invalid node ID'
-    );
-    assert(
-      utils.isValidContact(Contact.fromUrl(uri),
-                           process.env.STORJ_ALLOW_LOOPBACK),
-      'Invalid contact data'
-    );
-  } catch (err) {
-    return false;
-  }
-
-  return true;
-};
-
-/**
- * Returns a Storj contact from the URI
- * @private
- * @param {String} uri
- */
-Contact.fromUrl = function(uri) {
-  var parsed = url.parse(uri);
-
-  return new Contact({
-    address: parsed.hostname,
-    port: Number(parsed.port),
-    nodeID: parsed.path.substr(1)
-  });
-};
-
-module.exports = Contact;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_network_farmer.js.html b/Storj/core/docs/lib_network_farmer.js.html deleted file mode 100644 index 4692416..0000000 --- a/Storj/core/docs/lib_network_farmer.js.html +++ /dev/null @@ -1,439 +0,0 @@ - - - - - JSDoc: Source: lib/network/farmer.js - - - - - - - - - - -
- -

Source: lib/network/farmer.js

- - - - - - -
-
-
'use strict';
-
-var kfs = require('kfs');
-var fs = require('fs');
-var path = require('path');
-var kad = require('kad');
-var Network = require('./');
-var inherits = require('util').inherits;
-var StorageItem = require('../storage/item');
-var Contract = require('../contract');
-var merge = require('merge');
-var constants = require('../constants');
-var utils = require('../utils');
-
-/**
- * Creates and a new farmer interface
- * @constructor
- * @license AGPL-3.0
- * @extends {Network}
- * @param {Object} options
- * @param {String} options.paymentAddress - Optional payment address
- * @param {Array} options.opcodeSubscriptions - Contract opcodes to farm
- * @param {Number} options.maxOfferConcurrency - Max offers to have pending
- * @param {FarmerInterface~negotiator} options.contractNegotiator
- * @param {KeyPair} options.keyPair - Node's cryptographic identity
- * @param {StorageManager} options.storageManager - Storage manager backend
- * @param {String} options.bridgeUri - URL for bridge server seed lookup
- * @param {Object} options.logger - Logger instance
- * @param {Array} options.seedList - List of seed URIs to join
- * @param {String} options.rpcAddress - Public node IP or hostname
- * @param {Number} options.rpcPort - Listening port for RPC
- * @param {Boolean} options.doNotTraverseNat - Skip NAT traversal strategies
- * @param {Number} options.maxTunnels - Max number of tunnels to provide
- * @param {Number} options.tunnelServerPort - Port for tunnel server to use
- * @param {Object} options.tunnelGatewayRange
- * @param {Number} options.tunnelGatewayRange.min - Min port for gateway binding
- * @param {Number} options.tunnelGatewayRange.max - Max port for gateway binding
- * @param {Number} [options.offerBackoffLimit=4] - Do not send offers if more
- * than N transfers are active
- * @param {String[]} [options.renterWhitelist] - Node IDs to offer storage to
- * @param {Object} [options.joinRetry]
- * @param {Number} [options.joinRetry.times] - Times to retry joining net
- * @param {Number} [options.joinRetry.interval] - MS to wait before retrying
- * @emits Network#ready
- * @property {KeyPair} keyPair
- * @property {StorageManager} storageManager
- * @property {kad.Node} node - The underlying DHT node
- * @property {TriggerManager} triggerManager
- * @property {BridgeClient} bridgeClient
- * @property {Contact} contact
- * @property {Transport} transportAdapter
- * @property {kad.Router} router - The underlying DHT router
- * @property {DataChannelServer} dataChannelServer
- */
-function FarmerInterface(options) {
-  if (!(this instanceof FarmerInterface)) {
-    return new FarmerInterface(options);
-  }
-
-  options = merge.recursive(Object.create(FarmerInterface.DEFAULTS), options);
-
-  this._negotiator = options.contractNegotiator;
-  this._pendingOffers = [];
-  this._offerBackoffLimit = options.offerBackoffLimit;
-  this._renterWhitelist = Array.isArray(options.renterWhitelist) ?
-                          options.renterWhitelist :
-                          null;
-
-  Network.call(this, options);
-}
-
-inherits(FarmerInterface, Network);
-
-/**
- * Called when a contract is found that meets subscription criteria and allows
- * us to modify the contract terms if we desire and then uses the return value
- * to determine if we should send the renter an offer
- * @callback FarmerInterface~negotiator
- * @param {Contract} contract - The contract object to negotiate
- * @returns {Boolean}
- */
-
-FarmerInterface.Negotiator = function(contract, callback) {
-  var self = this;
-
-  if (this._renterWhitelist) {
-    var allowed =  {
-      renterNodeId: this._renterWhitelist.indexOf(
-        contract.get('renter_id')
-      ) !== -1,
-      renterExtendedPubKey: this._renterWhitelist.indexOf(
-        contract.get('renter_hd_key')
-      ) !== -1
-    };
-    var isWhitelisted = allowed.renterNodeId || allowed.renterExtendedPubKey;
-
-    self._logger.debug('renter is whitelisted: %s', isWhitelisted);
-
-    if (!isWhitelisted) {
-      return callback(false);
-    }
-  }
-
-  if (!contract.get('data_hash')) {
-    self._logger.warn('contract received with invalid data_hash, ignoring');
-    return callback(false);
-  }
-
-  // NB: Backoff on sending offers if we are already have high active transfer
-  var concurrentTransfer = (
-    self.transport.shardServer.activeTransfers >= self._offerBackoffLimit
-  );
-  self._logger.debug(
-    'active transfers %s is less than offerBackoffLimit %s: %s',
-    self.transport.shardServer.activeTransfers,
-    self._offerBackoffLimit,
-    !concurrentTransfer
-  );
-  if (concurrentTransfer) {
-    self._logger.warn('too many active transfers, not sending offer');
-    return callback(false);
-  }
-
-  // NB: Only bid on contracts for data we don't have
-  this.storageManager.load(contract.get('data_hash'), function(err, item) {
-    if (err) {
-      self._logger.debug('no storage item available for this shard');
-      return callback(true);
-    }
-
-    var renters = Object.keys(item.contracts);
-
-    if (renters.indexOf(contract.get('renter_id')) === -1) {
-      self._logger.debug('no contract currently staged for this shard');
-      return callback(true);
-    }
-
-    if (typeof item.shard.write === 'function') {
-      self._logger.debug('no data currently stored for this shard');
-      return callback(true);
-    }
-
-    self._logger.debug('shard already stored, not sending offer');
-    callback(false);
-  });
-};
-
-FarmerInterface.DEFAULTS = {
-  renterWhitelist: fs.readFileSync(
-    path.join(__dirname, '../../TRUSTED_KEYS')
-  ).toString().split('\n').filter((k) => !!k),
-  paymentAddress: '',
-  opcodeSubscriptions: ['0f01020202', '0f02020202', '0f03020202'],
-  contractNegotiator: FarmerInterface.Negotiator,
-  maxOfferConcurrency: constants.MAX_CONCURRENT_OFFERS,
-  offerBackoffLimit: 4
-};
-
-/**
- * Wraps the super call to {@link Network#join} to listen for contract after
- * successfully establishing a connection to the network
- * @param {Function} callback - Called on successful join
- */
-FarmerInterface.prototype.join = function(callback) {
-  var self = this;
-
-  Network.prototype.join.call(this, function(err) {
-    if (err) {
-      return callback(err);
-    }
-
-    self._listenForContracts(self._options.opcodeSubscriptions);
-    self.on(
-      'connected',
-      self._listenForContracts.bind(self, self._options.opcodeSubscriptions)
-    );
-    callback();
-  });
-};
-
-/**
- * Sends the given contract as an offer to the specified renter
- * @private
- * @param {Contract} contract - The contract to include in offer
- * @param {Contact} renter - The renter who originally published the contract
- */
-FarmerInterface.prototype._sendOfferForContract = function(contract, contact) {
-  var self = this;
-  var message = new kad.Message({
-    method: 'OFFER',
-    params: {
-      contract: contract.toObject(),
-      contact: self.contact
-    }
-  });
-
-  self._logger.debug('Sending offer for contract hash %s',
-    contract.get('data_hash'));
-  self._removeContractFromPendingList(contract);
-  self.transport.send(contact, message, function(err, response) {
-    if (err) {
-      return self._logger.warn(err.message);
-    }
-
-    if (response.error || !response.result.contract) {
-      return self._logger.warn(
-        response.error ? response.error.message : 'Renter refused to sign'
-      );
-    }
-
-    self._handleOfferRes(response, contract, contact);
-  });
-};
-
-/**
- * Returns the payment address supplied or the derived one from keypair
- * @returns {String}
- */
-FarmerInterface.prototype.getPaymentAddress = function() {
-  return this._options.paymentAddress || this.keyPair.getAddress();
-};
-
-/**
- * Handles a received contract and negotiates storage
- * @private
- * @param {Contract} contract
- */
-FarmerInterface.prototype._negotiateContract = function(contract, contact) {
-  var self = this;
-
-  contract.set('farmer_id', self.keyPair.getNodeID());
-  contract.set('payment_destination', self.getPaymentAddress());
-  contract.sign('farmer', self.keyPair.getPrivateKey());
-
-  var item = new StorageItem({ hash: contract.get('data_hash') });
-  var renterId = contract.get('renter_id');
-
-  if (typeof renterId !== 'string') {
-    self._removeContractFromPendingList(contract);
-    return self._logger.warn('dropping invalid contract with no renter id');
-  }
-
-  item.addContract({ nodeID: renterId }, contract);
-  item.addMetaData({ nodeID: renterId }, {});
-
-  self.storageManager.save(item, function(err) {
-    if (err) {
-      self._removeContractFromPendingList(contract);
-      return self._logger.error(err.message);
-    }
-
-    self._sendOfferForContract(contract, contact);
-  });
-};
-
-/**
- * Checks if we should send an offer by checking the pending offers and running
- * the optional custom negotiator function
- * @private
- * @param {Contract} contract
- * @param {Function} callback
- */
-FarmerInterface.prototype._shouldSendOffer = function(contract, callback) {
-  var self = this;
-
-  this._negotiator.call(this, contract, function(shouldNegotiate) {
-    /* eslint max-statements: [2, 16] */
-    self._logger.debug('negotiator returned: %s', shouldNegotiate);
-    self.storageManager._storage.size(
-      contract.get('data_hash'),
-      function(err, usedSpace) {
-        if (err) {
-          self._logger.error('Could not get usedSpace: %s',err.message);
-          return callback(false);
-        }
-
-        var maxCapacity = self.storageManager._options.maxCapacity;
-        var estimatedMaxBucketSize = Math.floor(maxCapacity / kfs.constants.B);
-        var freeSpace = estimatedMaxBucketSize - usedSpace;
-        var enoughFreeSpace = contract.get('data_size') <= freeSpace;
-        self._logger.debug('we have enough free space: %s', enoughFreeSpace);
-
-        callback(shouldNegotiate && enoughFreeSpace);
-      }
-    );
-  });
-};
-
-/**
- * Adds the contract data hash to the pending offers list
- * @private
- * @param {Contract} contract - The contract being negotiated
- */
-FarmerInterface.prototype._addContractToPendingList = function(contract) {
-  var id = contract.get('data_hash') + contract.get('renter_id');
-
-  if (this._pendingOffers.indexOf(id) !== -1) {
-    return 0;
-  }
-
-  return this._pendingOffers.push(id);
-};
-
-/**
- * Removes the contract data hash to the pending offers list
- * @param {Contract} contract - The contract being negotiated
- * @private
- */
-FarmerInterface.prototype._removeContractFromPendingList = function(contract) {
-  var index = this._pendingOffers.indexOf(
-    contract.get('data_hash') + contract.get('renter_id')
-  );
-
-  if (index === -1) {
-    return;
-  }
-
-  this._pendingOffers.splice(index, 1);
-};
-
-/**
- * Handles an offer response from a renter
- * @private
- */
-FarmerInterface.prototype._handleOfferRes = function(res, contract, renter) {
-  var self = this;
-  var final = null;
-
-  try {
-    final = Contract.fromObject(res.result.contract);
-  } catch (err) {
-    return self._logger.warn('renter responded with invalid contract');
-  }
-
-  if (!final.verify('renter', contract.get('renter_id'))) {
-    return self._logger.warn('renter signature is invalid');
-  }
-
-  self.storageManager.load(contract.get('data_hash'), function(err, item) {
-    if (err) {
-      item = new StorageItem({ hash: contract.get('data_hash') });
-    }
-
-    item.addContract(renter, contract);
-    item.addMetaData(renter, {});
-    self.storageManager.save(item, utils.noop);
-    self._logger.info('Offer accepted');
-  });
-};
-
-/**
- * Subscribes to a contract identifier on the network
- * @private
- * @param {Array} opcodes
- */
-FarmerInterface.prototype._listenForContracts = function(opcodes) {
-  this.subscribe(opcodes, this._handleContractPublication.bind(this));
-};
-
-/**
- * Handles received contract publications
- * @private
- * @param {Object} contract - The raw contract object
- */
-FarmerInterface.prototype._handleContractPublication = function(contract) {
-  var self = this;
-  var contractObj;
-  var contact = contract.contact;
-
-  this._logger.debug('received contract offer...');
-
-  try {
-    contractObj = Contract.fromObject(contract);
-  } catch (err) {
-    return; // If the contract is invalid just drop it
-  }
-
-  this._shouldSendOffer(contractObj, function(shouldSendOffer) {
-    if (!shouldSendOffer) {
-      return self._logger.debug('not sending an offer for the contract');
-    }
-
-    self._addContractToPendingList(contractObj);
-    self._negotiateContract(contractObj, contact);
-  });
-};
-
-module.exports = FarmerInterface;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_network_index.js.html b/Storj/core/docs/lib_network_index.js.html deleted file mode 100644 index cd895ab..0000000 --- a/Storj/core/docs/lib_network_index.js.html +++ /dev/null @@ -1,1005 +0,0 @@ - - - - - JSDoc: Source: lib/network/index.js - - - - - - - - - - -
- -

Source: lib/network/index.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var merge = require('merge');
-var async = require('async');
-var kad = require('kad');
-var HDKey = require('hdkey');
-var bitcore = require('bitcore-lib');
-var secp256k1 = require('secp256k1');
-var constants = require('../constants');
-var Message = require('bitcore-message');
-var Quasar = require('kad-quasar').Protocol;
-var utils = require('../utils');
-var KeyPair = require('../crypto-tools/keypair');
-var StorageManager = require('../storage/manager');
-var Protocol = require('./protocol');
-var Contact = require('./contact');
-var Transport = require('./transport');
-var EventEmitter = require('events').EventEmitter;
-var inherits = require('util').inherits;
-var diglet = require('diglet');
-var shuffle = require('knuth-shuffle').knuthShuffle;
-var BridgeClient = require('../bridge-client');
-var TriggerManager = require('../sips').SIP0003.TriggerManager;
-var OfferManager = require('../contract/offer-manager');
-
-/**
- * Storj network interface
- * @constructor
- * @license AGPL-3.0
- * @param {Object}  options
- * @param {String} [options.hdKey] - Extended SIP32 private key at 'group index'
- * @param {Number} [options.hdIndex] - Derivation index for hdKey
- * @param {KeyPair} [options.keyPair] - Node's cryptographic identity
- * @param {StorageManager} options.storageManager - Storage manager backend
- * @param {String} options.bridgeUri - URL for bridge server seed lookup
- * @param {Object} options.logger - Logger instance
- * @param {Array} options.seedList - List of seed URIs to join
- * @param {String} options.rpcAddress - Public node IP or hostname
- * @param {Number} options.rpcPort - Listening port for RPC
- * @param {Number} options.listenPort - Optional different listening port for RPC to bind to
- * @param {Boolean} options.doNotTraverseNat - Skip NAT traversal strategies
- * @param {Number} options.maxTunnels - Max number of tunnels to provide
- * @param {Number} options.maxConnections - Max concurrent connections
- * @param {Object} options.tunnelGatewayRange
- * @param {Number} options.tunnelGatewayRange.min - Min port for gateway bind
- * @param {Number} options.tunnelGatewayRange.max - Max port for gateway bind
- * @param {Object} [options.joinRetry]
- * @param {Number} [options.joinRetry.times] - Times to retry joining net
- * @param {Number} [options.joinRetry.interval] - MS to wait before retrying
- * @emits Network#ready
- * @property {KeyPair} keyPair
- * @property {StorageManager} storageManager
- * @property {kad.Node} node - The underlying DHT node
- * @property {TriggerManager} triggerManager
- * @property {BridgeClient} bridgeClient
- * @property {Contact} contact
- * @property {Transport} transportAdapter
- * @property {kad.Router} router - The underlying DHT router
- * @property {ShardServer} shardServer
- * @property {OfferManager} offerManager
- */
-function Network(options) {
-  if (!(this instanceof Network)) {
-    return new Network(options);
-  }
-
-  this._initKeyPair(options);
-  this.storageManager = options.storageManager;
-  this.offerManager = new OfferManager();
-
-  this._tunnelers = kad.Bucket();
-  this._options = this._checkOptions(options);
-  this._logger = options.logger;
-  this._storage = new kad.storage.MemStore();
-  this._pubkeys = {};
-  this._hdcache = {};
-  this._open = false;
-
-  this._initNetworkInterface();
-}
-
-inherits(Network, EventEmitter);
-
-Network.prototype._initKeyPair = function(options) {
-  if (options.hdKey) {
-    assert(!options.keyPair, '"keyPair" is not expected with "hdKey"');
-    assert(options.hdIndex, '"hdIndex" is expected with "hdKey"');
-    this.hdKey = HDKey.fromExtendedKey(options.hdKey);
-    this.hdIndex = options.hdIndex;
-    var key = this.hdKey.deriveChild(this.hdIndex);
-    this.keyPair = new KeyPair(key.privateKey.toString('hex'));
-  } else {
-    this.hdKey = null;
-    this.hdIndex = null;
-    this.keyPair = options.keyPair;
-  }
-};
-
-/**
- * Triggered when the transport's network interface is ready
- * @event Network#ready
- */
-
-/**
- * Triggered when the node has entered the overlay network
- * @event Network#connected
- */
-
-/**
- * Triggered when the node has exited the overlay network
- * @event Network#disconnected
- */
-
-/**
- * Triggered when an error occurs
- * @event Network#error
- */
-
-/**
- * Triggered when a valid offer is received, but we are not waiting for one
- * @event Network#unhandledOffer
- * @param {Contact} contact - The farmer contact the offer is from
- * @param {Contract} contract - The complete contract, signed by us and farmer
- * @param {Protocol~unhandledOfferResolver}
- */
-
-/**
- * Triggered when an unhandled offer is handled by the
- * {@link Network#unhandledOffer} listener by calling the event's supplied
- * {@link Network~unhandledOfferResolver}
- * @event Network#unhandledOfferResolved
- * @param {Contact} contact - The farmer contact the offer is from
- * @param {Contract} contract - The complete contract, signed by us and farmer
- */
-
-Network.DEFAULTS = {
-  bridgeUri: process.env.STORJ_BRIDGE || 'https://api.storj.io',
-  seedList: [],
-  joinRetry: { times: 1, interval: 5000 },
-  rpcAddress: '127.0.0.1',
-  rpcPort: 4000,
-  doNotTraverseNat: false,
-  maxTunnels: 3,
-  maxConnections: 150,
-  tunnelServerPort: 4001,
-  tunnelGatewayRange: { min: 4002, max: 4004 }
-};
-
-Network.RPC_VALIDATION_EXEMPT = [
-  'PROBE',
-  'FIND_TUNNEL',
-  'OPEN_TUNNEL'
-];
-
-/**
- * Check the options supplied to the constructor
- * @private
- */
-Network.prototype._checkOptions = function(options) {
-  assert(
-    options.keyPair instanceof KeyPair || typeof options.hdKey === 'string',
-    'Invalid keypair supplied'
-  );
-  assert(
-    options.storageManager instanceof StorageManager,
-    'Invalid manager supplied'
-  );
-  assert.ok(this._validateLogger(options.logger), 'Invalid logger supplied');
-
-  return merge(JSON.parse(JSON.stringify(Network.DEFAULTS)), options);
-};
-
-/**
- * Validates the logger object supplied
- * @private
- */
-Network.prototype._validateLogger = function(logger) {
-  return logger && logger.debug && logger.warn && logger.info && logger.error;
-};
-
-/**
- * Binds the transport adapter's hooks and events
- * @private
- */
-Network.prototype._bindTransportHooks = function() {
-  this.transport.on('error', this._handleTransportError.bind(this));
-  this.transport.before('serialize', this._signMessage.bind(this));
-  this.transport.before('receive', this._verifyMessage.bind(this));
-  this.transport.before('receive', kad.hooks.protocol(
-    this._protocol.getRouteMap()
-  ));
-  // NB: After receiving a message, reset the net re-entry timeout
-  this.transport.after('receive', () => {
-    clearTimeout(this._reEntryTimeout);
-    this._reEntryTimeout = setTimeout(
-      () => this._enterOverlay(utils.noop),
-      constants.NET_REENTRY
-    );
-  });
-};
-
-/**
- * Opens the connection to the network
- * @param {Function} callback - Called on successful network join
- */
-Network.prototype.join = function(callback) {
-  var self = this;
-
-  if (!this._ready) {
-    return this.once('ready', this.join.bind(this, callback));
-  }
-
-  this.node = new kad.Node({
-    transport: this.transport,
-    router: this.router,
-    storage: this._storage,
-    logger: this._logger
-  });
-
-  if (typeof callback === 'function') {
-    self.once('error', callback);
-    self.once('connected', function() {
-      if (self.transport._isPublic) {
-        self._listenForTunnelers();
-      }
-
-      self.removeListener('error', callback);
-      callback(null, self);
-    });
-  }
-
-  function onJoinComplete(err) {
-    if (err) {
-      return self.emit('error', err);
-    }
-
-    self.emit('connected');
-  }
-
-  async.series(
-    [
-      this._warnIfClockNotSynced.bind(this), // TODO: Make this not fail hard
-      this.storageManager.open.bind(this.storageManager),
-      this._setupTunnelClient.bind(this),
-    ],
-    function(err) {
-      if (err) {
-        return self.emit('error', err);
-      }
-
-      // enter overlay network and retry if failed
-      async.retry(
-        {
-          times: self._options.joinRetry.times,
-          interval: self._options.joinRetry.interval
-        },
-        self._enterOverlay.bind(self),
-        onJoinComplete
-      );
-    }
-  );
-};
-
-/**
- * Iteratively attempt connection to network via supplied seeds
- * @private
- */
-Network.prototype._enterOverlay = function(onConnected) {
-  var self = this;
-
-  function _trySeeds() {
-    async.detectSeries(self._options.seedList, function(uri, next) {
-      self._logger.info('attempting to join network via %s', uri);
-      self.connect(uri, function(err) {
-        if (err) {
-          self._logger.warn('failed to connect to seed %s', uri);
-          next(null, false);
-        } else {
-          self._logger.info('connected to the storj network via %s', uri);
-          next(null, true);
-        }
-      });
-    }, function(err, result) {
-      if (err || !result) {
-        // NB: If we fail to join log a warning and retry in 10 mins
-        self._logger.warn('failed to join the network, queuing re-entry');
-      }
-
-      // NB: Force re-entry into network to refresh routes every 10 minutes
-      clearTimeout(self._reEntryTimeout);
-      self._reEntryTimeout = setTimeout(_trySeeds, constants.NET_REENTRY);
-      onConnected(null);
-    });
-  }
-
-  if (this._options.seedList.length) {
-    return _trySeeds();
-  }
-
-  if (this._options.bridgeUri === null) {
-    self._logger.warn('no bridge uri or seeds provided, not connected');
-    return onConnected(null);
-  }
-
-  this._logger.info('resolving seeds from %s', this._options.bridgeUri);
-  this.bridgeClient.getContactList({ connected: true }, function(err, seeds) {
-    if (err) {
-      return onConnected(
-        new Error('Failed to discover seeds from bridge: ' + err.message)
-      );
-    }
-
-    self._options.seedList = shuffle(seeds)
-      .filter((c) => c.nodeID !== self.contact.nodeID)
-      .filter((c) => utils.isCompatibleVersion(
-        c.protocol,
-        process.env.STORJ_ALLOW_LOOPBACK
-      ))
-      .filter((c) => utils.isValidContact(c))
-      .map(utils.getContactURL);
-
-    _trySeeds();
-  });
-};
-
-/**
- * Disconnects from the network
- * @param {Function} callback - Called when successful disconnect
- */
-Network.prototype.leave = function(callback) {
-  var self = this;
-
-  if (typeof callback === 'function') {
-    this.once('error', callback);
-    this.once('disconnected', function() {
-      this.removeListener('error', callback);
-      callback(null);
-    });
-  }
-
-  this.storageManager.close(function(err) {
-    if (err) {
-      return self.emit('error', err);
-    }
-
-    self.node.disconnect(function(err) {
-      if (err) {
-        return self.emit('error', err);
-      }
-
-      self.emit('disconnected');
-    });
-  });
-};
-
-/**
- * Publishes a topic with content to the network
- * @param {String} topic - The serialized opcode topic
- * @param {Object} contents - Arbitrary publication contents
- * @param {Object} options - Options to pass to kad-quasar
- */
-Network.prototype.publish = function(topic, contents, options) {
-  return this._pubsub.publish(topic, contents, options);
-};
-
-/**
- * Subscribes to a topic on the network
- * @param {String} topic - The serialized opcode topic
- * @param {Object} handler - Function to handle received publications
- */
-Network.prototype.subscribe = function(topic, handler) {
-  return this._pubsub.subscribe(topic, handler);
-};
-
-/**
- * Connects to the node at the given URI
- * @param {String} uri - The storj protocol URI to connect
- * @param {Function} callback - Called on connection or error
- */
-Network.prototype.connect = function(uri, callback) {
-  const self = this;
-
-  callback = typeof callback === 'function' ? callback : function(err) {
-    if (err) {
-      self._logger.warn('failed to connect to %s, reason: %s',
-                        uri, err.message);
-    } else {
-      self._logger.info('connection established with %s', uri);
-    }
-  };
-
-  if (!Contact.isValidUrl(uri)) {
-    return callback(new Error('Invalid contact URI supplied'));
-  }
-
-  return this.node.connect(Contact.fromUrl(uri), callback);
-};
-
-/**
- * Will ping a neighbor
- * @param {String} neighbor - A contact
- * @param {Function} callback - Called on connection or error
- */
-Network.prototype.ping = function(neighbor, callback) {
-  var message = new kad.Message({
-    method: 'PING',
-    params: { contact: this.contact }
-  });
-
-  this.transport.send(neighbor, message, callback);
-};
-
-/**
- * Initilizes the network interface
- * @private
- */
-Network.prototype._initNetworkInterface = function() {
-  EventEmitter.call(this);
-
-  this.triggerManager = new TriggerManager();
-  this.bridgeClient = new BridgeClient(this._options.bridgeUri, {
-    logger: this._logger
-  });
-  this.contact = new Contact({
-    address: this._options.rpcAddress,
-    port: this._options.rpcPort,
-    nodeID: this.keyPair.getNodeID(),
-    hdKey: this.hdKey ? this.hdKey.publicExtendedKey : undefined,
-    hdIndex: this.hdIndex ? this.hdIndex : undefined
-  });
-  this.transport = new Transport(this.contact, {
-    logger: this._logger,
-    maxTunnels: this._options.maxTunnels,
-    maxConnections: this._options.maxConnections,
-    tunnelGatewayRange: this._options.tunnelGatewayRange,
-    doNotTraverseNat: this._options.doNotTraverseNat,
-    storageManager: this.storageManager,
-    bridgeClient: this._bridgeClient,
-    listenPort: this._options.listenPort
-  });
-  this.router = new kad.Router({
-    transport: this.transport,
-    logger: this._logger
-  });
-
-  this._protocol = new Protocol({ network: this });
-  this.transport.after('open', this._onTransportOpen.bind(this));
-  this._startRouterCleaner();
-};
-
-/**
- * Set up {@link ShardServer} after transport is ready
- * @private
- */
-Network.prototype._onTransportOpen = function() {
-  this._bindTransportHooks();
-
-  this._ready = true;
-  this._pubsub = new Quasar(this.router, {
-    logger: this._logger,
-    randomRelay: true,
-    maxRelayHops: constants.PUBLISH_TTL
-  });
-
-  this.emit('ready');
-};
-
-/**
- * Signs an outgoing message
- * @private
- * @param {kad.Message} message
- * @param {Function} callback
- */
-Network.prototype._signMessage = function(message, callback) {
-  var nonce = Date.now();
-  var target = message.id + nonce;
-  var signature = null;
-
-  try {
-    signature = this.keyPair.sign(target);
-  } catch (err) {
-    return callback(err);
-  }
-
-  if (kad.Message.isRequest(message)) {
-    message.params.nonce = nonce;
-    message.params.signature = signature;
-  } else {
-    message.result.nonce = nonce;
-    message.result.signature = signature;
-  }
-
-  callback();
-};
-
-/**
- * Verifies that the supplied contact is valid and compatible
- * @private
- * @param {Contact} contact
- */
-Network.prototype._validateContact = function(contact, callback) {
-  if (!utils.isCompatibleVersion(contact.protocol)) {
-    this.router.removeContact(contact);
-    return callback(new Error('Protocol version is incompatible'));
-  }
-
-  if (!utils.isValidContact(contact, process.env.STORJ_ALLOW_LOOPBACK)) {
-    this.router.removeContact(contact);
-    return callback(new Error('Invalid contact data supplied'));
-  }
-
-  callback(null);
-};
-
-/**
- * Verifies an incoming message
- * @private
- * @param {kad.Message} message
- * @param {Contact} contact
- * @param {Function} callback
- */
-Network.prototype._verifyMessage = function(message, contact, callback) {
-  var self = this;
-
-  this._validateContact(contact, function(err) {
-    if (err && Network.RPC_VALIDATION_EXEMPT.indexOf(message.method) === -1) {
-      return callback(err);
-    }
-
-    var messagekey = kad.Message.isRequest(message) ? 'params' : 'result';
-    var nonce = message[messagekey].nonce;
-    var signature = message[messagekey].signature;
-
-    if (Date.now() > (constants.NONCE_EXPIRE + nonce)) {
-      return callback(new Error('Message signature expired'));
-    }
-
-    var addr = bitcore.Address.fromPublicKeyHash(Buffer(contact.nodeID, 'hex'));
-    var signobj = self._createSignatureObject(signature);
-
-    self._verifySignature({
-      message: message,
-      nonce: nonce,
-      signobj: signobj,
-      address: addr,
-      contact: contact,
-      signature: signature
-    }, callback);
-  });
-};
-
-/**
- * Verifies the validity of the supplied signature
- * @private
- */
-Network.prototype._verifySignature = function(options, callback) {
-  /* eslint max-statements: [2, 20] */
-  if (!options.signobj) {
-    return callback(new Error('Invalid signature supplied'));
-  }
-
-  var signedmsg = Message(options.message.id + options.nonce);
-  var magic = signedmsg.magicHash();
-  var recovery = options.signobj.i;
-  var sig = secp256k1.signatureImport(options.signobj.toBuffer());
-  var pubKey = this._pubkeys[options.contact.nodeID];
-
-  if (!pubKey) {
-    try {
-      pubKey = secp256k1.recover(magic, sig, recovery, true);
-      this._pubkeys[options.contact.nodeID] = pubKey;
-    } catch (e) {
-      return callback(e);
-    }
-  }
-
-  if (!secp256k1.verify(magic, sig, pubKey)) {
-    return callback(new Error('Signature verification failed'));
-  }
-
-  if (!this._verifyHDKeyContact(options.contact, pubKey)) {
-    return callback(new Error('Invalid derived public key'));
-  }
-
-  callback(null);
-};
-
-Network.prototype._verifyHDKeyContact = function(contact, publicKeyBuffer) {
-  if (contact.hdKey) {
-    var contactPub = this._hdcache[contact.hdKey + contact.hdIndex];
-    if (!contactPub) {
-      var hdKey = HDKey.fromExtendedKey(contact.hdKey);
-      var nodeKey = hdKey.deriveChild(contact.hdIndex);
-      contactPub = nodeKey.publicKey;
-      this._hdcache[contact.hdKey + contact.hdIndex] = contactPub;
-    }
-    if (contactPub.compare(publicKeyBuffer) === 0) {
-      return true;
-    }
-    return false;
-  }
-  return true;
-};
-
-/**
- * Creates a signature object from signature string
- * @private
- */
-Network.prototype._createSignatureObject = function(signature) {
-  var compactSig;
-  var signobj;
-
-  try {
-    compactSig = new Buffer(signature, 'base64');
-    signobj = bitcore.crypto.Signature.fromCompact(compactSig);
-  } catch (err) {
-    return null;
-  }
-
-  return signobj;
-};
-
-/**
- * Proxies error events from the underlying transport adapter
- * @private
- * @param {Error} error
- */
-Network.prototype._handleTransportError = function(error) {
-  this._logger.warn(error.message);
-};
-
-/**
- * Subscribe to tunneler opcodes to manage known tunnelers
- * @private
- */
-Network.prototype._listenForTunnelers = function() {
-  var self = this;
-  var tunserver = self.transport.tunnelServer;
-  var prefix = Buffer([constants.OPCODE_TUNNELER_PREFIX], 'hex');
-  var available = Buffer([constants.OPCODE_DEG_LOW], 'hex');
-  var unavailable = Buffer([constants.OPCODE_DEG_NULL], 'hex');
-
-  function announce() {
-    let hasTunnelAvailable = Object.keys(
-      tunserver._proxies
-    ).length < tunserver._opts.maxProxiesAllowed;
-    self._pubsub.publish(
-      Buffer.concat([
-        prefix,
-        hasTunnelAvailable ? available : unavailable
-      ]).toString('hex'),
-      self.contact
-    );
-    setTimeout(announce, constants.TUNNEL_ANNOUNCE_INTERVAL);
-  }
-
-  if (this._options.maxTunnels) {
-    announce();
-  }
-
-  var tunUp = Buffer.concat([prefix, available]).toString('hex');
-  var tunDown = Buffer.concat([prefix, unavailable]).toString('hex');
-
-  this._pubsub.subscribe([tunUp, tunDown], function(contact, topic) {
-    if (topic === tunUp) {
-      if (!self._tunnelers.addContact(Contact(contact))) {
-        self._tunnelers.removeContact(self._tunnelers.getContact(0));
-        self._tunnelers.addContact(Contact(contact));
-      }
-    } else {
-      self._tunnelers.removeContact(Contact(contact));
-    }
-  });
-};
-
-/**
- * Determines if tunnel is needed
- * @private
- * @param {Function} callback
- */
-Network.prototype._setupTunnelClient = function(callback) {
-  var self = this;
-
-  if (this.transport._isPublic) {
-    return callback(null);
-  }
-
-  var neighbors = this._options.seedList
-    .filter(Contact.isValidUrl)
-    .map(Contact.fromUrl)
-    .filter((c) => c.nodeID !== self.contact.nodeID);
-
-  function _discoverIfReachable() {
-    self._logger.info('requesting probe from nearest neighbor');
-    self._requestProbe(neighbors[0], function(err, result) {
-      if (err || result.error) {
-        return self._findTunnel(neighbors, callback);
-      }
-
-      self._logger.info(
-        'you are publicly reachable, skipping tunnel establishment'
-      );
-      callback(null);
-    });
-  }
-
-  if (!neighbors.length) {
-    if (this._options.bridgeUri === null) {
-      return callback(
-        new Error('Could not find a neighbor to query for probe')
-      );
-    }
-
-    return this.bridgeClient.getContactList({}, function(err, result) {
-      if (err) {
-        return callback(new Error('Failed to get seeds for probe'));
-      }
-
-      neighbors = result.map(function(c) {
-        return new Contact(c);
-      });
-
-      _discoverIfReachable();
-    });
-  }
-
-  _discoverIfReachable();
-};
-
-/**
- * Requests a probe from the nearest neighbor
- * @private
- */
-Network.prototype._requestProbe = function(neighbor, callback) {
-  var message = new kad.Message({
-    method: 'PROBE',
-    params: { contact: this.contact }
-  });
-
-  this.transport.send(neighbor, message, callback);
-};
-
-/**
- * Finds a potential tunneler
- * @private
- * @param {Array} neighbors
- * @param {Function} callback
- */
-Network.prototype._findTunnel = function(neighbors, callback) {
-  var self = this;
-  var tunnelers = [];
-  var message = new kad.Message({
-    method: 'FIND_TUNNEL',
-    params: {
-      contact: this.contact,
-      relayers: []
-    }
-  });
-
-  // NB: If we are going to be tunneled, we better not accept any tunnel
-  // NB: connections from other nodes, so let's override our maxTunnels.
-  this._options.maxTunnels = 0;
-  this.transport.tunnelServer._opts.maxProxiesAllowed = 0;
-
-  if (!neighbors.length) {
-    return callback(
-      new Error('Could not find a neighbor to query for tunnels')
-    );
-  }
-
-  async.detectSeries(neighbors, function(neighbor, callback) {
-    self._logger.info('requesting tunnelers from neighbor');
-    self.transport.send(neighbor, message, function(err, resp) {
-      if (err) {
-        return callback(null, false);
-      }
-
-      if (!resp.result.tunnels.length) {
-        return callback(null, false);
-      }
-
-      tunnelers = tunnelers.concat(resp.result.tunnels).filter(
-        t => t.nodeID !== self.contact.nodeID
-      );
-
-      callback(null, true);
-    });
-  }, function() {
-    if (!tunnelers.length) {
-      return callback(
-        new Error('Failed to find tunnels from neighbors')
-      );
-    }
-
-    self._establishTunnel(tunnelers, callback);
-  });
-};
-
-/**
- * Creates a tunnel to a public node
- * @private
- * @param {Function} callback
- */
-Network.prototype._establishTunnel = function(tunnels, callback) {
-  var self = this;
-  var remoteAddress, remotePort, proxyPort;
-
-  function established() {
-    return proxyPort && remotePort && remoteAddress;
-  }
-
-  function openTunnel(done) {
-    if (!tunnels.length) {
-      return done(new Error('No tunnelers were returned'));
-    }
-
-    var tun = new Contact(tunnels[0]);
-    var msg = kad.Message({
-      method: 'OPEN_TUNNEL',
-      params: { contact: self.contact }
-    });
-
-    tunnels.shift();
-    self.transport.send(tun, msg, function(err, resp) {
-      if (err) {
-        return done();
-      }
-
-      remoteAddress = tun.address;
-      remotePort = tun.port;
-      proxyPort = resp.result.proxyPort;
-      done();
-    });
-  }
-
-  async.until(established, openTunnel, function(err) {
-    if (err) {
-      return callback(
-        new Error('Failed to establish tunnel, reason: ' + err.message)
-      );
-    }
-
-    var tunnelWasOpened = false;
-    var tunnelDidError = false;
-    var localAddress = self.transport._server.address();
-
-    if (!localAddress) {
-      return callback(new Error(
-        'Local transport not initialized, refusing to establish new tunnel'
-      ));
-    }
-
-    self._tunnelClient = new diglet.Tunnel({
-      localAddress: 'localhost',
-      localPort: localAddress.port,
-      remoteAddress: remoteAddress,
-      remotePort: proxyPort,
-      logger: self._logger
-    });
-
-    self._tunnelClient.once('established', () => {
-      self._logger.info('tunnel successfully established');
-
-      tunnelWasOpened = true;
-      self.contact.address = remoteAddress;
-      self.contact.port = remotePort;
-
-      callback();
-    });
-
-    self._tunnelClient.on('error', function onTunnelError(err) {
-      /* istanbul ignore else */
-      if (!tunnelDidError) {
-        tunnelDidError = true;
-
-        self._logger.warn(
-          'tunnel connection lost, reason: %s',
-          err.message
-        );
-        self._establishTunnel(tunnels, tunnelWasOpened ? utils.noop : callback);
-      } else {
-        self._logger.debug(
-          'stale tunnel client encountered an error: %s, ignoring',
-          err.message
-        );
-      }
-    });
-
-    self._tunnelClient.open();
-  });
-};
-
-/**
- * Cleans invalid contacts from routing table
- * @private
- */
-Network.prototype._cleanRoutingTable = function() {
-  var dropped = [];
-
-  for (var k in this.router._buckets) {
-    var bucket = this.router._buckets[k];
-    var bucketList = bucket.getContactList();
-
-    for (var i = 0; i < bucketList.length; i++) {
-      var isValidContact = utils.isValidContact(
-        bucketList[i],
-        process.env.STORJ_ALLOW_LOOPBACK
-      );
-      var isValidProtocol = utils.isCompatibleVersion(bucketList[i].protocol);
-
-      if (!isValidContact || !isValidProtocol) {
-        dropped.push(bucketList[i]);
-        bucket.removeContact(bucketList[i]);
-      }
-    }
-  }
-
-  return dropped;
-};
-
-/**
- * Cleans the routing table on an interval
- * @private
- */
-Network.prototype._startRouterCleaner = function() {
-  var self = this;
-
-  setInterval(function() {
-    self._logger.debug('cleaning bad contacts from routing table');
-    var dropped = self._cleanRoutingTable();
-    self._logger.debug('dropping %s bad contacts from router', dropped.length);
-  }, constants.ROUTER_CLEAN_INTERVAL);
-};
-
-/**
- * Warns the user if their clock is not synchronized with NTP server
- * @private
- */
-Network.prototype._warnIfClockNotSynced = function(callback) {
-  var self = this;
-
-  utils.ensureNtpClockIsSynchronized(function(err, delta) {
-    if (err) {
-      self._logger.warn(err.message);
-    } else {
-      self._logger.info('clock is synchronized with ntp, delta: %s ms', delta);
-    }
-
-    callback(null);
-  });
-};
-
-module.exports = Network;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_network_monitor.js.html b/Storj/core/docs/lib_network_monitor.js.html deleted file mode 100644 index 926d469..0000000 --- a/Storj/core/docs/lib_network_monitor.js.html +++ /dev/null @@ -1,285 +0,0 @@ - - - - - JSDoc: Source: lib/network/monitor.js - - - - - - - - - - -
- -

Source: lib/network/monitor.js

- - - - - - -
-
-
'use strict';
-
-var Network = require('./index');
-var EventEmitter = require('events').EventEmitter;
-var inherits = require('util').inherits;
-var assert = require('assert');
-var merge = require('merge');
-var async = require('async');
-var request = require('request');
-
-/**
- * Wraps a {@link Network} instance and provides events for gathering
- * statistics about node operation
- * @constructor
- * @license AGPL-3.0
- * @param {Network} network - The network interface to monitor
- * @param {Object} options
- */
-function Monitor(network, options) {
-  if (!(this instanceof Monitor)) {
-    return new Monitor(network, options);
-  }
-
-  assert(network instanceof Network, 'Invalid network instance supplied');
-
-  this._source = network;
-  this._options = merge(Object.create(Monitor.DEFAULTS), options);
-  this._statistics = {};
-  this._collectors = {
-    soft: [
-      Monitor.getConnectedPeers,
-      Monitor.getDiskUtilization
-    ],
-    hard: [
-      Monitor.getPaymentAddressBalances
-    ]
-  };
-
-  EventEmitter.call(this);
-}
-
-inherits(Monitor, EventEmitter);
-
-/**
- * Triggered when a valid offer is received, but we are not waiting for one
- * @event Monitor#update
- * @param {Object} stats
- */
-
-Monitor.DEFAULTS = {
-  softInterval: 10000, // NB: Interval for simple jobs
-  hardInterval: 3 * 60 * 1000 // NB: Interval for resource heavy jobs
-};
-
-/**
- * Starts the network monitor
- * @returns {Monitor}
- */
-Monitor.prototype.start = function() {
-  if (this._softInterval && this._hardInterval) {
-    return false;
-  }
-
-  this._softInterval = setInterval(
-    this._collectSoftStats.bind(this),
-    this._options.softInterval
-  );
-
-  this._hardInterval = setInterval(
-    this._collectHardStats.bind(this),
-    this._options.hardInterval
-  );
-
-  return true;
-};
-
-/**
- * Stops the network monitor
- * @returns {Monitor}
- */
-Monitor.prototype.stop = function() {
-  if (!this._softInterval && !this._hardInterval) {
-    return false;
-  }
-
-  clearInterval(this._softInterval);
-  clearInterval(this._hardInterval);
-
-  delete this._softInterval;
-  delete this._hardInterval;
-
-  return true;
-};
-
-/**
- * Returns the current snapshot
- * @returns {Object} snapshot
- */
-Monitor.prototype.getSnapshot = function() {
-  return merge(Object.create(this._statistics), {
-    timestamp: new Date()
-  });
-};
-
-/**
- * Collects the soft stats
- * @private
- */
-Monitor.prototype._collectStats = function(collectors) {
-  var self = this;
-
-  async.parallel(collectors.map(function(collector) {
-    return collector.bind(null, self._source);
-  }), function(err, results) {
-    results.forEach(function(result) {
-      self._statistics = merge(self._statistics, result);
-    });
-    self.emit('update', self.getSnapshot());
-  });
-};
-
-/**
- * Collects the soft stats
- * @private
- */
-Monitor.prototype._collectSoftStats = function() {
-  this._collectStats(this._collectors.soft);
-};
-
-/**
- * Collects the hard stats
- * @private
- */
-Monitor.prototype._collectHardStats = function() {
-  this._collectStats(this._collectors.hard);
-};
-
-/**
- * Gets the list of currently known {@link Contact}s
- * @static
- * @param {Network} source - The network instance to use
- * @param {Function} callback
- */
-Monitor.getConnectedPeers = function(source, callback) {
-  var stats = { connected: 0 };
-  var buckets = source.router._buckets;
-
-  for (var k in buckets) {
-    stats.connected += buckets[k].getSize();
-  }
-
-  callback(null, { peers: stats });
-};
-
-/**
- * Gets the amount of used space compared to amount shared
- * @static
- * @param {Network} source - The network instance to use
- * @param {Function} callback
- */
-Monitor.getDiskUtilization = function(source, callback) {
-  var stats = { free: source.storageManager._options.maxCapacity };
-
-  source.storageManager._storage.size(function(err, bytes) {
-    if (err) {
-      return callback(null, {
-        disk: merge(stats, { used: 0, free: stats.free })
-      });
-    }
-
-    callback(null, {
-      disk: merge(stats, { used: bytes, free: stats.free - bytes })
-    });
-  });
-};
-
-/**
- * Gets the balance of SJCX/SJCT from a {@link FarmerInterface}
- * @static
- * @param {Network} source - The network instance to use
- * @param {Function} callback
- */
-Monitor.getPaymentAddressBalances = function(source, callback) {
-  var stats = { balances: { sjcx: 0, sjct: 0 } };
-  var address = source.keyPair.getAddress();
-
-  if (source._options.paymentAddress) {
-    address = source._options.paymentAddress.trim();
-  }
-
-  var url = 'https://counterpartychain.io/api/balances/' + address;
-
-  request({ url: url, json: true }, function(err, res, body) {
-    if (err || res.statusCode !== 200) {
-      return callback(null, { payments: stats });
-    }
-
-    if (body && body.data) {
-      for (var balance = 0; balance < body.data.length; balance++) {
-        stats.balances[body.data[balance].asset.toLowerCase()] = Number(
-          body.data[balance].amount
-        );
-      }
-    }
-
-    callback(null, { payments: stats });
-  });
-};
-
-/**
- * Gets the total contracts stored
- * @static
- * @param {Network} source - The network instance to use
- * @param {Function} callback
- */
-Monitor.getContractsDetails = function(source, callback) {
-  var stats = { total: 0 };
-  var stream = source.storageManager._storage.createReadStream();
-
-  stream.on('data', function(item) {
-    stats.total += Object.keys(item.contracts).length;
-  });
-
-  stream.on('end', function() {
-    callback(null, { contracts: stats });
-  });
-
-  stream.on('error', function() {
-    stream.removeAllListeners();
-    callback(null, { contracts: stats });
-  });
-};
-
-module.exports = Monitor;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_network_protocol.js.html b/Storj/core/docs/lib_network_protocol.js.html deleted file mode 100644 index 82d4696..0000000 --- a/Storj/core/docs/lib_network_protocol.js.html +++ /dev/null @@ -1,758 +0,0 @@ - - - - - JSDoc: Source: lib/network/protocol.js - - - - - - - - - - -
- -

Source: lib/network/protocol.js

- - - - - - -
-
-
'use strict';
-
-var through = require('through');
-var crypto = require('crypto');
-var assert = require('assert');
-var utils = require('../utils');
-var ProofStream = require('../audit-tools/proof-stream');
-var Contract = require('../contract');
-var stream = require('readable-stream');
-var kad = require('kad');
-var async = require('async');
-var Contact =  require('./contact');
-var constants = require('../constants');
-var ExchangeReport = require('../bridge-client/exchange-report');
-
-/**
- * Defines the Storj protocol methods and mounts on a {@link Network} instance
- * to handle Storj protocol messages
- * @constructor
- * @license AGPL-3.0
- * @param {Object} options
- * @param {Network} options.network - Network instance to bind to
- */
-function Protocol(opts) {
-  if (!(this instanceof Protocol)) {
-    return new Protocol(opts);
-  }
-
-  assert(typeof opts === 'object' , 'Invalid options supplied');
-
-  this._network = opts.network;
-  this._logger = this._network._logger;
-}
-
-Protocol.RENEW_PROPS_ALLOWED = [
-  'renter_id',
-  'renter_hd_key',
-  'renter_hd_index',
-  'renter_signature',
-  'store_begin',
-  'store_end'
-];
-
-/**
- * Handles OFFER messages
- * @param {Object} params
- * @param {Contact} params.contact - Sender contact information
- * @param {Contract} params.contract - Serialized contract data
- * @param {Protocol~handleOfferCallback} callback
- * @fires Network#unhandledOffer
- * @fires Network#unhandledOfferResolved
- */
-Protocol.prototype.handleOffer = function(params, callback) {
-  var self = this;
-  var contract = null;
-
-  try {
-    contract = Contract.fromObject(params.contract);
-  } catch (err) {
-    return callback(new Error('Invalid contract format'));
-  }
-
-  self._logger.info(
-    'handling storage contract offer from %s hash %s',
-    params.contact.nodeID,
-    contract.get('data_hash')
-  );
-
-  var key = contract.get('data_hash');
-  var offerStream = self._network.offerManager.getStream(key);
-
-  this._verifyContract(contract, params.contact, function(err) {
-    if (err) {
-      return callback(err);
-    }
-
-    if (offerStream) {
-      // NB: We are waiting on/accepting offers for this contract,
-      // NB: so add it to the offer queue
-      offerStream.addOfferToQueue(Contact(params.contact), contract);
-    } else {
-      // NB: We are not waiting on/accepting offers for this contract,
-      // NB: so notify implementors
-      self._network.emit(
-        'unhandledOfferResolved',
-        Contact(params.contact),
-        contract
-      );
-    }
-
-    callback(null, { contract: contract.toObject() });
-  });
-};
-/**
- * @callback Protocol~handleOfferCallback
- * @param {Error|null} err
- * @param {Object} result
- * @param {Contract} result.contract - Signed contract
- */
-
-/**
- * Verifies that the contract is valid
- * @private
- */
-Protocol.prototype._verifyContract = function(contract, contact, callback) {
-  contract.sign('renter', this._network.keyPair.getPrivateKey());
-
-  if (!contract.isComplete()) {
-    return callback(new Error('Contract is not complete'));
-  }
-
-  if (!contract.verify('farmer', contact.nodeID)) {
-    return callback(new Error('Invalid signature from farmer'));
-  }
-
-  var offerStream = this._network.offerManager.getStream(
-    contract.get('data_hash')
-  );
-
-  if (!offerStream) {
-    if (!this._network.listenerCount('unhandledOffer')) {
-      return callback(new Error('Contract no longer open to offers'));
-    }
-
-    return this._network.emit('unhandledOffer', contact, contract, callback);
-  }
-
-  var blacklist = offerStream.options.farmerBlacklist;
-
-  if (blacklist.indexOf(contact.nodeID) !== -1) {
-    return callback(new Error('Contract no longer open to offers'));
-  }
-
-  callback(null);
-};
-/**
- * @callback Protocol~unhandledOfferResolver
- * @param {Error} [error] - An error if the offer cannot be resolved
- */
-
-/**
- * Handles AUDIT messages
- * @param {Object} params
- * @param {Contact} params.contact - Sender contact information
- * @param {Object[]} params.audits
- * @param {String} params.audits.data_hash - Shard data hash to audit
- * @param {String} params.audits.challenge - Challenge string for audit
- * @param {Protocol~handleAuditCallback} callback
- */
-Protocol.prototype.handleAudit = function(params, callback) {
-  var self = this;
-  var limit = constants.MAX_CONCURRENT_AUDITS;
-
-  if (!Array.isArray(params.audits)) {
-    return callback(new Error('Invalid audit list supplied'));
-  }
-
-  this._logger.info(
-    'handling storage audit from %s', params.contact.nodeID
-  );
-
-  async.mapLimit(params.audits, limit, function(audit, done) {
-    self._proveShardExistence(
-      audit.data_hash,
-      audit.challenge,
-      params.contact.nodeID,
-      done
-    );
-  }, function onComplete(err, proofs) {
-    if (err) {
-      return callback(err);
-    }
-
-    callback(null, { proofs: proofs });
-  });
-};
-/**
- * @callback Protocol~handleAuditCallback
- * @param {Error|null} err
- * @param {Object} result
- * @param {Array[]} result.proofs - Mapped list of proof responses
- */
-
-/**
- * Performs a single audit proof generation
- * @private
- * @param {String} hash - The hash of the shard to prove
- * @param {String} challenge - The challenge input for proof generation
- * @param {String} nodeID - The nodeID of the auditor
- * @param {Function} callback - Called on completion of the proof generation
- */
-Protocol.prototype._proveShardExistence = function(hash, chall, nid, cb) {
-  if (!hash || !chall) {
-    return cb(new Error('Invalid data hash or challenge provided'));
-  }
-
-  this._network.storageManager.load(hash, function(err, item) {
-    if (err) {
-      return cb(err);
-    }
-
-    if (item.shard instanceof stream.Writable) {
-      return cb(new Error('Shard not found'));
-    }
-
-    var proof = new ProofStream(item.trees[nid], chall);
-
-    proof.on('error', function(err) {
-      proof.removeAllListeners('finish');
-      cb(err);
-    });
-
-    proof.on('finish', function() {
-      proof.removeAllListeners('error');
-      cb(null, proof.getProofResult());
-    });
-
-    item.shard.pipe(proof);
-  });
-};
-
-/**
- * Handles CONSIGN messages
- * @param {Object} params
- * @param {Contact} params.contact - Sender contact information
- * @param {String} params.data_hash - Shard data hash (contract key)
- * @param {String[]} params.audit_tree - Bottom leaves of audit merkle tree
- * @param {Protocol~handleConsignCallback} callback
- */
-Protocol.prototype.handleConsign = function(params, callback) {
-  var self = this;
-  var token = utils.generateToken();
-
-  self._logger.info(
-    'handling storage consignment request from %s hash %s',
-    params.contact.nodeID,
-    params.data_hash
-  );
-
-  self._network.storageManager.load(params.data_hash, function(err, item) {
-    if (err) {
-      return callback(err);
-    }
-
-    var contract = item.getContract(params.contact);
-    var t = Date.now();
-
-    if (!contract) {
-      return callback(new Error('Consignment is not authorized'));
-    }
-
-    item.trees[contract.get('renter_id')] = params.audit_tree;
-
-    try {
-      assert(
-        t < contract.get('store_end') &&
-        t + constants.CONSIGN_THRESHOLD > contract.get('store_begin'),
-        'Consignment violates contract store time'
-      );
-    } catch (err) {
-      return callback(err);
-    }
-
-    self._network.storageManager.save(item, function(err) {
-      if (err) {
-        return callback(err);
-      }
-
-      self._logger.info(
-        'authorizing upload data channel for %s', params.contact.nodeID
-      );
-
-      self._network.transport.shardServer.accept(
-        token,
-         params.data_hash,
-         params.contact
-       );
-      callback(null, { token: token });
-    });
-  });
-};
-/**
- * @callback Protocol~handleConsignCallback
- * @param {Error|null} err
- * @param {Object} result
- * @param {String} result.token - Data channel authorization token
- */
-
-/**
- * Handles MIRROR messages
- * @param {Object} params
- * @param {Contact} params.contact - Sender contact information
- * @param {String} params.data_hash - Shard hash to mirror
- * @param {String} params.token - Data channel authorization token
- * @param {Contact} params.farmer - The farmer to transfer data from
- * @param {Protocol~handleMirrorCallback} callback
- */
-Protocol.prototype.handleMirror = function(params, callback) {
-  /* eslint max-statements: [2, 16] */
-  const self = this;
-  const {data_hash: hash, token} = params;
-  const bridgeClient = this._network.bridgeClient;
-
-  self._logger.info(
-    'handling mirror request from %s hash %s', params.contact.nodeID, hash
-  );
-
-  self._network.storageManager.load(hash, function(err, item) {
-    if (err) {
-      return callback(err);
-    }
-
-    // NB: Don't mirror data we are not contracted for
-    if (!item.getContract(params.contact)) {
-      return callback(new Error('No contract found for shard'));
-    }
-
-    // NB: Don't mirror if we already have the shard
-    if (typeof item.shard.write !== 'function') {
-      return callback(null, {});
-    }
-
-    self._logger.info(
-      'opening data transfer with %j to mirror %s',
-      params.farmer,
-      hash
-    );
-
-    const hasher256 = crypto.createHash('sha256');
-    const report = new ExchangeReport({
-      reporterId: self._network.contact.nodeID,
-      farmerId: params.farmer.nodeID
-    });
-    const downloader = utils.createShardDownloader(
-      new Contact(params.farmer),
-      hash,
-      token
-    );
-    const hash256updater = through(function(data) {
-      hasher256.update(data);
-      this.queue(data);
-    });
-
-    function _onFinish() {
-      if (item.hash !== utils.rmd160(hasher256.digest())) {
-        self._logger.warn('mirror read integrity check failed, destroying');
-        report.end(ExchangeReport.FAILURE, 'FAILED_INTEGRITY');
-        item.shard.destroy(utils.warnOnError(self._logger));
-      } else {
-        self._logger.info('successfully mirrored shard hash %s', item.hash);
-        report.end(ExchangeReport.SUCCESS, 'MIRROR_SUCCESS');
-      }
-      bridgeClient.createExchangeReport(report);
-    }
-
-    report.begin(hash);
-    downloader.on('error', function _onStreamError(err) {
-      self._logger.error('failed to read from mirror node: %s', err.message);
-      item.shard.destroy(utils.warnOnError(self._logger));
-      report.end(ExchangeReport.FAILURE, 'MIRROR_FAILED');
-      bridgeClient.createExchangeReport(report);
-    }).pipe(hash256updater).pipe(item.shard).on('finish', _onFinish);
-    callback(null, {});
-  });
-};
-/**
- * @callback Protocol~handleMirrorCallback
- * @param {Error|null} err
- * @param {Object} result - Empty acknowledgement
- */
-
-/**
- * Handles RETRIEVE messages
- * @param {Object} params
- * @param {Contact} params.contact - Sender contact information
- * @param {String} params.data_hash - RMD160(SHA256(shard_data))
- * @param {Protocol~handleRetrieveCallback} callback
- */
-Protocol.prototype.handleRetrieve = function(params, callback) {
-  var self = this;
-  var hash = params.data_hash;
-  var token = utils.generateToken();
-
-  if (!kad.utils.isValidKey(hash)) {
-    return callback(new Error('Invalid data hash provided: ' + hash));
-  }
-
-  self._logger.info(
-    'handling storage retrieve request from %s hash %s',
-    params.contact.nodeID,
-    hash
-  );
-
-  self._network.storageManager.load(hash, function(err, item) {
-    if (err) {
-      return callback(err);
-    }
-
-    if (!item.getContract(params.contact)) {
-      return callback(new Error('Retrieval is not authorized'));
-    }
-
-    if (typeof item.shard.write === 'function') {
-      return callback(new Error('Shard data not found'));
-    }
-
-    // TODO: We will need to increment the download count to track payments
-
-    self._logger.info(
-      'authorizing download data channel for %s', params.contact.nodeID
-    );
-
-    self._network.transport.shardServer.accept(
-      token,
-      item.hash,
-      params.contact
-    );
-    callback(null, { token: token });
-  });
-};
-/**
- * @callback Protocol~handleRetrieveCallback
- * @param {Error|null} err
- * @param {Object} result
- * @param {String} result.token - Authorization token for data channel
- */
-
-/**
- * Handles PROBE messages
- * @param {Object} params
- * @param {Contact} params.contact - Sender contact information
- * @param {Protocol~handleProbeCallback} callback
- */
-Protocol.prototype.handleProbe = function(params, callback) {
-  var message = new kad.Message({
-    method: 'PING',
-    params: { contact: this._network.contact }
-  });
-
-  this._logger.info('performing probe for %s', params.contact.nodeID);
-  this._network.transport.send(params.contact, message, function(err) {
-    if (err) {
-      return callback(new Error('Probe failed, you are not addressable'));
-    }
-
-    callback(null, {});
-  });
-};
-/**
- * @callback Protocol~handleProbeCallback
- * @param {Error|null} err
- * @param {Object} result - Empty acknowledgement
- */
-
-/**
- * Handles FIND_TUNNEL messages
- * @param {Object} params
- * @param {Contact} params.contact - Sender contact information
- * @param {Contact[]} params.relayers - List of contacts who have already
- * relayed the FIND_TUNNEL request
- * @param {Protocol~handleFindTunnelCallback} callback
- */
-Protocol.prototype.handleFindTunnel = function(params, callback) {
-  var tunServer = this._network.transport.tunnelServer;
-  var numProxies = Object.keys(tunServer._proxies).length;
-  var available = numProxies < tunServer._opts.maxProxiesAllowed;
-  var knownTunnelers = this._network._tunnelers.getContactList();
-  var tunnels = available ?
-                [this._network.contact].concat(knownTunnelers) :
-                knownTunnelers;
-
-  this._logger.info('finding tunnels for %s', params.contact.nodeID);
-
-  if (tunnels.length) {
-    this._logger.info(
-      'sending %s tunnels to %s', tunnels.length, params.contact.nodeID
-    );
-    return callback(null, { tunnels: tunnels });
-  }
-
-  if (params.relayers.length < constants.MAX_FIND_TUNNEL_RELAYS) {
-    return this._askNeighborsForTunnels(params.relayers, callback);
-  }
-
-  callback(null, { tunnels: tunnels });
-};
-/**
- * @callback Protocol~handleFindTunnelCallback
- * @param {Error|null} err
- * @param {Object} result
- * @param {Contact[]} result.tunnels - List of known tunnelers
- */
-
-/**
- * Sends a FIND_TUNNEL to our seed on behalf of requester
- * @private
- */
-Protocol.prototype._askNeighborsForTunnels = function(relayers, callback) {
-  var self = this;
-  var nearestNeighbors = this._network.router.getNearestContacts(
-    this._network.contact.nodeID,
-    3,
-    this._network.contact.nodeID
-  ).filter(function(contact) {
-    return relayers.indexOf(contact.nodeID) === -1;
-  });
-
-  this._logger.info('asking nearest neighbors for known tunnels');
-
-  function askNeighbor(neighbor, done) {
-    self._network.transport.send(neighbor, kad.Message({
-      method: 'FIND_TUNNEL',
-      params: {
-        contact: self._network.contact,
-        relayers: [self._network.contact].concat(relayers)
-      }
-    }), function(err, response) {
-      if (err || !Array.isArray(response.result.tunnels)) {
-        return done(null, false);
-      }
-
-      if (response.result.tunnels && response.result.tunnels.length) {
-        response.result.tunnels.forEach(function(tun) {
-          if (self._network._tunnelers.getSize() < kad.constants.K) {
-            self._network._tunnelers.addContact(new Contact(tun));
-          }
-        });
-        return done(null, true);
-      }
-
-      done(null, false);
-    });
-  }
-
-  async.detectSeries(nearestNeighbors, askNeighbor, function() {
-    callback(null, { tunnels: self._network._tunnelers.getContactList() });
-  });
-};
-
-/**
- * Handles OPEN_TUNNEL messages
- * @param {Object} params
- * @param {Contact} params.contact - Sender contact information
- * @param {Protocol~handleOpenTunnelCallback} callback
- */
-Protocol.prototype.handleOpenTunnel = function(params, callback) {
-  var self = this;
-  var tunnelServer = this._network.transport.tunnelServer;
-
-  this._logger.info('opening gateway for %s', params.contact.nodeID);
-  tunnelServer.addProxy(params.contact.nodeID, function(err, proxy) {
-    if (err) {
-      return callback(err);
-    }
-
-    if (!self._network.transport._requiresTraversal) {
-      return callback(null, {
-        proxyPort: proxy.getProxyPort()
-      });
-    }
-
-    self._network.transport.createPortMapping(proxy.getProxyPort(), (err) => {
-      if (err) {
-        return callback(err);
-      }
-
-      callback(null, { proxyPort: proxy.getProxyPort() });
-    });
-  });
-};
-/**
- * @callback Protocol~handleOpenTunnelCallback
- * @param {Error|null} err
- * @param {Object} result
- * @param {String} result.tunnel - WebSocket URI including auth token
- * @param {Object} result.alias
- * @param {String} result.alias.address - Gateway address on the tunneler
- * @param {Number} result.alias.port - Gateway port on the tunneler
- */
-
-/**
- * Handles TRIGGER messages
- * @see https://github.com/Storj/sips/blob/master/sip-0003.md
- * @param {Object} params
- * @param {String} params.behavior - Trigger behavior name to process
- * @param {Object} params.contents - Trigger content payload
- * @param {Contact} params.contact - Sender contact information
- * @param {Protocol~handleTriggerCallback} callback
- */
-Protocol.prototype.handleTrigger = function(params, callback) {
-  this._network.triggers.process(params, callback);
-};
-/**
- * @callback Protocol~handleTriggerCallback
- * @param {Error|null} err
- * @param {Object} result - Arbitrary key-value pairs
- */
-
-/**
- * Handles RENEW messages
- * @see https://github.com/Storj/sips/blob/master/sip-0004.md
- * @param {Object} params
- * @param {Contact} params.contact - Sender contact information
- * @param {String} params.renter_id - Renter nodeID of the original contract
- * @param {String} params.renter_signature - Contract signature from original
- * node ID
- * @param {Object} params.contract - Updated contract data
- * @param {Protocol~handleRenewCallback} callback
- */
-Protocol.prototype.handleRenew = function(params, callback) {
-  var self = this;
-  var updatedContract = null;
-  var dataHash = null;
-
-  try {
-    assert.ok(params.renter_id, 'No original renter_id was supplied');
-    assert.ok(params.renter_signature, 'No original renter signature supplied');
-
-    updatedContract = Contract.fromObject(params.contract);
-    dataHash = updatedContract.get('data_hash');
-
-    self._logger.info('handling contract renew request from %s hash %s',
-      params.contact.nodeID,
-      dataHash
-    );
-
-    assert.ok(
-      updatedContract.verifyExternal(
-        params.renter_signature,
-        params.renter_id
-      ),
-      'Invalid original renter signature on updated contract'
-    );
-    assert.ok(
-      updatedContract.verify('renter', updatedContract.get('renter_id')),
-      'Invalid new renter signature on updated contract'
-    );
-  } catch (err) {
-    return callback(err);
-  }
-
-  this._network.storageManager.load(dataHash, function(err, item) {
-    if (err) {
-      return callback(err);
-    }
-
-    var originalContract = item.getContract(params.contact);
-
-    if (!originalContract) {
-      return callback(new Error('No contract found for renter_id'));
-    }
-
-    var changedProperties = Contract.diff(originalContract, updatedContract);
-
-    // TODO: Come back and consider how to handle attacks on store time
-    for (var i = 0; i < changedProperties.length; i++) {
-      if (Protocol.RENEW_PROPS_ALLOWED.indexOf(changedProperties[i]) === -1) {
-        self._logger.error('Renew contract failed: %s cannot be changed',
-          changedProperties[i]);
-        return callback(new Error(changedProperties[i] + ' cannot be changed'));
-      }
-    }
-
-    updatedContract.sign('farmer', self._network.keyPair.getPrivateKey());
-    item.removeContract(params.contact);
-    item.addContract({
-      nodeID: updatedContract.get('renter_id'),
-      hdKey: updatedContract.get('renter_hd_key'),
-      hdIndex: updatedContract.get('renter_hd_index')
-    }, updatedContract);
-
-    self._network.storageManager.save(item, function(err) {
-      if (err) {
-        return callback(new Error('Failed to save updated contract'));
-      }
-
-      callback(null, { contract: updatedContract.toObject() });
-    });
-  });
-};
-/**
- * @callback Protocol~handleRenewCallback
- * @param {Error|null} err
- * @param {Object} result
- * @param {Object} result.contract - Signed updated contract
- */
-
-/**
- * Returns bound references to the protocol handlers
- * @returns {Object} handlers
- */
-Protocol.prototype.getRouteMap = function() {
-  return {
-    OFFER: this.handleOffer.bind(this),
-    AUDIT: this.handleAudit.bind(this),
-    CONSIGN: this.handleConsign.bind(this),
-    MIRROR: this.handleMirror.bind(this),
-    RETRIEVE: this.handleRetrieve.bind(this),
-    PROBE: this.handleProbe.bind(this),
-    FIND_TUNNEL: this.handleFindTunnel.bind(this),
-    OPEN_TUNNEL: this.handleOpenTunnel.bind(this),
-    TRIGGER: this.handleTrigger.bind(this),
-    RENEW: this.handleRenew.bind(this)
-  };
-};
-
-module.exports = Protocol;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_network_renter.js.html b/Storj/core/docs/lib_network_renter.js.html deleted file mode 100644 index 687141a..0000000 --- a/Storj/core/docs/lib_network_renter.js.html +++ /dev/null @@ -1,356 +0,0 @@ - - - - - JSDoc: Source: lib/network/renter.js - - - - - - - - - - -
- -

Source: lib/network/renter.js

- - - - - - -
-
-
'use strict';
-
-var merge = require('merge');
-var assert = require('assert');
-var Contract = require('../contract');
-var Contact = require('./contact');
-var AuditStream = require('../audit-tools/audit-stream');
-var kad = require('kad');
-var Network = require('./');
-var inherits = require('util').inherits;
-var StorageItem = require('../storage/item');
-var async = require('async');
-var OfferStream = require('../contract/offer-stream');
-
-/**
- * Creates and a new renter interface
- * @constructor
- * @license AGPL-3.0
- * @extends {Network}
- * @param {Object}  options
- * @param {String} [options.hdKey] - Extended key at 'group index' as per SIP32
- * @param {Number} [options.hdIndex] - Derivation index for hdKey
- * @param {KeyPair}[options.keyPair] - Node's cryptographic identity
- * @param {StorageManager} options.storageManager - Storage manager backend
- * @param {String}  options.bridgeUri - URL for bridge server seed lookup
- * @param {Object}  options.logger - Logger instance
- * @param {Array}   options.seedList - List of seed URIs to join
- * @param {String}  options.rpcAddress - Public node IP or hostname
- * @param {Number}  options.rpcPort - Listening port for RPC
- * @param {Boolean} options.doNotTraverseNat - Skip NAT traversal strategies
- * @param {Number}  options.maxTunnels - Max number of tunnels to provide
- * @param {Number}  options.tunnelServerPort - Port for tunnel server to use
- * @param {Object}  options.tunnelGatewayRange
- * @param {Number}  options.tunnelGatewayRange.min - Min port for gateway bind
- * @param {Number}  options.tunnelGatewayRange.max - Max port for gateway bind
- * @param {Object}  options.rateLimiterOpts - Options for {@link RateLimiter}
- * @param {Object} [options.joinRetry]
- * @param {Number} [options.joinRetry.times] - Times to retry joining net
- * @param {Number} [options.joinRetry.interval] - MS to wait before retrying
- * @emits Network#ready
- * @property {KeyPair} keyPair
- * @property {StorageManager} storageManager
- * @property {kad.Node} node - The underlying DHT node
- * @property {TriggerManager} triggerManager
- * @property {BridgeClient} bridgeClient
- * @property {Contact} contact
- * @property {Transport} transportAdapter
- * @property {kad.Router} router - The underlying DHT router
- * @property {DataChannelServer} dataChannelServer
- */
-function RenterInterface(options) {
-  if (!(this instanceof RenterInterface)) {
-    return new RenterInterface(options);
-  }
-
-  Network.call(this, options);
-}
-
-inherits(RenterInterface, Network);
-
-/**
- * Creates a readable stream of offers for the storage contract
- * @param {Contract} contract - The storage contract to publish
- * @param {Object} [offerStreamOptions] - Options passed to {@link OfferStream}
- * @returns {OfferStream} offerStream
- */
-RenterInterface.prototype.getOfferStream = function(contract, options) {
-  assert(contract instanceof Contract, 'Invalid contract supplied');
-
-  var hash = contract.get('data_hash');
-  var offerStream = new OfferStream(contract, options);
-  var content = merge(contract.toObject(), { contact: this.contact });
-
-  this.offerManager.addStream(offerStream);
-  this.publish(contract.getTopicString(), content, { key: hash });
-
-  return offerStream;
-};
-
-/**
- * Issues an audit request to the given farmer for the data and returns the
- * {@link ProofStream#getProofResult} structure for verification.
- * @param {Contact} farmer - Farmer contact from which proof is needed
- * @param {StorageItem} item - The storage item on which to perform the audit
- * @param {RenterInterface~getStorageProofCallback} callback - Proof handler
- */
-RenterInterface.prototype.getStorageProof = function(farmer, item, callback) {
-  assert(farmer instanceof Contact, 'Invalid contact supplied');
-  assert(item instanceof StorageItem, 'Invalid storage item supplied');
-
-  if (!item.challenges[farmer.nodeID]) {
-    return callback(new Error('Item has no contracts with supplied farmer'));
-  }
-
-  if (!item.challenges[farmer.nodeID].challenges.length) {
-    return callback(new Error('There are no remaining challenges to send'));
-  }
-
-  var message = new kad.Message({
-    method: 'AUDIT',
-    params: {
-      audits: [
-        {
-          data_hash: item.hash,
-          challenge: item.challenges[farmer.nodeID].challenges.shift()
-        }
-      ],
-      contact: this.contact
-    }
-  });
-
-  this.transport.send(farmer, message, function(err, response) {
-    if (err) {
-      return callback(err);
-    }
-
-    if (response.error) {
-      return callback(new Error(response.error.message));
-    }
-
-    if (!Array.isArray(response.result.proofs)) {
-      return callback(new Error('Invalid proof returned'));
-    }
-
-    callback(null, response.result.proofs[0]);
-  });
-};
-/**
- * This callback is called upon receipt of an audit proof from
- * {@link RenterInterface#getStorageProof}
- * @callback RenterInterface~getStorageProofCallback
- * @param {Error|null} err - If requesting the proof failed, an error object
- * @param {Array} proof - Result from {@link ProofStream#getProofResult}
- */
-
-/**
- * Requests a consignment pointer from the given farmer for opening a
- * {@link DataChannelClient} for transferring the the data shard to the farmer
- * @param {Contact} farmer - The farmer contact object for requesting token
- * @param {Contract} contract - The storage contract for this consignment
- * @param {AuditStream} audit - The audit object for merkle leaves
- * @param {RenterInterface~getConsignmentPointerCallback} callback
- */
-RenterInterface.prototype.getConsignmentPointer = function(f, c, a, callback) {
-  var farmer = f;
-  var contract = c;
-  var audit = a;
-
-  assert(farmer instanceof Contact, 'Invalid farmer contact supplied');
-  assert(contract instanceof Contract, 'Invalid contract supplied');
-  assert(audit instanceof AuditStream, 'Invalid audit object supplied');
-
-  var message = new kad.Message({
-    method: 'CONSIGN',
-    params: {
-      data_hash: contract.get('data_hash'),
-      audit_tree: audit.getPublicRecord(),
-      contact: this.contact
-    }
-  });
-
-  this.transport.send(farmer, message, function(err, response) {
-    if (err) {
-      return callback(err);
-    }
-
-    if (response.error) {
-      return callback(new Error(response.error.message));
-    }
-
-    callback(null, {
-      farmer: f,
-      hash: contract.get('data_hash'),
-      token: response.result.token,
-      operation: 'PUSH'
-    });
-  });
-};
-/**
- * This callback is called upon receipt of a consignment token from
- * {@link RenterInterface#getConsignmentPointer}
- * @callback RenterInterface~getConsignmentPointerCallback
- * @param {Error|null} err - If requesting the token failed, an error object
- * @param {Object} pointer
- * @param {Contact} pointer.farmer
- * @param {String} pointer.hash
- * @param {String} pointer.token
- * @param {String} pointer.operation
- */
-
-/**
- * Requests a retrieval token from the given farmer for opening a
- * {@link DataChannelClient} for transferring the data shard from the farmer
- * @param {Contact} farmer - The farmer contact object for requesting token
- * @param {Contract} contract - The storage contract for this consignment
- * @param {RenterInterface~getRetrievalPointerCallback} callback - Token handler
- */
-RenterInterface.prototype.getRetrievalPointer = function(f, c, callback) {
-  var farmer = f;
-  var contract = c;
-
-  assert(farmer instanceof Contact, 'Invalid farmer contact supplied');
-  assert(contract instanceof Contract, 'Invalid contract supplied');
-
-  var message = new kad.Message({
-    method: 'RETRIEVE',
-    params: {
-      data_hash: contract.get('data_hash'),
-      contact: this.contact
-    }
-  });
-
-  this.transport.send(farmer, message, function(err, response) {
-    if (err) {
-      return callback(err);
-    }
-
-    if (response.error) {
-      return callback(new Error(response.error.message));
-    }
-
-    callback(null, {
-      farmer: f,
-      hash: contract.get('data_hash'),
-      token: response.result.token,
-      operation: 'PULL'
-    });
-  });
-};
-/**
- * This callback is called upon receipt of a retrieval token from
- * {@link RenterInterface#getRetrieveToken}
- * @callback RenterInterface~getRetrievalPointerCallback
- * @param {Error|null} err - If requesting the token failed, an error object
- * @param {Object} pointer
- * @param {Contact} pointer.farmer
- * @param {String} pointer.hash
- * @param {String} pointer.token
- * @param {String} pointer.operation
- */
-
-/**
- * Requests that the given destination farmers mirror the data from the sources
- * @param {Array.<Object>} sources - Pointers for each destination
- * @param {Array.<Contact>} destinations - The farmers to replicate to
- * @param {RenterInterface~getMirrorNodesCallback} callback - Results handler
- */
-RenterInterface.prototype.getMirrorNodes = function(sources, dests, callback) {
-  var self = this;
-
-  assert(Array.isArray(sources), 'Invalid sources list supplied');
-  assert(Array.isArray(dests), 'Invalid destination list supplied');
-  assert(
-    sources.length === dests.length,
-    'Sources and destinations must have equal length'
-  );
-
-  dests.forEach(function(dest) {
-    assert(dest instanceof Contact, 'Invalid destination supplied');
-  });
-
-  function _sendMirrorRequest(destination, next) {
-    var source = sources.shift();
-    var message = new kad.Message({
-      method: 'MIRROR',
-      params: {
-        data_hash: source.hash,
-        token: source.token,
-        farmer: source.farmer,
-        contact: self.contact
-      }
-    });
-
-    self.transport.send(destination, message, function(err, response) {
-      if (err || !response || response.error) {
-        return next(null, false);
-      }
-      next(null, true);
-    });
-  }
-
-  function _onMirrorRequestsComplete(err, results) {
-    // Error is never passed in the filter, as the test is for an error
-    // we can keep the error check here anyways, if the code changes.
-    /* istanbul ignore next */
-    if (err) {
-      return callback(err);
-    }
-    if (results.length === 0) {
-      return callback(new Error('All mirror requests failed'));
-    }
-
-    callback(null, results);
-  }
-
-  async.filter(dests, _sendMirrorRequest, _onMirrorRequestsComplete);
-};
-/**
- * This callback is called upon acknowledgement of a mirror request
- * @callback RenterInterface~getMirrorNodesCallback
- * @param {Error|null} err - If requesting all mirrors failed, an error object
- * @param {Array.<Contact>} results - The farmers who successfully mirrored
- */
-
-module.exports = RenterInterface;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_network_shard-server.js.html b/Storj/core/docs/lib_network_shard-server.js.html deleted file mode 100644 index 9cb70e6..0000000 --- a/Storj/core/docs/lib_network_shard-server.js.html +++ /dev/null @@ -1,346 +0,0 @@ - - - - - JSDoc: Source: lib/network/shard-server.js - - - - - - - - - - -
- -

Source: lib/network/shard-server.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var StorageManager = require('../storage/manager');
-var events = require('events');
-var inherits = require('util').inherits;
-var crypto = require('crypto');
-var utils = require('../utils');
-var constants = require('../constants');
-var BridgeClient = require('../bridge-client');
-var ExchangeReport = require('../bridge-client/exchange-report');
-
-/**
- * Creates a shard server for sending and receiving consigned file shards
- * @constructor
- * @license AGPL-3.0
- * @param {Object} options
- * @param {String} options.nodeID - The farmer nodeID
- * @param {StorageManager} options.storageManager - Storage manager backend
- * @param {kad.Logger} options.logger - Logger to use from {@link Network}
- * @param {Number} [options.tokenTtl=1800000] - Close after idle
- */
-function ShardServer(options) {
-  if (!(this instanceof ShardServer)) {
-    return new ShardServer(options);
-  }
-
-  this._checkOptions(options);
-  events.EventEmitter.call(this);
-
-  this.activeTransfers = 0;
-  this._nodeID = options.nodeID;
-  this._bridgeClient = options.bridgeClient || new BridgeClient();
-  this._manager = options.storageManager;
-  this._log = options.logger;
-  this._ttl = options.tokenTtl || constants.TOKEN_EXPIRE;
-  this._allowed = {};
-
-  setInterval(this._reapDeadTokens.bind(this), this._ttl);
-}
-
-/**
- * Triggered when a shard has finished uploading to this instance
- * @event ShardServer#shardUploaded
- * @param {StorageItem} item - The item associated with the upload
- */
-
-/**
- * Triggered when a shard has finished downloading from this instance
- * @event ShardServer#shardDownloaded
- * @param {StorageItem} item - The item associated with the download
- */
-
-/**
- * Triggered when a error occurs
- * @event ShardServer#error
- * @param {Error} error - The error object
- */
-
-inherits(ShardServer, events.EventEmitter);
-
-/**
- * Begin accepting data for the given file hash and token
- * @param {String} token - The authorization token created for transfer
- * @param {String} filehash - The shard hash to allow for the token
- * @param {Contact} contact - contact that negotiated the token
- */
-ShardServer.prototype.accept = function(token, filehash, contact) {
-  assert(typeof token === 'string', 'Invalid token supplied');
-  assert(typeof filehash === 'string', 'Invalid filehash supplied');
-
-  this._allowed[token] = {
-    hash: filehash,
-    contact: contact,
-    expires: Date.now() + this._ttl,
-    report: new ExchangeReport({
-      reporterId: this._nodeID,
-      farmerId: this._nodeID
-    })
-  };
-};
-
-/**
- * Stop accepting data for the given token
- * @param {String} token - The authorization token created for transfer
- */
-ShardServer.prototype.reject = function(token) {
-  assert(typeof token === 'string', 'Invalid token supplied');
-  delete this._allowed[token];
-};
-
-/**
- * Checks the options supplied to constructor
- * @private
- */
-ShardServer.prototype._checkOptions = function(options) {
-  assert.ok(options, 'No options were supplied to constructor');
-  assert(
-    options.storageManager instanceof StorageManager,
-    'Invalid manager supplied'
-  );
-  assert.ok(options.logger, 'Invalid logger supplied');
-  assert.ok(options.nodeID, 'Invalid nodeID supplied');
-};
-
-/**
- * Validates the given token
- * @param {String} token
- * @param {String} hash
- */
-ShardServer.prototype.isAuthorized = function(token, hash) {
-  var self = this;
-
-  try {
-    assert.ok(token, 'You did not supply a token');
-    assert.ok(self._allowed[token], 'The supplied token is not accepted');
-    assert.ok(hash, 'You did not supply the data hash');
-    assert(self._allowed[token].expires > Date.now(), 'Token has expired');
-    assert(self._allowed[token].hash === hash, 'Token not valid for hash');
-  } catch (err) {
-    return [false, err];
-  }
-
-  return [true, null];
-};
-
-/**
- * Decrements the active transfer count on early socket close
- * @private
- */
-ShardServer.prototype._handleEarlySocketClose = function() {
-  this._log.warn('channel terminated early (possibly by client)');
-  this.activeTransfers--;
-};
-
-/**
- * Decrements the active transfer count on request error
- * @private
- */
-ShardServer.prototype._handleRequestError = function(err) {
-  this._log.warn('channel encountered an error: %s', err.message);
-  this.activeTransfers--;
-};
-
-/**
- * Receives the data stream and writes it to storage
- * @param {http.IncomingMessage} req
- * @param {http.ServerResponse} req
- */
-ShardServer.prototype.routeConsignment = function(req, res) {
-  const self = this;
-  const hasher = crypto.createHash('sha256');
-  const [isAuthed, authError] = this.isAuthorized(
-    req.query.token,
-    req.params.hash
-  );
-
-  if (!isAuthed) {
-    return res.send(401, { result: authError.message });
-  }
-
-  const {report, contact, hash} = this._allowed[req.query.token];
-
-  report.begin(hash);
-
-  this._manager.load(hash, function(err, item) {
-    if (err) {
-      return res.send(404, { result: err.message });
-    }
-
-    const nodeID = Object.keys(item.contracts)[0];
-    const shardsize = item.getContract({ nodeID: nodeID }).get('data_size');
-
-    // If the shard is not writable, it means we already have it, so let's
-    // just respond with a success message
-    if (typeof item.shard.write !== 'function') {
-      report.end(ExchangeReport.SUCCESS, 'SHARD_EXISTS');
-      self._bridgeClient.createExchangeReport(report);
-      return res.send(304, { result: 'Consignment completed' });
-    }
-
-    let received = 0;
-
-    self.activeTransfers++;
-    req.on('error', self._handleRequestError.bind(self));
-    res.on('close', self._handleEarlySocketClose.bind(self));
-    req.on('data', function(chunk) {
-      received += chunk.length;
-
-      hasher.update(chunk);
-      item.shard.write(chunk);
-
-      if (received > shardsize) {
-        report.end(ExchangeReport.FAILURE, 'FAILED_INTEGRITY');
-        self._bridgeClient.createExchangeReport(report);
-        item.shard.destroy(utils.warnOnError(self._log));
-        self.activeTransfers--;
-        return res.send(400, {
-          result: 'Shard exceeds the amount defined in the contract'
-        });
-      }
-    });
-
-    req.on('end', function() {
-      /* eslint max-statements: [2, 15] */
-      var calculatedHash = utils.rmd160(hasher.digest());
-      self.activeTransfers--;
-
-      if (calculatedHash !== hash) {
-        report.end(ExchangeReport.FAILURE, 'FAILED_INTEGRITY');
-        self._bridgeClient.createExchangeReport(report);
-        self._log.warn('calculated hash does not match the expected result');
-        item.shard.destroy(utils.warnOnError(self._log));
-        return res.send(400, {
-          result: 'Calculated hash does not match the expected result'
-        });
-      }
-
-      self._log.debug('Shard upload completed hash %s', hash);
-      item.shard.end();
-      report.end(ExchangeReport.SUCCESS, 'SHARD_UPLOADED');
-      self._bridgeClient.createExchangeReport(report);
-      self.reject(req.query.token);
-      res.send(200, { result: 'Consignment completed' });
-      self.emit('shardUploaded', item, contact);
-    });
-  });
-};
-
-/**
- * Pumps the data through to the client
- * @param {http.IncomingMessage} req
- * @param {http.ServerResponse} res
- */
-ShardServer.prototype.routeRetrieval = function(req, res) {
-  const self = this;
-  const [isAuthed, authError] = this.isAuthorized(
-    req.query.token,
-    req.params.hash
-  );
-
-  if (!isAuthed) {
-    return res.send(401, { result: authError.message });
-  }
-
-  const {report, contact, hash} = this._allowed[req.query.token];
-
-  this._manager.load(hash, function(err, item) {
-    if (err) {
-      return res.send(404, { result: err.message });
-    }
-
-    function _handleReadFailure(err) {
-      self.activeTransfers--;
-      report.end(ExchangeReport.FAILURE, 'READ_FAILED');
-      self._bridgeClient.createExchangeReport(report);
-      res.send(500, { result: err.message });
-    }
-
-    function _handleTransferFinish() {
-      self.activeTransfers--;
-      self._log.debug('Shard download completed hash %s', item.hash);
-      report.end(ExchangeReport.SUCCESS, 'SHARD_DOWNLOADED');
-      self._bridgeClient.createExchangeReport(report);
-      self.emit('shardDownloaded', item, contact);
-      self.reject(req.query.token);
-    }
-
-    self.activeTransfers++;
-    req.on('error', self._handleRequestError.bind(self));
-    res.on('close', self._handleEarlySocketClose.bind(self));
-    res.header('content-type', 'application/octet-stream');
-    report.begin(hash);
-    item.shard
-      .on('error', _handleReadFailure)
-      .on('end', _handleTransferFinish)
-      .pipe(res);
-  });
-};
-
-/**
- * Enumerates the authorized list and rejects expired
- * @private
- */
-ShardServer.prototype._reapDeadTokens = function() {
-  let now = Date.now();
-
-  for (let token in this._allowed) {
-    if (this._allowed[token].expires < now) {
-      this.reject(token);
-    }
-  }
-};
-
-module.exports = ShardServer;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_network_transport.js.html b/Storj/core/docs/lib_network_transport.js.html deleted file mode 100644 index 36c0959..0000000 --- a/Storj/core/docs/lib_network_transport.js.html +++ /dev/null @@ -1,478 +0,0 @@ - - - - - JSDoc: Source: lib/network/transport.js - - - - - - - - - - -
- -

Source: lib/network/transport.js

- - - - - - -
-
-
'use strict';
-
-const inherits = require('util').inherits;
-const kad = require('kad');
-const portfinder = require('portfinder');
-const natupnp = require('nat-upnp');
-const ip = require('ip');
-const merge = require('merge');
-const utils = require('../utils');
-const http = require('http');
-const restify = require('restify');
-const diglet = require('diglet');
-const net = require('net');
-const url = require('url');
-const ShardServer = require('./shard-server');
-
-/**
- * Custom HTTP transport adapter
- * @constructor
- * @license AGPL-3.0
- * @param {kad.Contact} contact - Contact object to binding to port
- * @param {Object}  options
- * @param {Logger}  options.logger - Logger for diagnositcs
- * @param {Number}  options.maxTunnels - Number of tunnels to provide to network
- * @param {Boolean} options.doNotTraverseNat - Do not try to punch out of NAT
- * @param {Object}  options.tunnelGatewayRange
- * @param {Number}  options.tunnelGatewayRange.min - Min port for gateway bind
- * @param {Number}  options.tunnelGatewayRange.max - Max port for gateway bind
- * @param {Number}  options.listenPort - Different port for the server to listen on (optional)
- * @param {StorageManager} options.storageManager
- * @param {BridgeClient} options.bridgeClient
- */
-function Transport(contact, options) {
-  if (!(this instanceof Transport)) {
-    return new Transport(contact, options);
-  }
-
-  this._opts = merge(Object.create(Transport.DEFAULTS), options);
-  this._queuedResponses = {};
-  this._maxTunnels = this._opts.maxTunnels;
-  this._doNotTraverseNat = this._opts.doNotTraverseNat;
-  this._tunnelGatewayRange = this._opts.tunnelGatewayRange;
-  this._server = restify.createServer({
-    name: 'storj',
-    handleUpgrades: true
-  });
-
-  kad.RPC.call(this, contact, options);
-  this.on(
-    'MESSAGE_DROP',
-    kad.transports.HTTP.prototype._handleDroppedMessage.bind(this)
-  );
-}
-
-Transport.DEFAULTS = {
-  maxTunnels: 3,
-  doNotTraverseNat: false,
-  tunnelGatewayRange: { min: 0, max: 0 }
-};
-
-/**
- * Triggered when the max connections limit is reached
- * @event Transport#connectionLimitReached
- */
-
-inherits(Transport, kad.RPC);
-
-/**
- * Opens the transport, trying UPnP to become publicly addressable and falling
- * back to using a Tunnel
- * @private
- * @param {Function} callback
- */
-Transport.prototype._open = function(callback) {
-  const self = this;
-
-  this.tunnelServer = new diglet.Server({
-    logger: this._log,
-    proxyPortRange: this._opts.tunnelGatewayRange,
-    proxyMaxConnections: 12,
-    maxProxiesAllowed: this._opts.maxTunnels
-  });
-  this.shardServer = new ShardServer({
-    bridgeClient: this._opts.bridgeClient,
-    storageManager: this._opts.storageManager,
-    logger: this._log,
-    nodeID: this._contact.nodeID
-  });
-
-  if (self._doNotTraverseNat) {
-    self._isPublic = true;
-
-    /* istanbul ignore next */
-    self._log.warn(
-      'your address is %s and traversal strategies are disabled',
-      ip.isPublic(self._contact.address) ? 'public' : 'private'
-    );
-
-    return self._bindServer(callback);
-  }
-
-  self._requiresTraversal = true;
-
-  function _traverseNat() {
-    self._log.warn(
-      'you are not publicly reachable, trying traversal strategies...'
-    );
-    self._forwardPort(function(err, wanip, port) {
-      self._isPublic = !err;
-
-      if (self._isPublic) {
-        self._contact.port = port || self._contact.port;
-        self._log.info('node bound and port mapped: %s', self._contact.port);
-      }
-
-      self._bindServer(callback);
-      self._contact.address = wanip || self._contact.address;
-    });
-  }
-
-  self._bindServer(function() {
-    self._checkIfReachable(function(isReachable) {
-      if (isReachable) {
-        return callback(null);
-      }
-
-      self._close();
-      _traverseNat();
-    });
-  });
-};
-
-/**
- * Sets up server routes
- * @private
- */
-Transport.prototype._bindServer = function(callback) {
-  const self = this;
-
-  // Disable TCP Nagle algorithm
-  self._server.on('connection', (sock) => sock.setNoDelay(true));
-
-  // Middleware
-  self._server.use(self._routeTunnelProxies.bind(self));
-  self._server.use(restify.CORS());
-
-  self._server.opts(/.*/, self._handleOpts.bind(self));
-
-  // Routes
-  self._server.post(
-    '/',
-    restify.bodyParser(),
-    self._handleRPC.bind(self)
-  );
-  self._server.post(
-    '/shards/:hash',
-    restify.queryParser(),
-    self.shardServer.routeConsignment.bind(self.shardServer)
-  );
-  self._server.get(
-    '/shards/:hash',
-    restify.queryParser(),
-    self.shardServer.routeRetrieval.bind(self.shardServer)
-  );
-
-  const port = self._opts.listenPort ?
-    self._opts.listenPort : self._contact.port;
-  self._server.listen(port, callback);
-};
-
-/**
- * _handleOpts handles incomming OPTIONS requests. These requests are preflight
- * requests for Cross-Origin requests enforced by browser security. This
- * function essentially allows all methods and headers for any origin, allowing
- * any domain to make a request to a farmer.
- * @private
- */
-Transport.prototype._handleOpts = function(req, res, next) {
-  res.header('Access-Control-Allow-Origin', '*');
-  res.header('Access-Control-Allow-Methods',
-    req.header('Access-Control-Request-Method'));
-  res.header('Access-Control-Allow-Headers',
-    req.header('Access-Control-Request-Headers'));
-  res.send(200);
-  return next();
-};
-
-/**
- * Handles incoming RPC messages
- * @private
- */
-Transport.prototype._handleRPC = function(req, res) {
-  const self = this;
-  let message;
-
-  try {
-    message = new kad.Message(req.body);
-  } catch (err) {
-    res.send(400, new Error('Invalid RPC message'));
-    self.receive(null);
-    return;
-  }
-
-  if (kad.Message.isRequest(message)) {
-    self._queuedResponses[message.id] = res;
-  }
-
-  self.receive(message.serialize(), {});
-};
-
-/**
- * Routes incoming requests to tunnels if any
- * @private
- */
-Transport.prototype._routeTunnelProxies = function(req, res, next) {
-  var self = this;
-  var targetNodeId = req.header('x-storj-node-id');
-  var upgradeReq = res.claimUpgrade ? res.claimUpgrade() : null;
-
-  if (!targetNodeId || targetNodeId === self._contact.nodeID) {
-    return next();
-  }
-
-  if (upgradeReq) {
-    self.tunnelServer.routeWebSocketConnection(
-      targetNodeId,
-      req,
-      upgradeReq.socket,
-      () => null
-    );
-  } else {
-    self.tunnelServer.routeHttpRequest(
-      targetNodeId,
-      req,
-      res,
-      () => null
-    );
-  }
-};
-
-/**
- * Implement the message dispatcher for RPC
- * @private
- */
-Transport.prototype._send = function(data, contact) {
-  var self = this;
-  var parsedMessage = JSON.parse(data.toString());
-
-  if (self._queuedResponses[parsedMessage.id]) {
-    self._queuedResponses[parsedMessage.id].send(200, parsedMessage);
-    delete self._queuedResponses[parsedMessage.id];
-    return;
-  }
-
-  if (!contact.valid()) {
-    return self.receive(null);
-  }
-
-  var client = restify.createJsonClient({
-    version: '*',
-    url: url.format({
-      hostname: contact.address,
-      port: contact.port,
-      protocol: 'http:'
-    }),
-    headers: {
-      'content-type': 'application/json',
-      'x-storj-node-id': contact.nodeID
-    },
-    agent: new http.Agent({ keepAlive: true, keepAliveMsecs: 25000 }),
-    // NB: Disable TCP Nagle algorithm - use `signRequest` options to
-    // NB: manipulate the request object before sending
-    signRequest: function(req) {
-      /* istanbul ignore next */
-      req.setNoDelay(true);
-    }
-  });
-
-  client.post('/', parsedMessage, (err, req, res, data) => {
-    if (err) {
-      self._log.warn('error returned from remote host: %s', err.message);
-      return self.receive(null);
-    }
-
-    let message;
-
-    try {
-      message = kad.Message(data);
-    } catch (err) {
-      return self.receive(null);
-    }
-
-    self.receive(message.serialize(), {});
-  });
-};
-
-/**
- * Closes the transport
- * @private
- */
-Transport.prototype._close = function() {
-  this._server.close();
-};
-
-/**
- * Checks if we are publicly reachable
- * @private
- * @param {Function}
- */
-Transport.prototype._checkIfReachable = function(callback) {
-  if (ip.isPrivate(this._contact.address)) {
-    return callback(false);
-  }
-
-  var sock = net.connect({
-    host: this._contact.address,
-    port: this._contact.port
-  });
-
-  sock.once('error', () => {
-    callback(false);
-    sock.removeAllListeners();
-    sock.destroy();
-  });
-  sock.once('connect', () => {
-    callback(true);
-    sock.removeAllListeners();
-    sock.end();
-  });
-};
-
-/**
- * Creates a port mapping with UPnP
- * @param {Number} port - The port to forward
- * @param {Function} callback - Callback function
- */
-Transport.prototype.createPortMapping = function(port, callback) {
-  var self = this;
-  var natupnpClient = natupnp.createClient();
-
-  natupnpClient.portMapping({
-    public: port,
-    private: port,
-    ttl: 0
-  }, function(err) {
-    if (err) {
-      self._log.warn('could not connect to NAT device via UPnP: %s', port);
-      return callback(err);
-    }
-
-    natupnpClient.externalIp(function(err, wanip) {
-      if (err) {
-        self._log.warn('could not obtain public IP address');
-        return callback(err);
-      }
-
-      if (!net.isIP(wanip)) {
-        self._log.warn('UPnP device has no valid IP address: %s',
-                        JSON.stringify(wanip));
-        return callback(new Error('UPnP device has no valid IP address'));
-      }
-
-      if (ip.isPrivate(wanip)) {
-        self._log.warn('UPnP device has no public IP address: %s', wanip);
-        return callback(new Error('UPnP device has no public IP address'));
-      }
-
-      self._log.info('successfully traversed NAT via UPnP: %s:%s', wanip, port);
-      callback(null, wanip, port);
-    });
-  });
-};
-
-/**
- * Resolve random port to use for opening a gateway
- * @private
- * @param {Number}  port
- * @param {Function} callback
- */
-Transport.prototype._getPort = function(callback) {
-  var self = this;
-
-  if (self._contact.port) {
-    return callback(null, self._contact.port);
-  }
-
-  portfinder.basePort = Math.floor(Math.random() * (65535 - 1024) + 1024);
-  portfinder.getPort(callback);
-};
-
-/**
- * Forwards a port and resolves the public IP
- * @private
- * @param {Function} callback
- */
-Transport.prototype._forwardPort = function(callback) {
-  var self = this;
-
-  self._getPort(function(err, port) {
-    if (err) {
-      self._log.warn('could not obtain port');
-      return callback(err);
-    }
-
-    self.createPortMapping(port, callback);
-  });
-};
-
-/**
- * Sends the RPC message to the given contact
- * @param {Contact} contact
- * @param {kad.Message} message
- * @param {Function} callback
- */
-Transport.prototype.send = function(contact, message, callback) {
-  if (kad.Message.isResponse(message)) {
-    return kad.RPC.prototype.send.apply(this, arguments);
-  }
-
-  if (!utils.isValidContact(contact, !!process.env.STORJ_ALLOW_LOOPBACK)) {
-    return callback(new Error('Invalid or forbidden contact address'));
-  }
-
-  kad.RPC.prototype.send.apply(this, arguments);
-};
-
-module.exports = Transport;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_patches.js.html b/Storj/core/docs/lib_patches.js.html deleted file mode 100644 index d5eda12..0000000 --- a/Storj/core/docs/lib_patches.js.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - JSDoc: Source: lib/patches.js - - - - - - - - - - -
- -

Source: lib/patches.js

- - - - - - -
-
-
/**
- * @module storj/patches
- * @license AGPL-3.0
- */
-
-'use strict';
-
-var kad = require('kad');
-var constants = require('./constants');
-
-module.exports = function() {
-
-  // NB: Increase response timeout for RPC calls
-  kad.constants.T_RESPONSETIMEOUT = constants.RPC_TIMEOUT;
-
-};
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_sips_0003_index.js.html b/Storj/core/docs/lib_sips_0003_index.js.html deleted file mode 100644 index 9aafad1..0000000 --- a/Storj/core/docs/lib_sips_0003_index.js.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - JSDoc: Source: lib/sips/0003/index.js - - - - - - - - - - -
- -

Source: lib/sips/0003/index.js

- - - - - - -
-
-
/**
- * @module storj/sips/0003
- */
-
-'use strict';
-
-/** {@link TriggerManager} */
-exports.TriggerManager = require('./trigger-manager');
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_sips_0003_trigger-manager.js.html b/Storj/core/docs/lib_sips_0003_trigger-manager.js.html deleted file mode 100644 index 5eb16a9..0000000 --- a/Storj/core/docs/lib_sips_0003_trigger-manager.js.html +++ /dev/null @@ -1,188 +0,0 @@ - - - - - JSDoc: Source: lib/sips/0003/trigger-manager.js - - - - - - - - - - -
- -

Source: lib/sips/0003/trigger-manager.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-
-/**
- * Implements behavior triggers as described in SIP-0003
- * @constructor
- * @license AGPL-3.0
- * @see https://github.com/storj/sips/blob/master/sip-0003.md
- */
-function TriggerManager(options) {
-  if (!(this instanceof TriggerManager)) {
-    return new TriggerManager(options);
-  }
-
-  this._options = options;
-  this._authorized = {};
-  this._behaviors = {};
-}
-
-/**
- * Adds a trigger handler for the given nodeID and behavior
- * @param {String|Array} nodeID - The nodeID(s) to authorize for the trigger
- * (supports `*` wildcard)
- * @param {Object} behaviors - Behavior name to {TriggerManager~triggerHandler}s
- */
-TriggerManager.prototype.add = function(nodeID, behaviors) {
-  var self = this;
-
-  if (Array.isArray(nodeID)) {
-    return nodeID.forEach(function(nodeID) {
-      self.add(nodeID, behaviors);
-    });
-  }
-
-  for (var behavior in behaviors) {
-    assert(
-      typeof behaviors[behavior] === 'function',
-      'Trigger handler must be a function'
-    );
-
-    if (!this._authorized[behavior]) {
-      this._authorized[behavior] = [];
-    }
-
-    if (this._authorized[behavior].indexOf(nodeID) === -1) {
-      this._authorized[behavior].push(nodeID);
-    }
-
-    this._behaviors[nodeID + ':' + behavior] = behaviors[behavior];
-  }
-};
-
-/**
- * Removes a trigger handler for the given nodeID and behavior
- * @param {String|Array} nodeID - The nodeID(s) to deauthorize for the trigger
- * @param {String|Array} behaviors - Behavior name to unregister
- */
-TriggerManager.prototype.remove = function(nodeID, behavior) {
-  var self = this;
-
-  if (Array.isArray(nodeID)) {
-    return nodeID.forEach(function(nodeID) {
-      if (Array.isArray(behavior)) {
-        return behavior.forEach(function(behavior) {
-          self.remove(nodeID, behavior);
-        });
-      }
-
-      self.remove(nodeID, behavior);
-    });
-  }
-
-  if (this._authorized[behavior]) {
-    var index = this._authorized[behavior].indexOf(nodeID);
-
-    if (index !== -1) {
-      this._authorized[behavior].splice(index, 1);
-    }
-  }
-
-  delete this._behaviors[nodeID + ':' + behavior];
-};
-
-/**
- * Process a received trigger message
- * @param {Object} messageParams - The received message params
- * @param {TriggerManager~processCallback} callback - Result of trigger process
- */
-TriggerManager.prototype.process = function(messageParams, callback) {
-  var authorized = this._authorized[messageParams.behavior];
-  var allowAnySource = authorized ? authorized.indexOf('*') !== -1 : false;
-  var sourceNodeId = allowAnySource || messageParams.contact.nodeID;
-
-  if (!authorized) {
-    return callback(new Error('No trigger handler defined for behavior'));
-  }
-
-  if (!allowAnySource && authorized.indexOf(sourceNodeId) === -1) {
-    return callback(new Error('Not authorized to process trigger'));
-  }
-
-  this._behaviors[sourceNodeId + ':' + messageParams.behavior](
-    messageParams,
-    callback,
-    this.remove.bind(this, sourceNodeId, messageParams.behavior)
-  );
-};
-
-/**
- * Called when a trigger is received from authorized source
- * @callback TriggerManager~triggerHandler
- * @param {Object} messageParams - The RPC message parameters
- * @param {TriggerManager~replyToSender} replyToSender - Respond to the trigger
- * @param {TriggerManager~destroyTrigger} destroyTrigger - Unregisters trigger
- */
-
-/**
- * Passed to the trigger handler for replying to the message
- * @callback TriggerManager~replyToSender
- * @param {Error|null} err - Optional error to respond with
- * @param {Object} params - Response parameters to return
- */
-
-/**
- * Optionally called from trigger handler to unregister the trigger handler
- * @callback TriggerManager~destroyTrigger
- */
-
-/**
- * Called upon the processing of a trigger message
- * @callback TriggerManager~processCallback
- * @param {Error|null} err - Optional error resulting from processing
- * @param {Object} params - Response parameters to send back
- */
-
-module.exports = TriggerManager;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_sips_index.js.html b/Storj/core/docs/lib_sips_index.js.html deleted file mode 100644 index 003f4e6..0000000 --- a/Storj/core/docs/lib_sips_index.js.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - JSDoc: Source: lib/sips/index.js - - - - - - - - - - -
- -

Source: lib/sips/index.js

- - - - - - -
-
-
/**
- * @module storj/sips
- * @license AGPL-3.0
- */
-
-'use strict';
-
-/** {@link module:storj/sips/0003} */
-module.exports.SIP0003 = require('./0003');
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_storage_adapter.js.html b/Storj/core/docs/lib_storage_adapter.js.html deleted file mode 100644 index 504771c..0000000 --- a/Storj/core/docs/lib_storage_adapter.js.html +++ /dev/null @@ -1,318 +0,0 @@ - - - - - JSDoc: Source: lib/storage/adapter.js - - - - - - - - - - -
- -

Source: lib/storage/adapter.js

- - - - - - -
-
-
'use strict';
-
-var stream = require('readable-stream');
-var assert = require('assert');
-var Item = require('./item');
-var EventEmitter = require('events').EventEmitter;
-var inherits = require('util').inherits;
-var StorageItem = require('./item');
-
-/**
- * Abstract base class for storage adapter
- * @constructor
- * @license AGPL-3.0
- */
-function StorageAdapter() {
-  if (!(this instanceof StorageAdapter)) {
-    return new StorageAdapter();
-  }
-
-  EventEmitter.call(this);
-}
-
-/**
- * Triggered when the adapter is ready
- * @event StorageAdapter#ready
- */
-
-/**
- * Triggered when a new item is added
- * @event StorageAdapter#add
- * @param {StorageItem} item
- */
-
-/**
- * Triggered when an item is deleted
- * @event StorageAdapter#delete
- * @param {StorageItem} item
- */
-
-/**
- * Triggered when an existing item is updated
- * @event StorageAdapter#update
- * @param {StorageItem} itemBeforeUpdate
- * @param {StorageItem} itemAfterUpdate
- */
-
-inherits(StorageAdapter, EventEmitter);
-
-/**
- * Calls the implemented {@link StorageAdapter#_get} and validates the result
- * @param {String} key - Shard hash to get metadata for
- * @param {Function} callback - Called with error or {@link StorageItem}
- */
-StorageAdapter.prototype.get = function(key, callback) {
-  assert(typeof key === 'string', 'Invalid key supplied');
-  assert(key.length === 40, 'Key must be 160 bit hex string');
-  assert(typeof callback === 'function', 'Callback function must be supplied');
-
-  return this._get(key, function(err, result) {
-    if (err) {
-      return callback(err);
-    }
-
-    callback(null, new StorageItem(result));
-  });
-};
-
-/**
- * Calls the implemented {@link StorageAdapter#_peek} and validates the result
- * @param {String} key - Shard hash to get metadata for
- * @param {Function} callback - Called with error or {@link StorageItem}
- */
-StorageAdapter.prototype.peek = function(key, callback) {
-  assert(typeof key === 'string', 'Invalid key supplied');
-  assert(key.length === 40, 'Key must be 160 bit hex string');
-  assert(typeof callback === 'function', 'Callback function must be supplied');
-
-  return this._peek(key, function(err, result) {
-    if (err) {
-      return callback(err);
-    }
-
-    callback(null, new StorageItem(result));
-  });
-};
-
-/**
- * Calls the implemented {@link StorageAdapter#_put} and validates the input
- * @param {StorageItem} item - Item to write to storage
- * @param {Function} callback - Called on complete write
- */
-StorageAdapter.prototype.put = function(item, callback) {
-  var self = this;
-
-  assert(item instanceof Item, 'Invalid storage item supplied');
-  assert(typeof callback === 'function', 'Callback function must be supplied');
-
-  item.updateTimestamp();
-
-  return this.peek(item.hash, function(doesNotExist, existingItem) {
-    self._put(item.hash, item.toObject(), function(err) {
-      if (err) {
-        return callback(err);
-      }
-
-      if (doesNotExist) {
-        self.emit('add', item);
-      } else {
-        self.emit('update', existingItem, item);
-      }
-
-      callback(null);
-    });
-  });
-};
-
-/**
- * Calls the implemented {@link StorageAdapter#_del}
- * @param {String} key - Shard hash to delete the data for
- * @param {Function} callback - Called with error or {@link StorageItem}
- */
-StorageAdapter.prototype.del = function(key, callback) {
-  var self = this;
-
-  assert(typeof key === 'string', 'Invalid key supplied');
-  assert(key.length === 40, 'Key must be 160 bit hex string');
-  assert(typeof callback === 'function', 'Callback function must be supplied');
-
-  this.peek(key, function(err, item) {
-    if (err) {
-      return callback(err);
-    }
-
-    return self._del(key, function(err) {
-      if (err) {
-        return callback(err);
-      }
-
-      self.emit('delete', item);
-      callback(null);
-    });
-  });
-};
-
-/**
- * Calls the implemented {@link StorageAdapter#_size}
- * @param {String} [key] - Optional file key
- * @param {Function} callback - Called with error or number of bytes stored
- */
-StorageAdapter.prototype.size = function(/* [,key] callback */) {
-  return this._size.apply(this, arguments);
-};
-
-/**
- * Calls the implemented {@link StorageAdapter#_flush}
- * @param {Function} callback - Called with error or null
- */
-StorageAdapter.prototype.flush = function(callback) {
-  assert(typeof callback === 'function', 'Callback function must be supplied');
-
-  return this._flush(callback);
-};
-
-/**
- * Calls the implemented {@link StorageAdapter#_keys} and returns a readable
- * stream containing each stored item
- * @return {ReadableStream}
- */
-StorageAdapter.prototype.createReadStream = function() {
-  return this._keys().pipe(new stream.Transform({
-    objectMode: true,
-    transform: (key, enc, next) => {
-      this.peek(key.toString(), next);
-    },
-    flush: (done) => done()
-  }));
-};
-
-/**
- * Performs lookup and provides an {@link StorageItem} to the callback
- * @abstract
- * @param {String} key - Shard hash
- * @param {Function} callback - Called on complete
- */
-StorageAdapter.prototype._flush = function(/* callback */) {
-  throw new Error('Method not implemented');
-};
-
-/**
- * Performs lookup and provides an {@link StorageItem} to the callback
- * @abstract
- * @param {String} key - Shard hash
- * @param {Function} callback - Called on complete
- */
-StorageAdapter.prototype._get = function(/* key, callback */) {
-  throw new Error('Method not implemented');
-};
-
-/**
- * Performs lookup and provides an {@link StorageItem} to the callback but does
- * not initialize any shard read/write stream
- * @abstract
- * @param {String} key - Shard hash
- * @param {Function} callback - Called on complete
- */
-StorageAdapter.prototype._peek = function(/* key, callback */) {
-  throw new Error('Method not implemented');
-};
-
-/**
- * Delete the shard data at the given key
- * @abstract
- * @param {String} key - Shard hash
- * @param {Function} callback - Called on complete
- */
-StorageAdapter.prototype._del = function(/* key, callback */) {
-  throw new Error('Method not implemented');
-};
-
-/**
- * Stores the {@link StorageItem}
- * @abstract
- * @param {String} key - Shard hash
- * @param {Item} item - Item to store
- * @param {Function} callback - Called on complete
- */
-StorageAdapter.prototype._put = function(/* item, callback */) {
-  throw new Error('Method not implemented');
-};
-
-/**
- * Returns the hashes of all shards stored
- * @abstract
- * @returns {ReadableStream}
- */
-StorageAdapter.prototype._keys = function() {
-  throw new Error('Method not implemented');
-};
-
-/**
- * Returns the number of bytes stored
- * @abstract
- * @param {Function} callback - Called on complete
- */
-StorageAdapter.prototype._size = function(/* callback */) {
-  throw new Error('Method not implemented');
-};
-
-/**
- * Opens the storage adapter
- * @abstract
- * @param {Function} callback - Called on complete
- */
-StorageAdapter.prototype._open = function(callback) {
-  callback(null);
-};
-
-/**
- * Closes the storage adapter
- * @abstract
- * @param {Function} callback - Called on complete
- */
-StorageAdapter.prototype._close = function(callback) {
-  callback(null);
-};
-
-module.exports = StorageAdapter;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_storage_adapters_embedded.js.html b/Storj/core/docs/lib_storage_adapters_embedded.js.html deleted file mode 100644 index 4f3618d..0000000 --- a/Storj/core/docs/lib_storage_adapters_embedded.js.html +++ /dev/null @@ -1,333 +0,0 @@ - - - - - JSDoc: Source: lib/storage/adapters/embedded.js - - - - - - - - - - -
- -

Source: lib/storage/adapters/embedded.js

- - - - - - -
-
-
'use strict';
-
-var inherits = require('util').inherits;
-var StorageAdapter = require('../adapter');
-var levelup = require('levelup');
-var kfs = require('kfs');
-var path = require('path');
-var assert = require('assert');
-var utils = require('../../utils');
-var mkdirp = require('mkdirp');
-
-/**
- * Implements an LevelDB/KFS storage adapter interface
- * @extends {StorageAdapter}
- * @param {String} storageDirPath - Path to store the level db
- * @constructor
- * @license AGPL-3.0
- */
-function EmbeddedStorageAdapter(storageDirPath) {
-  if (!(this instanceof EmbeddedStorageAdapter)) {
-    return new EmbeddedStorageAdapter(storageDirPath);
-  }
-
-  this._validatePath(storageDirPath);
-
-  this._path = storageDirPath;
-  this._db = levelup(path.join(this._path, 'contracts.db'), {
-    maxOpenFiles: EmbeddedStorageAdapter.MAX_OPEN_FILES
-  });
-  this._fs = kfs(path.join(this._path, 'sharddata.kfs'));
-  this._isOpen = true;
-}
-
-EmbeddedStorageAdapter.SIZE_START_KEY = '0';
-EmbeddedStorageAdapter.SIZE_END_KEY = 'z';
-EmbeddedStorageAdapter.MAX_OPEN_FILES = 1000;
-
-inherits(EmbeddedStorageAdapter, StorageAdapter);
-
-/**
- * Validates the storage path supplied
- * @private
- */
-EmbeddedStorageAdapter.prototype._validatePath = function(storageDirPath) {
-  if (!utils.existsSync(storageDirPath)) {
-    mkdirp.sync(storageDirPath);
-  }
-
-  assert(utils.isDirectory(storageDirPath), 'Invalid directory path supplied');
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_get}
- * @private
- * @param {String} key
- * @param {Function} callback
- */
-EmbeddedStorageAdapter.prototype._get = function(key, callback) {
-  var self = this;
-
-  this._db.get(key, { fillCache: false }, function(err, value) {
-    if (err) {
-      return callback(err);
-    }
-
-    var result = JSON.parse(value);
-    var fskey = result.fskey || key;
-
-    self._fs.exists(fskey, function(err, exists) {
-      if (err) {
-        return callback(err);
-      }
-
-      function _getShardStreamPointer(callback) {
-        var getStream = exists ?
-                        self._fs.createReadStream.bind(self._fs) :
-                        self._fs.createWriteStream.bind(self._fs);
-        if (!exists) {
-          fskey = utils.rmd160(key, 'hex');
-          result.fskey = fskey;
-        }
-        getStream(fskey, function(err, stream) {
-          if (err) {
-            return callback(err);
-          }
-
-          result.shard = stream;
-
-          callback(null, result);
-        });
-      }
-
-      _getShardStreamPointer(callback);
-    });
-  });
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_peek}
- * @private
- * @param {String} key
- * @param {Function} callback
- */
-EmbeddedStorageAdapter.prototype._peek = function(key, callback) {
-  this._db.get(key, { fillCache: false }, function(err, value) {
-    if (err) {
-      return callback(err);
-    }
-
-    callback(null, JSON.parse(value));
-  });
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_put}
- * @private
- * @param {String} key
- * @param {Object} item
- * @param {Function} callback
- */
-EmbeddedStorageAdapter.prototype._put = function(key, item, callback) {
-  var self = this;
-
-  item.shard = null; // NB: Don't store any shard data here
-
-  item.fskey = utils.rmd160(key, 'hex');
-
-  self._db.put(key, JSON.stringify(item), {
-    sync: true
-  }, function(err) {
-    if (err) {
-      return callback(err);
-    }
-
-    callback(null);
-  });
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_del}
- * @private
- * @param {String} key
- * @param {Function} callback
- */
-EmbeddedStorageAdapter.prototype._del = function(key, callback) {
-  var self = this;
-  var fskey = key;
-
-  self._peek(key, function(err, item) {
-    if (!err && item.fskey) {
-      fskey = item.fskey;
-    }
-
-    self._db.del(key, function(err) {
-      if (err) {
-        return callback(err);
-      }
-
-      self._fs.unlink(fskey, function(err) {
-        if (err) {
-          return callback(err);
-        }
-
-        callback(null);
-      });
-    });
-  });
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_flush}
- * @private
- * @param {Function} callback
- */
-EmbeddedStorageAdapter.prototype._flush = function(callback) {
-  this._fs.flush(callback);
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_size}
- * @private
- * @param {String} [key]
- * @param {Function} callback
- */
-EmbeddedStorageAdapter.prototype._size = function(key, callback) {
-  var self = this;
-
-  if (typeof key === 'function') {
-    callback = key;
-    key = null;
-  }
-
-  this._db.db.approximateSize(
-    EmbeddedStorageAdapter.SIZE_START_KEY,
-    EmbeddedStorageAdapter.SIZE_END_KEY,
-    function(err, contractDbSize) {
-      if (err) {
-        return callback(err);
-      }
-
-      function handleStatResults(err, stats) {
-        if (err) {
-          return callback(err);
-        }
-
-        var kfsUsedSpace = stats.reduce(function(stat1, stat2) {
-          return {
-            sBucketStats: {
-              size: stat1.sBucketStats.size + stat2.sBucketStats.size
-            }
-          };
-        }, {
-          sBucketStats: { size: 0 }
-        }).sBucketStats.size;
-
-        callback(null, kfsUsedSpace + contractDbSize);
-      }
-
-      /* istanbul ignore if */
-      if (key) {
-        self._fs.stat(utils.rmd160(key, 'hex'), handleStatResults);
-      } else {
-        self._fs.stat(handleStatResults);
-      }
-    }
-  );
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_keys}
- * @private
- * @returns {ReadableStream}
- */
-EmbeddedStorageAdapter.prototype._keys = function() {
-  return this._db.createKeyStream();
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_open}
- * @private
- * @param {Function} callback
- */
-EmbeddedStorageAdapter.prototype._open = function(callback) {
-  var self = this;
-
-  if (!this._isOpen) {
-    return this._db.open(function(err) {
-      if (err) {
-        return callback(err);
-      }
-
-      self._isOpen = true;
-      callback(null);
-    });
-  }
-
-  callback(null);
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_close}
- * @private
- * @param {Function} callback
- */
-EmbeddedStorageAdapter.prototype._close = function(callback) {
-  var self = this;
-
-  if (this._isOpen) {
-    return this._db.close(function(err) {
-      if (err) {
-        return callback(err);
-      }
-
-      self._isOpen = false;
-      callback(null);
-    });
-  }
-
-  callback(null);
-};
-
-module.exports = EmbeddedStorageAdapter;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_storage_adapters_ram.js.html b/Storj/core/docs/lib_storage_adapters_ram.js.html deleted file mode 100644 index cdc99af..0000000 --- a/Storj/core/docs/lib_storage_adapters_ram.js.html +++ /dev/null @@ -1,216 +0,0 @@ - - - - - JSDoc: Source: lib/storage/adapters/ram.js - - - - - - - - - - -
- -

Source: lib/storage/adapters/ram.js

- - - - - - -
-
-
'use strict';
-
-var inherits = require('util').inherits;
-var stream = require('readable-stream');
-var StorageAdapter = require('../adapter');
-
-/**
- * Implements an in-memory storage adapter
- * @extends {StorageAdapter}
- * @constructor
- * @license AGPL-3.0
- */
-function RAMStorageAdapter() {
-  if (!(this instanceof RAMStorageAdapter)) {
-    return new RAMStorageAdapter();
-  }
-
-  this._items = {};
-  this._shards = {};
-}
-
-inherits(RAMStorageAdapter, StorageAdapter);
-
-/**
- * Implements the abstract {@link StorageAdapter#_get}
- * @private
- * @param {String} key
- * @param {Function} callback
- */
-RAMStorageAdapter.prototype._get = function(key, callback) {
-  var self = this;
-  var result = this._items[key];
-
-  if (!result) {
-    return callback(new Error('Shard data not found'));
-  }
-
-  if (this._shards[key]) {
-    result.shard = this._decorateStreamWithDestroy(key, new stream.Readable({
-      read: function() {
-        if (this._finished) {
-          this.push(null);
-        } else {
-          this.push(self._shards[key]);
-          this._finished = true;
-        }
-      }
-    }));
-  } else {
-    result.shard = this._decorateStreamWithDestroy(key, new stream.Writable({
-      write: function(data, encoding, next) {
-        self._shards[key] = data;
-        next();
-      }
-    }));
-  }
-
-  callback(null, result);
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_peek}
- * @private
- * @param {String} key
- * @param {Function} callback
- */
-RAMStorageAdapter.prototype._peek = function(key, callback) {
-  if (!this._items[key]) {
-    return callback(new Error('Shard data not found'));
-  }
-
-  callback(null, this._items[key]);
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_put}
- * @private
- * @param {String} key
- * @param {StorageItem} item
- * @param {Function} callback
- */
-RAMStorageAdapter.prototype._put = function(key, item, callback) {
-  this._items[key] = item;
-
-  callback();
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_flush}
- * @private
- * @param {Function} callback
- */
-RAMStorageAdapter.prototype._flush = function(callback) {
-  callback();
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_del}
- * @private
- * @param {String} key
- * @param {Function} callback
- */
-RAMStorageAdapter.prototype._del = function(key, callback) {
-  delete this._shards[key];
-
-  callback();
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_size}
- * @private
- * @param {String} [key]
- * @param {Function} callback
- */
-/* istanbul ignore next */
-RAMStorageAdapter.prototype._size = function(key, callback) {
-  /* istanbul ignore if */
-  if (typeof key === 'function') {
-    callback = key;
-  }
-
-  var shardBytes = 0;
-
-  for (var _key in this._shards) {
-    shardBytes += this._shards[_key].length;
-  }
-
-  callback(
-    null,
-    Buffer(JSON.stringify(this._items)).length + shardBytes
-  );
-};
-
-/**
- * Implements the abstract {@link StorageAdapter#_keys}
- * @private
- * @returns {ReadableStream}
- */
-RAMStorageAdapter.prototype._keys = function() {
-  var keys = Object.keys(this._items);
-
-  return new stream.Readable({
-    read: function() {
-      this.push(keys.length ? keys.shift() : null);
-    }
-  });
-};
-
-/**
- * Decorates a stream with a destroy method to remove any data written
- * @private
- * @param {String} key
- * @param {Stream} stream
- */
-RAMStorageAdapter.prototype._decorateStreamWithDestroy = function(key, stream) {
-  var self = this;
-
-  stream.destroy = function() {
-    delete self._shards[key];
-  };
-
-  return stream;
-};
-
-module.exports = RAMStorageAdapter;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_storage_item.js.html b/Storj/core/docs/lib_storage_item.js.html deleted file mode 100644 index b8db4c9..0000000 --- a/Storj/core/docs/lib_storage_item.js.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - JSDoc: Source: lib/storage/item.js - - - - - - - - - - -
- -

Source: lib/storage/item.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var Contract = require('../contract');
-var merge = require('merge');
-
-/**
- * Represents a storage item, including contracts, challenges, the shard itself
- * along with metadata describing download count, payments, etc
- * @constructor
- * @license AGPL-3.0
- * @param {Object} data
- * @param {String|null} data.hash - Shard hash to use as storage key
- * @param {Stream|null} data.shard - Raw binary blob of shard
- * @param {Object} data.contracts - Dictionary of nodeID:{@link Contract}
- * @param {Object} data.trees - Dictionary of nodeID:merkleLeaves
- * @param {Object} data.challenges - Dictionary of nodeID:privateAuditData
- * @param {Object} data.meta - Dictionary of arbitrary nodeID:metadata
- */
-function StorageItem(data) {
-  if (!(this instanceof StorageItem)) {
-    return new StorageItem(data);
-  }
-
-  data = merge({}, data);
-
-  this.hash = null;
-  this.fskey = null;
-  this.shard = null;
-  this.contracts = {};
-  this.contractsHDMap = {};
-  this.trees = data.trees || {};
-  this.challenges = data.challenges || {};
-  this.meta = data.meta || {};
-  this.modified = data.modified || Date.now();
-
-  this._init(data);
-}
-
-/**
- * Adds the trees and challenges to the item keyed by nodeID
- * @param {Contact} contact - The contact associated with the trees
- * @param {Audit|AuditStream} audit - The audit or challenge generator
- */
-StorageItem.prototype.addAuditRecords = function(contact, audit) {
-  this.trees[contact.nodeID] = audit.getPublicRecord();
-  this.challenges[contact.nodeID] = audit.getPrivateRecord();
-
-  return this;
-};
-
-/**
- * Adds the contract data keyed by nodeID and hdKey
- * @param {Contact} contact - The contact associated with the trees
- * @param {Contract} contract - The storage contract instance
- */
-StorageItem.prototype.addContract = function(contact, contract) {
-  assert(contract instanceof Contract, 'Invalid contract supplied');
-  assert(contact && contact.nodeID, 'contact.nodeID is expected');
-
-  this.contracts[contact.nodeID] = contract;
-  var hdKey = contact.hdKey;
-
-  if (hdKey) {
-    this.contractsHDMap[hdKey] = contract;
-  }
-
-  return this;
-};
-
-/**
- * Gets a contract data by a contact based on the hdKey or the nodeID
- * of the contact. It will return false if the contract is not found for the
- * contact, which will indicate that the contact is not authorized for
- * that specific contract.
- * @param {Contact} contact - The contact associated with the trees
- * @param {Contract} contract - The storage contract instance
- * @returns {Contract|Boolean}
- */
-StorageItem.prototype.getContract = function(contact) {
-  if (contact.hdKey) {
-    return this.contractsHDMap[contact.hdKey] || false;
-  } else {
-    return this.contracts[contact.nodeID] || false;
-  }
-};
-
-/**
- * Deletes the contract for the given contact
- * @param {Contact} contact
- * @returns {Boolean} didRemoveContract
- */
-StorageItem.prototype.removeContract = function(contact) {
-  if (this.getContract(contact)) {
-    if (contact.hdKey) {
-      delete this.contractsHDMap[contact.hdKey];
-    } else {
-      delete this.contracts[contact.nodeID];
-    }
-    return true;
-  }
-  return false;
-};
-
-/**
- * Adds the meta data keyed by nodeID
- * @param {Contact} contact - The contact associated with the trees
- * @param {Object} meta - Arbitrary metadata about the shard
- */
-StorageItem.prototype.addMetaData = function(contact, meta) {
-  this.meta[contact.nodeID] = meta;
-
-  return this;
-};
-
-/**
- * Updates the timestamp for the item
- */
-StorageItem.prototype.updateTimestamp = function() {
-  this.modified = Date.now();
-
-  return this;
-};
-
-/**
- * Returns a plain object representation of the item
- */
-StorageItem.prototype.toObject = function() {
-  var contracts = {};
-
-  for (var c in this.contracts) {
-    contracts[c] = this.contracts[c].toObject();
-  }
-
-  return {
-    hash: this.hash,
-    fskey: this.fskey,
-    shard: null,
-    contracts: contracts,
-    challenges: this.challenges,
-    trees: this.trees,
-    meta: this.meta,
-    modified: this.modified
-  };
-};
-
-/**
- * Initializes the item values with the given data
- * @private
- * @param {Object} data
- * @returns {StorageItem}
- */
-StorageItem.prototype._init = function(data) {
-  assert(typeof data === 'object', 'Invalid item data supplied');
-
-  this.shard = data.shard || null;
-  this.hash = data.hash || null;
-  this.fskey = data.fskey || null;
-
-  for (var nodeID in data.contracts) {
-    var contract = new Contract(data.contracts[nodeID]);
-    this.addContract({
-      nodeID: nodeID,
-      hdKey: contract.get('renter_hd_key')
-    }, contract);
-  }
-
-  return this;
-};
-
-module.exports = StorageItem;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_storage_manager.js.html b/Storj/core/docs/lib_storage_manager.js.html deleted file mode 100644 index 09e240c..0000000 --- a/Storj/core/docs/lib_storage_manager.js.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - JSDoc: Source: lib/storage/manager.js - - - - - - - - - - -
- -

Source: lib/storage/manager.js

- - - - - - -
-
-
'use strict';
-
-var constants = require('../constants');
-var assert = require('assert');
-var StorageAdapter = require('./adapter');
-var StorageItem = require('./item');
-var merge = require('merge');
-var EventEmitter = require('events').EventEmitter;
-var inherits = require('util').inherits;
-var Logger = require('kad-logger-json');
-
-/**
- * Interface for managing contracts, shards, and audits
- * @constructor
- * @license AGPL-3.0
- * @extends {EventEmitter}
- * @param {StorageAdapter} storage - Storage adapter to use
- * @param {Object} options
- * @param {Boolean} options.disableReaper - Don't perform periodic reaping of
- * stale contracts
- * @param {Object} [options.logger] - Logger to use for debugging
- * @param {Number} options.maxCapacity - Max number of bytes to allow in storage
- */
-function StorageManager(storage, options) {
-  if (!(this instanceof StorageManager)) {
-    return new StorageManager(storage, options);
-  }
-
-  assert(storage instanceof StorageAdapter, 'Invalid storage adapter');
-
-  this._options = merge(Object.create(StorageManager.DEFAULTS), options);
-  this._storage = storage;
-  this._logger = this._options.logger || new Logger(0);
-
-  this._initShardReaper();
-}
-
-inherits(StorageManager, EventEmitter);
-
-StorageManager.DEFAULTS = {
-  disableReaper: false,
-  maxCapacity: Infinity
-};
-
-/**
- * Loads the storage {@link Item} at the given key
- * @param {String} hash - Shard hash to load data for
- * @param {Function} callback - Called with error or {@link StorageItem}
- */
-StorageManager.prototype.load = function(hash, callback) {
-  assert(typeof hash === 'string', 'Invalid key supplied');
-  assert(hash.length === 40, 'Key must be 160 bit hex string');
-  assert(typeof callback === 'function', 'Callback function must be supplied');
-
-  this._storage.get(hash, function(err, item) {
-    if (err) {
-      return callback(err);
-    }
-
-    if (!(item instanceof StorageItem)) {
-      return callback(new Error('Storage adapter provided invalid result'));
-    }
-
-    callback(null, item);
-  });
-};
-
-/**
- * Saves the storage {@link StorageItem} at the given key
- * @param {StorageItem} item - The {@link StorageItem} to store
- * @param {Function} callback - Called on complete
- */
-StorageManager.prototype.save = function(item, callback) {
-  var self = this;
-
-  assert(item instanceof StorageItem, 'Invalid storage item supplied');
-  assert(typeof callback === 'function', 'Callback function must be supplied');
-
-  self._storage.get(item.hash, function(err, existingItem) {
-    self._storage.put(
-      self._merge(existingItem, item),
-      function(err) {
-        if (err) {
-          return callback(err);
-        }
-
-        callback(null);
-      }
-    );
-  });
-};
-
-/**
- * Merges two storage items together
- * @private
- */
-StorageManager.prototype._merge = function(item1, item2) {
-  return new StorageItem(
-    merge.recursive(
-      true,
-      item1 ?
-        ((item1 instanceof StorageItem) ?
-          item1.toObject() :
-          StorageItem(item1).toObject()) :
-        {},
-      item2 ?
-        ((item2 instanceof StorageItem) ?
-          item2.toObject() :
-          StorageItem(item2).toObject()) :
-        {}
-    )
-  );
-};
-
-/**
- * Opens the underlying storage adapter
- * @param {Function} callback - Called on complete
- */
-StorageManager.prototype.open = function(callback) {
-  this._storage._open(callback);
-};
-
-/**
- * Closes the underlying storage adapter
- * @param {Function} callback - Called on complete
- */
-StorageManager.prototype.close = function(callback) {
-  this._storage._close(callback);
-};
-
-/**
- * Enumerates all storage contracts and reaps stale data
- * @param {Function} callback - Called on complete
- */
-StorageManager.prototype.clean = function(callback) {
-  var self = this;
-  var rstream = this._storage.createReadStream();
-  var timestamp = Date.now();
-
-  this._logger.info('starting shard reaper, checking for expired contracts');
-
-  rstream.on('data', function(item) {
-    rstream.pause();
-
-    var total = Object.keys(item.contracts).length;
-    var endedOrIncomplete = 0;
-
-    for (var nodeID in item.contracts) {
-      var ended = item.contracts[nodeID].get('store_end') < timestamp;
-      var incomplete = !item.contracts[nodeID].isComplete();
-
-      if (ended || incomplete) {
-        endedOrIncomplete++;
-      }
-    }
-
-    if (total === endedOrIncomplete) {
-      self._logger.info('destroying shard/contract for %s', item.hash);
-      self._storage.del(item.hash, function(/* err */) {
-        rstream.resume();
-      });
-    } else {
-      rstream.resume();
-    }
-  });
-
-  rstream.on('end', function() {
-    self._logger.info('flushing shards, some buckets will be inaccessible');
-    self._storage.flush(function(err) {
-      /* istanbul ignore if */
-      if (err) {
-        self._logger.warn('problem while flushing shards, %s', err.message);
-      }
-
-      self._logger.info('flushing shards finished');
-      callback();
-    });
-  });
-};
-
-/**
- * Initialize the shard reaper to check for stale contracts and reap shards
- * @private
- */
-StorageManager.prototype._initShardReaper = function() {
-  if (this._options.disableReaper) {
-    return false;
-  }
-
-  setTimeout(this.clean.bind(this, this._initShardReaper.bind(this)),
-             constants.CLEAN_INTERVAL);
-};
-
-module.exports = StorageManager;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_storage_migration.js.html b/Storj/core/docs/lib_storage_migration.js.html deleted file mode 100644 index a35c0f3..0000000 --- a/Storj/core/docs/lib_storage_migration.js.html +++ /dev/null @@ -1,188 +0,0 @@ - - - - - JSDoc: Source: lib/storage/migration.js - - - - - - - - - - -
- -

Source: lib/storage/migration.js

- - - - - - -
-
-
'use strict';
-
-var assert = require('assert');
-var StorageAdapter = require('./adapter');
-var inherits = require('util').inherits;
-var EventEmitter = require('events').EventEmitter;
-var StorageItem = require('./item');
-var WritableStream = require('readable-stream').Writable;
-
-/**
- * Migrates data stored with one {@link StorageAdapter} to another
- * @constructor
- * @license AGPL-3.0
- * @param {StorageAdapter} source - The source adapter
- * @param {StorageAdapter} target - The migration destination
- */
-function StorageMigration(source, target) {
-  if (!(this instanceof StorageMigration)) {
-    return new StorageMigration(source, target);
-  }
-
-  assert(source instanceof StorageAdapter, 'Invalid storage adapter supplied');
-  assert(target instanceof StorageAdapter, 'Invalid storage adapter supplied');
-
-  this.source = source;
-  this.target = target;
-  this.readyState = StorageMigration.STOPPED;
-  this._isReady = false;
-
-  EventEmitter.call(this);
-}
-
-inherits(StorageMigration, EventEmitter);
-
-StorageMigration.STOPPED = 0;
-StorageMigration.STARTED = 1;
-
-/**
- * Starts the migration process
- */
-StorageMigration.prototype.start = function() {
-  var self = this;
-
-  assert(
-    this.readyState === StorageMigration.STOPPED,
-    'Migration has already started'
-  );
-
-  self.readyState = StorageMigration.STARTED;
-  self._sourceStream = self.source.createReadStream();
-  self._targetStream = new WritableStream({
-    write: self._handleSourceObject.bind(self),
-    objectMode: true
-  });
-
-  self._targetStream.on('finish', self._handleSourceFinished.bind(self));
-  self._sourceStream.on('error', self._handleSourceError.bind(self));
-  self._targetStream.on('error', self._handleSourceError.bind(self));
-
-  return self._sourceStream.pipe(self._targetStream);
-};
-
-/**
- * Stops the migration process
- */
-StorageMigration.prototype.stop = function() {
-  assert(
-    this.readyState === StorageMigration.STARTED,
-    'Migration has already stopped'
-  );
-
-  this._sourceStream.removeAllListeners();
-
-  this.readyState = StorageMigration.STOPPED;
-  this._sourceStream = null;
-};
-
-/**
- * Handles a data event from the source read stream and inserts it into the
- * the target adapter
- * @private
- * @param {StorageItem} sourceItem - Storage item from the source read stream
- */
-StorageMigration.prototype._handleSourceObject = function(sourceItem, enc, cb) {
-  var self = this;
-
-  self.target.put(StorageItem(sourceItem), function(err) {
-    if (err) {
-      return cb(err);
-    }
-
-    self.target.get(sourceItem.hash, function(err, targetItem) {
-      if (err) {
-        return cb(err);
-      }
-
-      self.source.get(sourceItem.hash, function(err, fullSourceItem) {
-        if (err) {
-          return cb(err);
-        }
-
-        if (typeof fullSourceItem.shard.read === 'function') {
-          return fullSourceItem.shard.pipe(targetItem.shard)
-            .on('error', cb)
-            .on('finish', cb);
-        }
-
-        cb();
-      });
-    });
-  });
-};
-
-/**
- * Handles the completion of the source stream read
- * @private
- */
-StorageMigration.prototype._handleSourceFinished = function() {
-  this.readyState = StorageMigration.STOPPED;
-  this._sourceStream = null;
-
-  this.emit('finish');
-};
-
-/**
- * Handles errors received from the underyling source stream
- * @private
- * @param {Error} error
- */
-StorageMigration.prototype._handleSourceError = function(err) {
-  this.readyState = StorageMigration.STOPPED;
-  this._sourceStream = null;
-
-  this.emit('error', err);
-};
-
-module.exports = StorageMigration;
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_utils.js.html b/Storj/core/docs/lib_utils.js.html deleted file mode 100644 index 31c93d5..0000000 --- a/Storj/core/docs/lib_utils.js.html +++ /dev/null @@ -1,640 +0,0 @@ - - - - - JSDoc: Source: lib/utils.js - - - - - - - - - - -
- -

Source: lib/utils.js

- - - - - - -
-
-
/**
- * @module storj/utils
- * @license LGPL-3.0
- */
-
-'use strict';
-
-var http = require('http');
-var stream = require('readable-stream');
-var assert = require('assert');
-var HDKey = require('hdkey');
-var constants = require('./constants');
-var KeyPair = require('./crypto-tools/keypair');
-var crypto = require('crypto');
-var semver = require('semver');
-var ip = require('ip');
-var ntp = require('ntp-client');
-var bitcore = require('bitcore-lib');
-var ECIES = require('bitcore-ecies');
-var through = require('through');
-var fs = require('fs');
-var base58 = bitcore.deps.bs58;
-var os = require('os');
-
-/**
- * Returns the SHA-1 hash of the input
- * @param {String|Buffer} input - Data to hash
- * @param {String} encoding - The encoding type of the data
- * @returns {String}
- */
-module.exports.sha1 = function(input, encoding) {
-  return crypto.createHash('sha1').update(input, encoding).digest('hex');
-};
-
-/**
- * Returns the SHA-256 hash of the input
- * @param {String|Buffer} input - Data to hash
- * @param {String} encoding - The encoding type of the data
- * @returns {String}
- */
-module.exports.sha256 = function(input, encoding) {
-  return crypto.createHash('sha256').update(input, encoding).digest('hex');
-};
-
-/**
- * Returns the SHA-256 hash of the input
- * @param {String|Buffer} input - Data to hash
- * @param {String} encoding - The encoding type of the data
- * @returns {Buffer}
- */
-module.exports.sha256b = function(input, encoding) {
-  return crypto.createHash('sha256').update(input, encoding).digest();
-};
-
-/**
- * Returns the SHA-512 hash of the input
- * @param {String|Buffer} input - Data to hash
- * @param {String} encoding - The encoding type of the data
- * @returns {String}
- */
-module.exports.sha512 = function(input, encoding) {
-  return crypto.createHash('sha512').update(input, encoding).digest('hex');
-};
-
-/**
- * Returns the RIPEMD-160 hash of the input
- * @param {String|Buffer} input - Data to hash
- * @param {String} encoding - The encoding type of the data
- * @returns {String}
- */
-module.exports.rmd160 = function(input, encoding) {
-  return crypto.createHash('rmd160').update(input, encoding).digest('hex');
-};
-
-/**
- * Returns the RIPEMD-160 hash of the input
- * @param {String|Buffer} input - Data to hash
- * @param {String} encoding - The encoding type of the data
- * @returns {Buffer}
- */
-module.exports.rmd160b = function(input, encoding) {
-  return crypto.createHash('rmd160').update(input, encoding).digest();
-};
-
-/**
- * Returns the WHIRLPOOL hash of the input
- * @param {String|Buffer} input - Data to hash
- * @param {String} encoding - The encoding type of the data
- * @returns {String}
- */
-module.exports.whirlpool = function(input, encoding) {
-  return crypto.createHash('whirlpool').update(input, encoding).digest('hex');
-};
-
-/**
- * Returns the RIPEMD-160 SHA-256 hash of this input
- * @param {String|Buffer} input - Data to hash
- * @param {String} encoding - The encoding type of the data
- * @returns {String}
- */
-module.exports.rmd160sha256 = function(input, encoding) {
-  return module.exports.rmd160(
-    Buffer(module.exports.sha256(input, encoding), 'hex')
-  );
-};
-
-/**
- * Returns the RIPEMD-160 SHA-256 hash of this input
- * @param {String|Buffer} input - Data to hash
- * @param {String} encoding - The encoding type of the data
- * @returns {Buffer}
- */
-module.exports.rmd160sha256b = function(input, encoding) {
-  return module.exports.rmd160b(module.exports.sha256b(input, encoding))
-};
-
-/**
- * Returns the SHA-1 WHIRLPOOL hash of this input
- * @param {String|Buffer} input - Data to hash
- * @param {String} encoding - The encoding type of the data
- * @returns {String}
- */
-module.exports.sha1whirlpool = function(input, encoding) {
-  return module.exports.sha1(
-    Buffer(module.exports.whirlpool(input, encoding), 'hex')
-  );
-};
-
-/**
- * Returns the next power of two number
- * @param {Number} number
- * @returns {Number}
- */
-module.exports.getNextPowerOfTwo = function(num) {
-  return Math.pow(2, Math.ceil(Math.log(num) / Math.log(2)));
-};
-
-/**
- * Generates a unique token
- * @returns {String}
- */
-module.exports.generateToken = function() {
-  return module.exports.rmd160sha256(crypto.randomBytes(512));
-};
-
-/**
- * Returns a stringified URL from the supplied contact object
- * @param {Object} contact
- * @param {String} contact.address
- * @param {Number} contact.port
- * @param {String} contact.nodeID
- * @returns {String}
- */
-module.exports.getContactURL = function(contact) {
-  return [
-    'storj://', contact.address, ':', contact.port, '/', contact.nodeID
-  ].join('');
-};
-
-/**
- * Returns whether or not the supplied semver tag is compatible
- * @param {String} version - The semver tag from the contact
- * @returns {Boolean} compatible
- */
-module.exports.isCompatibleVersion = function(version) {
-  var local = require('./version').protocol;
-  var remote = version;
-  var sameMajor = semver.major(local) === semver.major(remote);
-  var diffs = ['prerelease', 'prepatch', 'preminor', 'premajor'];
-
-  if (diffs.indexOf(semver.diff(remote, local)) !== -1) {
-    return false;
-  } else {
-    return sameMajor;
-  }
-};
-
-/**
- * Determines if the supplied contact is valid
- * @param {Contact} contact - The contact information for a given peer
- * @param {Boolean} loopback - Allows contacts that are localhost
- * @returns {Boolean}
- */
-module.exports.isValidContact = function(contact, loopback) {
-  if (!contact) {
-    return false;
-  }
-
-  var isValidAddr = ip.isV4Format(contact.address) ||
-                    ip.isV6Format(contact.address) ||
-                    ip.isPublic(contact.address);
-  var isValidPort = contact.port > 0;
-  var isAllowedAddr = ip.isLoopback(contact.address) ? !!loopback : true;
-
-  return isValidPort && isValidAddr && isAllowedAddr;
-};
-
-/**
- * Determines if a value is hexadecimal string
- * @param {*} a - The value to be tested
- * @returns {Boolean}
- */
-module.exports.isHexaString = function(a) {
-  if (typeof a !== 'string') {
-    return false;
-  }
-  return /^[0-9a-fA-F]+$/.test(a);
-};
-
-/**
- * Creates an ECIES ciper object from a private and a public key
- * @param {String} privateKey - The private key of the sender
- * @param {String} publicKey - The public key of the recipient
- * @returns {Object}
- */
-module.exports.createEciesCipher = function(privateKey, publicKey) {
-  var cipher = ECIES();
-
-  cipher.privateKey(KeyPair(privateKey)._privkey);
-  cipher.publicKey(bitcore.PublicKey.fromDER(Buffer(publicKey, 'hex')));
-
-  return cipher;
-};
-
-/**
- * Validates the logger object supplied
- * @private
- */
-module.exports.validateLogger = function(logger) {
-  return logger && logger.debug && logger.warn && logger.info && logger.error;
-};
-
-/**
- * Returns number of bytes from human readable size and unit strings
- * @param {String|Number} size - The size measurement
- * @param {String} unit - The unit of measure (MB|MiB|GB|GiB|TB|TiB)
- * @returns {Number}
- */
-module.exports.toNumberBytes = function(size, unit) {
-  /* eslint complexity: [2, 7] */
-  switch (unit.toUpperCase()) {
-    case 'MB':
-      size = Number(size) * Math.pow(1000, 2);
-      break;
-    case 'GB':
-      size = Number(size) * Math.pow(1000, 3);
-      break;
-    case 'TB':
-      size = Number(size) * Math.pow(1000, 4);
-      break;
-    case 'MIB':
-      size = Number(size) * Math.pow(1024, 2);
-      break;
-    case 'GIB':
-      size = Number(size) * Math.pow(1024, 3);
-      break;
-    case 'TIB':
-      size = Number(size) * Math.pow(1024, 4);
-      break;
-    default:
-      throw new Error('Unit must be one of TB, TiB, GB, GiB, MB or MiB');
-  }
-
-  return Number(size.toFixed());
-};
-
-/**
- * Encrypts the given data with the supplied password and base58 encodes it
- * @param {String} password - The passphrase to use for encryption
- * @param {String} data - The string to encrypt
- * @returns {String}
- */
-module.exports.simpleEncrypt = function(password, str) {
-  var aes256 = crypto.createCipher('aes-256-cbc', password);
-  var a = aes256.update(str, 'utf8');
-  var b = aes256.final();
-  var buf = new Buffer(a.length + b.length);
-
-  a.copy(buf, 0);
-  b.copy(buf, a.length);
-
-  return base58.encode(buf);
-};
-
-/**
- * Decrypts the given data with the supplied password and base58 decodes it
- * @param {String} password - The passphrase to use for decryption
- * @param {String} data - The string to decrypt
- * @returns {String}
- */
-module.exports.simpleDecrypt = function(password, str) {
-  var aes256 = crypto.createDecipher('aes-256-cbc', password);
-  var a = aes256.update(new Buffer(base58.decode(str)));
-  var b = aes256.final();
-  var buf = new Buffer(a.length + b.length);
-
-  a.copy(buf, 0);
-  b.copy(buf, a.length);
-
-  return buf.toString('utf8');
-};
-
-/**
- * Returns the delta between system time and NTP time
- * @param {Function} callback - Called with (err, delta)
- */
-module.exports.getNtpTimeDelta = function(callback) {
-  var timeBeforeRequest = new Date();
-
-  ntp.getNetworkTime(
-    ntp.defaultNtpServer,
-    ntp.defaultNtpPort,
-    function(err, networkTime) {
-      if (err) {
-        return callback(err);
-      }
-
-      var systemTime = Date.now();
-      var latency = parseInt((systemTime - timeBeforeRequest) / 2);
-      var delta = networkTime.getTime() - Math.abs(systemTime - latency);
-
-      callback(null, delta);
-    }
-  );
-};
-
-/**
- * Determines if the system clock is syncronized with network
- * @param {Function} callback - Called with (err, delta)
- */
-module.exports.ensureNtpClockIsSynchronized = function(callback) {
-  module.exports.getNtpTimeDelta(function(err, delta) {
-    if (err) {
-      return callback(err);
-    }
-
-    if (Math.abs(delta) > constants.NONCE_EXPIRE) {
-      return callback(new Error('System clock is not syncronized with NTP'));
-    }
-
-    callback(null, delta);
-  });
-};
-
-/**
- * Returns a through stream that trims the output based on the given range
- * @param {Number} trimFront - Number of bytes to trim off front of stream
- * @param {Number} totalBytes - The total length of the stream in bytes
- */
-module.exports.createStreamTrimmer = function(trimFront, totalBytes) {
-  var bytesTrimmedFront = 0;
-  var bytesRead = 0;
-
-  return through(function(data) {
-    if (trimFront - bytesTrimmedFront > data.length) {
-      bytesTrimmedFront += data.length;
-      bytesRead += 0;
-      this.queue(new Buffer([]));
-    } else if (trimFront > bytesTrimmedFront) {
-      var frontTrimmedSlice = data.slice(trimFront - bytesTrimmedFront);
-      bytesTrimmedFront += data.length;
-      bytesRead += frontTrimmedSlice.length;
-      this.queue(frontTrimmedSlice);
-    } else if (bytesRead < totalBytes) {
-      var backTrimmedSlice = data.slice(0, totalBytes - bytesRead);
-      bytesRead += backTrimmedSlice.length;
-      this.queue(backTrimmedSlice);
-    } else {
-      this.queue(null);
-    }
-  });
-};
-
-/**
- * Check if file exists
- * @param {String} file - Path to file
- * @returns {Boolean}
- */
-module.exports.existsSync = function(file) {
-  try {
-    fs.statSync(file);
-  } catch (err) {
-    return false;
-  }
-
-  return true;
-};
-
-/**
- * Check if a path is a directory
- * @param {String} dirPath - Path to a directory
- * @returns {Boolean}
- */
-module.exports.isDirectory = function(dirPath) {
-  try {
-    return fs.statSync(dirPath).isDirectory();
-  } catch (err) {
-    return false;
-  }
-};
-
-/**
- * Check for env STORJ_TEMP todetermine temp directory
- */
-module.exports.tmpdir = function() {
-  var tmpdir = process.env.STORJ_TEMP;
-
-  if (
-    !tmpdir ||
-    (typeof tmpdir === 'undefined') ||
-    !module.exports.existsSync(tmpdir)
-  ) {
-    tmpdir = os.tmpdir();
-  }
-
-  return tmpdir;
-};
-
-/**
- * Empty function stub
- * @private
- */
-module.exports.noop = function() {};
-
-/**
- * Calculate bucket id from a given user id and bucket name
- * @param {String} user - user id
- * @param {String} bucketName - bucket name
- */
-module.exports.calculateBucketId = function(user, bucketName) {
-  var rmd160sha256 = module.exports.rmd160sha256;
-  var hash = rmd160sha256(user + bucketName, 'utf-8');
-  return hash.substring(0, 24);
-};
-
-/**
- * Calculate file id from a given bucket id and file name
- * @param {String} bucket - bucket id
- * @param {String} fileName - file name
- */
-module.exports.calculateFileId = function(bucket, fileName) {
-  var rmd160sha256 = module.exports.rmd160sha256;
-  var hash = rmd160sha256(bucket + fileName, 'utf-8');
-  return hash.substring(0, 24);
-};
-
-/**
- * Calculate file id from a user id, bucket name, and file name
- * @param {String} user - user id
- * @param {String} bucketName - bucket name
- * @param {String} fileName - file name
- */
-module.exports.calculateFileIdByName = function(user, bucketName, fileName) {
-  var bucket = module.exports.calculateBucketId(user, bucketName);
-  var hash = module.exports.calculateFileId(bucket, fileName);
-  return hash;
-};
-
-/**
- * Checks if the supplied HD key is valid (base58 encoded) and proper length
- * @param {String} hdKey - The HD key in base 58 encoding
- * @returns {Boolean} isValidHDKey
- */
-module.exports.isValidHDNodeKey = function(hdKey) {
-  return typeof hdKey === 'string' &&
-    /^[1-9a-km-zA-HJ-NP-Z]{1,111}$/.test(hdKey);
-};
-
-/**
- * Checks if the input is a non-hardened HD key index
- * @param {Number} hdIndex - The HD key index
- * @returns {Boolean} isValidHDKeyIndex
- */
-module.exports.isValidNodeIndex = function(n) {
-  return !Number.isNaN(n) && (parseInt(n) === n) && n >= 0 &&
-    n <= constants.MAX_NODE_INDEX;
-};
-
-/**
- * Returns a HD key object using corrent key derivation path using the
- * given seed
- * @see https://github.com/Storj/complex
- * @param {Buffer} seed64 - 64 byte seed for generating key
- * @returns {HDKey}
- */
-module.exports.createComplexKeyFromSeed = function(seed64) {
-  assert(Buffer.isBuffer(seed64), 'Seed must be a buffer');
-  assert(seed64.length === 64, 'Seed must be 64 bytes in length');
-
-  var hdKey = HDKey.fromMasterSeed(seed64).derive(
-    constants.HD_KEY_DERIVATION_PATH
-  );
-
-  return hdKey.privateExtendedKey;
-};
-
-/**
- * Returns a request object for uploading a shard to a farmer
- * @param {Contact} farmer - Farmer contact object
- * @param {String} shardHash - The hash of the shard to upload
- * @param {String} transferToken - The authorized transfer token
- * @returns {http.ClientRequest}
- */
-module.exports.createShardUploader = function(farmer, hash, token) {
-  function _createUploadStream() {
-    return http.request({
-      method: 'POST',
-      protocol: 'http:',
-      hostname: farmer.address,
-      port: farmer.port,
-      path: `/shards/${hash}?token=${token}`,
-      headers: {
-        'content-type': 'application/octet-stream',
-        'x-storj-node-id': farmer.nodeID
-      }
-    });
-  }
-
-  return new stream.Transform({
-    transform: function(chunk, encoding, callback) {
-      if (!this._uploader) {
-        this._uploader = _createUploadStream();
-        this._uploader.on('response', this.emit.bind(this, 'response'));
-        this._uploader.on('error', (err) => {
-          this.unpipe();
-          this.emit('error', err);
-        });
-      }
-
-      this._uploader.write(chunk, encoding, callback);
-    },
-    flush: function(callback) {
-      if (this._uploader) {
-        this._uploader.end();
-      }
-      callback();
-    }
-  });
-};
-
-/**
- * Returns a request object for downloading a shard from a farmer
- * @param {Contact} farmer - Farmer contact object
- * @param {String} shardHash - The hash of the shard to upload
- * @param {String} transferToken - The authorized transfer token
- * @returns {http.ClientRequest}
- */
-module.exports.createShardDownloader = function(farmer, hash, token) {
-  function _createDownloadStream() {
-    return http.get({
-      protocol: 'http:',
-      hostname: farmer.address,
-      port: farmer.port,
-      path: `/shards/${hash}?token=${token}`,
-      headers: {
-        'content-type': 'application/octet-stream',
-        'x-storj-node-id': farmer.nodeID
-      }
-    });
-  }
-
-  return new stream.Readable({
-    read: function() {
-      if (!this._downloader) {
-        this._downloader = _createDownloadStream();
-        this._downloader.on('response', (res) => {
-          res
-            .on('data', this.push.bind(this))
-            .on('error', this.emit.bind(this, 'error'))
-            .on('end', this.push.bind(this, null));
-        })
-        .on('error', this.emit.bind(this, 'error'));
-      }
-    }
-  });
-};
-
-/**
- * Helper for passing an error only logger callback
- * @param {Logger} logger - Logger object
- * @returns {Function}
- */
-module.exports.warnOnError = function(logger) {
-  return function(err) {
-    if (err) {
-      logger.warn(err.message);
-    }
-  };
-};
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/lib_version.js.html b/Storj/core/docs/lib_version.js.html deleted file mode 100644 index 0b9aab7..0000000 --- a/Storj/core/docs/lib_version.js.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - JSDoc: Source: lib/version.js - - - - - - - - - - -
- -

Source: lib/version.js

- - - - - - -
-
-
/**
- * @module storj/version
- */
-
-'use strict';
-
-var semver = require('semver');
-var assert = require('assert');
-var postfix = process.env.STORJ_NETWORK ? '-' + process.env.STORJ_NETWORK : '';
-
-module.exports = {
-  /** @constant {String} protocol - The supported protocol version */
-  protocol: '1.1.0' + postfix,
-  /** @constant {String} software - The current software version */
-  software: require('../package').version
-};
-
-assert(
-  semver.valid(module.exports.protocol),
-  'Invalid protocol version specified'
-);
-
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - diff --git a/Storj/core/docs/module-storj.html b/Storj/core/docs/module-storj.html deleted file mode 100644 index ec1ac1c..0000000 --- a/Storj/core/docs/module-storj.html +++ /dev/null @@ -1,2197 +0,0 @@ - - - - - JSDoc: Module: storj - - - - - - - - - - -
- -

Module: storj

- - - - - - -
- -
- - - -
- -
-
- - - - - -
- - - - - - - - - - - - - - -

Members

- - - -

(static) AuditStream

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) BridgeClient

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) constants

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) Contact

- - - - -
- Contact -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) Contract

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) DataCipherKeyIv

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) DecryptStream

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) deps

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) DeterministicKeyIv

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) EmbeddedStorageAdapter

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) EncryptStream

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) Farmer

- - - - -
- Farmer -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) FileDemuxer

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) FileMuxer

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) KeyPair

- - - - -
- KeyPair -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) KeyRing

- - - - -
- KeyRing -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) Monitor

- - - - -
- Monitor -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) Network

- - - - -
- Network -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) OfferManager

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) OfferStream

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) ProofStream

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) Protocol

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) RAMStorageAdapter

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) Renter

- - - - -
- Renter -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) ShardServer

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) sips

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) StorageAdapter

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) StorageItem

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) StorageManager

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) StorageMigration

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) Transport

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) utils

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) Verification

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(static) version

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/module-storj_constants.html b/Storj/core/docs/module-storj_constants.html deleted file mode 100644 index 25a2a2a..0000000 --- a/Storj/core/docs/module-storj_constants.html +++ /dev/null @@ -1,1919 +0,0 @@ - - - - - JSDoc: Module: storj/constants - - - - - - - - - - -
- -

Module: storj/constants

- - - - - - -
- -
- - - -
- -
-
- - - - - -
- - - - - - - - - - - - - - -

Members

- - - -

(inner, constant) AUDIT_BYTES :Number

- - - - -
- Number of bytes for audit challenge -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) CIPHER_ALG :String

- - - - -
- Cipher/Decipher algorithm -
- - - -
Type:
-
    -
  • - -String - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) CLEAN_INTERVAL :Number

- - - - -
- Interval for reaping stale shards -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) CONSIGN_THRESHOLD :Number

- - - - -
- Threshold for consign time -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) HD_KEY_DERIVATION_PATH

- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) MAX_CONCURRENT_AUDITS :Number

- - - - -
- Number of concurrent audits -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) MAX_CONCURRENT_OFFERS :Number

- - - - -
- Number of concurrent offers -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) MAX_FIND_TUNNEL_RELAYS

- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) MAX_NODE_INDEX

- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) NET_REENTRY :Number

- - - - -
- Max wait time before re-entering net -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) NONCE_EXPIRE :Number

- - - - -
- Time to honor a signed message -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) OFFER_TIMEOUT :Number

- - - - -
- Max wait time for storage offer -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) OPCODE_CONTRACT_PREFIX :Number

- - - - -
- Prefix opcode for contracts -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) OPCODE_DEG_HIGH :Number

- - - - -
- Opcode for medium criteria degree -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) OPCODE_DEG_LOW :Number

- - - - -
- Opcode for low criteria degree -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) OPCODE_DEG_MED :Number

- - - - -
- Opcode for medium criteria degree -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) OPCODE_DEG_NULL :Number

- - - - -
- Opcode for null criteria degree -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) OPCODE_TUNDCX_PREFIX :Number

- - - - -
- Opcode for tunnel datachannel -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) OPCODE_TUNNELER_PREFIX :Number

- - - - -
- Prefix opcode for tunneler -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) OPCODE_TUNRPC_PREFIX :Number

- - - - -
- Opcode for tunnel rpc message -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) PREFIX :Number

- - - - -
- NodeID prefix (same as bitcoin) -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) PUBLISH_TTL :Number

- - - - -
- Max time for publication relay -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) ROUTER_CLEAN_INTERVAL :Number

- - - - -
- Drop bad contacts -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) RPC_TIMEOUT :Number

- - - - -
- Max wait time for a RPC response -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) TOKEN_EXPIRE :Number

- - - - -
- Reject datachannl token after time -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) TUNNEL_ANNOUNCE_INTERVAL :Number

- - - - -
- Announce tunnel state -
- - - -
Type:
-
    -
  • - -Number - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/module-storj_deps.html b/Storj/core/docs/module-storj_deps.html deleted file mode 100644 index bf472e6..0000000 --- a/Storj/core/docs/module-storj_deps.html +++ /dev/null @@ -1,296 +0,0 @@ - - - - - JSDoc: Module: storj/deps - - - - - - - - - - -
- -

Module: storj/deps

- - - - - - -
- -
- - - -
- -
-
- - - - - -
- - - - - - - - - - - - - - -

Members

- - - -

(static) bitcore

- - - - -
- A modular node for Bitcoin and blockchain-based apps -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - -
See:
-
- -
- - - -
- - - - - - - - -

(static) kad

- - - - -
- Implementation of the Kademlia distributed hash table -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - -
See:
-
- -
- - - -
- - - - - - - - -

(static) kfs

- - - - -
- Kademlia inspired local file store based on LevelDB -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - -
See:
-
- -
- - - -
- - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/module-storj_patches.html b/Storj/core/docs/module-storj_patches.html deleted file mode 100644 index ba49daf..0000000 --- a/Storj/core/docs/module-storj_patches.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - JSDoc: Module: storj/patches - - - - - - - - - - -
- -

Module: storj/patches

- - - - - - -
- -
- - - -
- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/module-storj_sips.html b/Storj/core/docs/module-storj_sips.html deleted file mode 100644 index 30b918e..0000000 --- a/Storj/core/docs/module-storj_sips.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - JSDoc: Module: storj/sips - - - - - - - - - - -
- -

Module: storj/sips

- - - - - - -
- -
- - - -
- -
-
- - - - - -
- - - - - - - - - - - - - - -

Members

- - - -

(static) SIP0003

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/module-storj_sips_0003.html b/Storj/core/docs/module-storj_sips_0003.html deleted file mode 100644 index aeac5ba..0000000 --- a/Storj/core/docs/module-storj_sips_0003.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - JSDoc: Module: storj/sips/0003 - - - - - - - - - - -
- -

Module: storj/sips/0003

- - - - - - -
- -
- - - -
- -
-
- - - - - -
- - - - - - - - - - - - - - -

Members

- - - -

(static) TriggerManager

- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/module-storj_utils.html b/Storj/core/docs/module-storj_utils.html deleted file mode 100644 index 8ee540c..0000000 --- a/Storj/core/docs/module-storj_utils.html +++ /dev/null @@ -1,5990 +0,0 @@ - - - - - JSDoc: Module: storj/utils - - - - - - - - - - -
- -

Module: storj/utils

- - - - - - -
- -
- - - -
- -
-
- - - - - -
- - - - - - - - - - - - - - - - -

Methods

- - - - - - - -

(static) calculateBucketId(user, bucketName)

- - - - - - -
- Calculate bucket id from a given user id and bucket name -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
user - - -String - - - - user id
bucketName - - -String - - - - bucket name
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(static) calculateFileId(bucket, fileName)

- - - - - - -
- Calculate file id from a given bucket id and file name -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bucket - - -String - - - - bucket id
fileName - - -String - - - - file name
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(static) calculateFileIdByName(user, bucketName, fileName)

- - - - - - -
- Calculate file id from a user id, bucket name, and file name -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
user - - -String - - - - user id
bucketName - - -String - - - - bucket name
fileName - - -String - - - - file name
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(static) createComplexKeyFromSeed(seed64) → {HDKey}

- - - - - - -
- Returns a HD key object using corrent key derivation path using the -given seed -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
seed64 - - -Buffer - - - - 64 byte seed for generating key
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - -
See:
-
- -
- - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -HDKey - - -
-
- - - - - - - - - - - - - -

(static) createEciesCipher(privateKey, publicKey) → {Object}

- - - - - - -
- Creates an ECIES ciper object from a private and a public key -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
privateKey - - -String - - - - The private key of the sender
publicKey - - -String - - - - The public key of the recipient
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Object - - -
-
- - - - - - - - - - - - - -

(static) createShardDownloader(farmer, shardHash, transferToken) → {http.ClientRequest}

- - - - - - -
- Returns a request object for downloading a shard from a farmer -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
farmer - - -Contact - - - - Farmer contact object
shardHash - - -String - - - - The hash of the shard to upload
transferToken - - -String - - - - The authorized transfer token
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -http.ClientRequest - - -
-
- - - - - - - - - - - - - -

(static) createShardUploader(farmer, shardHash, transferToken) → {http.ClientRequest}

- - - - - - -
- Returns a request object for uploading a shard to a farmer -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
farmer - - -Contact - - - - Farmer contact object
shardHash - - -String - - - - The hash of the shard to upload
transferToken - - -String - - - - The authorized transfer token
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -http.ClientRequest - - -
-
- - - - - - - - - - - - - -

(static) createStreamTrimmer(trimFront, totalBytes)

- - - - - - -
- Returns a through stream that trims the output based on the given range -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
trimFront - - -Number - - - - Number of bytes to trim off front of stream
totalBytes - - -Number - - - - The total length of the stream in bytes
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(static) ensureNtpClockIsSynchronized(callback)

- - - - - - -
- Determines if the system clock is syncronized with network -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called with (err, delta)
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(static) existsSync(file) → {Boolean}

- - - - - - -
- Check if file exists -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
file - - -String - - - - Path to file
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

(static) generateToken() → {String}

- - - - - - -
- Generates a unique token -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

(static) getContactURL(contact) → {String}

- - - - - - -
- Returns a stringified URL from the supplied contact object -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Object - - - - -
Properties
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
address - - -String - - - -
port - - -Number - - - -
nodeID - - -String - - - -
- -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

(static) getNextPowerOfTwo(number) → {Number}

- - - - - - -
- Returns the next power of two number -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
number - - -Number - - - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Number - - -
-
- - - - - - - - - - - - - -

(static) getNtpTimeDelta(callback)

- - - - - - -
- Returns the delta between system time and NTP time -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -function - - - - Called with (err, delta)
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(static) isCompatibleVersion(version) → {Boolean}

- - - - - - -
- Returns whether or not the supplied semver tag is compatible -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
version - - -String - - - - The semver tag from the contact
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- compatible -
- - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

(static) isDirectory(dirPath) → {Boolean}

- - - - - - -
- Check if a path is a directory -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
dirPath - - -String - - - - Path to a directory
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

(static) isHexaString(a) → {Boolean}

- - - - - - -
- Determines if a value is hexadecimal string -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
a - - -* - - - - The value to be tested
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

(static) isValidContact(contact, loopback) → {Boolean}

- - - - - - -
- Determines if the supplied contact is valid -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
contact - - -Contact - - - - The contact information for a given peer
loopback - - -Boolean - - - - Allows contacts that are localhost
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

(static) isValidHDNodeKey(hdKey) → {Boolean}

- - - - - - -
- Checks if the supplied HD key is valid (base58 encoded) and proper length -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
hdKey - - -String - - - - The HD key in base 58 encoding
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- isValidHDKey -
- - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

(static) isValidNodeIndex(hdIndex) → {Boolean}

- - - - - - -
- Checks if the input is a non-hardened HD key index -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
hdIndex - - -Number - - - - The HD key index
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- isValidHDKeyIndex -
- - - -
-
- Type -
-
- -Boolean - - -
-
- - - - - - - - - - - - - -

(static) rmd160(input, encoding) → {String}

- - - - - - -
- Returns the RIPEMD-160 hash of the input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -String -| - -Buffer - - - - Data to hash
encoding - - -String - - - - The encoding type of the data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

(static) rmd160b(input, encoding) → {Buffer}

- - - - - - -
- Returns the RIPEMD-160 hash of the input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -String -| - -Buffer - - - - Data to hash
encoding - - -String - - - - The encoding type of the data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Buffer - - -
-
- - - - - - - - - - - - - -

(static) rmd160sha256(input, encoding) → {String}

- - - - - - -
- Returns the RIPEMD-160 SHA-256 hash of this input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -String -| - -Buffer - - - - Data to hash
encoding - - -String - - - - The encoding type of the data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

(static) rmd160sha256b(input, encoding) → {Buffer}

- - - - - - -
- Returns the RIPEMD-160 SHA-256 hash of this input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -String -| - -Buffer - - - - Data to hash
encoding - - -String - - - - The encoding type of the data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Buffer - - -
-
- - - - - - - - - - - - - -

(static) sha1(input, encoding) → {String}

- - - - - - -
- Returns the SHA-1 hash of the input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -String -| - -Buffer - - - - Data to hash
encoding - - -String - - - - The encoding type of the data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

(static) sha1whirlpool(input, encoding) → {String}

- - - - - - -
- Returns the SHA-1 WHIRLPOOL hash of this input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -String -| - -Buffer - - - - Data to hash
encoding - - -String - - - - The encoding type of the data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

(static) sha256(input, encoding) → {String}

- - - - - - -
- Returns the SHA-256 hash of the input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -String -| - -Buffer - - - - Data to hash
encoding - - -String - - - - The encoding type of the data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

(static) sha256b(input, encoding) → {Buffer}

- - - - - - -
- Returns the SHA-256 hash of the input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -String -| - -Buffer - - - - Data to hash
encoding - - -String - - - - The encoding type of the data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Buffer - - -
-
- - - - - - - - - - - - - -

(static) sha512(input, encoding) → {String}

- - - - - - -
- Returns the SHA-512 hash of the input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -String -| - -Buffer - - - - Data to hash
encoding - - -String - - - - The encoding type of the data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

(static) simpleDecrypt(password, data) → {String}

- - - - - - -
- Decrypts the given data with the supplied password and base58 decodes it -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
password - - -String - - - - The passphrase to use for decryption
data - - -String - - - - The string to decrypt
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

(static) simpleEncrypt(password, data) → {String}

- - - - - - -
- Encrypts the given data with the supplied password and base58 encodes it -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
password - - -String - - - - The passphrase to use for encryption
data - - -String - - - - The string to encrypt
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -

(static) tmpdir()

- - - - - - -
- Check for env STORJ_TEMP todetermine temp directory -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(static) toNumberBytes(size, unit) → {Number}

- - - - - - -
- Returns number of bytes from human readable size and unit strings -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
size - - -String -| - -Number - - - - The size measurement
unit - - -String - - - - The unit of measure (MB|MiB|GB|GiB|TB|TiB)
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -Number - - -
-
- - - - - - - - - - - - - -

(static) warnOnError(logger) → {function}

- - - - - - -
- Helper for passing an error only logger callback -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
logger - - -Logger - - - - Logger object
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -function - - -
-
- - - - - - - - - - - - - -

(static) whirlpool(input, encoding) → {String}

- - - - - - -
- Returns the WHIRLPOOL hash of the input -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -String -| - -Buffer - - - - Data to hash
encoding - - -String - - - - The encoding type of the data
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - - - -
-
- Type -
-
- -String - - -
-
- - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/module-storj_version.html b/Storj/core/docs/module-storj_version.html deleted file mode 100644 index 7bb39ff..0000000 --- a/Storj/core/docs/module-storj_version.html +++ /dev/null @@ -1,233 +0,0 @@ - - - - - JSDoc: Module: storj/version - - - - - - - - - - -
- -

Module: storj/version

- - - - - - -
- -
- - - -
- -
-
- - - - - -
- - - - - - - - - - - - - - -

Members

- - - -

(inner, constant) protocol :String

- - - - -
- The supported protocol version -
- - - -
Type:
-
    -
  • - -String - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(inner, constant) software :String

- - - - -
- The current software version -
- - - -
Type:
-
    -
  • - -String - - -
  • -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/scripts/linenumber.js b/Storj/core/docs/scripts/linenumber.js deleted file mode 100644 index 4354785..0000000 --- a/Storj/core/docs/scripts/linenumber.js +++ /dev/null @@ -1,25 +0,0 @@ -/*global document */ -(() => { - const source = document.getElementsByClassName('prettyprint source linenums'); - let i = 0; - let lineNumber = 0; - let lineId; - let lines; - let totalLines; - let anchorHash; - - if (source && source[0]) { - anchorHash = document.location.hash.substring(1); - lines = source[0].getElementsByTagName('li'); - totalLines = lines.length; - - for (; i < totalLines; i++) { - lineNumber++; - lineId = `line${lineNumber}`; - lines[i].id = lineId; - if (lineId === anchorHash) { - lines[i].className += ' selected'; - } - } - } -})(); diff --git a/Storj/core/docs/scripts/prettify/Apache-License-2.0.txt b/Storj/core/docs/scripts/prettify/Apache-License-2.0.txt deleted file mode 100644 index d645695..0000000 --- a/Storj/core/docs/scripts/prettify/Apache-License-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/Storj/core/docs/scripts/prettify/lang-css.js b/Storj/core/docs/scripts/prettify/lang-css.js deleted file mode 100644 index 041e1f5..0000000 --- a/Storj/core/docs/scripts/prettify/lang-css.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", -/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/Storj/core/docs/scripts/prettify/prettify.js b/Storj/core/docs/scripts/prettify/prettify.js deleted file mode 100644 index eef5ad7..0000000 --- a/Storj/core/docs/scripts/prettify/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p th:last-child { border-right: 1px solid #ddd; } - -.ancestors, .attribs { color: #999; } -.ancestors a, .attribs a -{ - color: #999 !important; - text-decoration: none; -} - -.clear -{ - clear: both; -} - -.important -{ - font-weight: bold; - color: #950B02; -} - -.yes-def { - text-indent: -1000px; -} - -.type-signature { - color: #aaa; -} - -.name, .signature { - font-family: Consolas, Monaco, 'Andale Mono', monospace; -} - -.details { margin-top: 14px; border-left: 2px solid #DDD; } -.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; } -.details dd { margin-left: 70px; } -.details ul { margin: 0; } -.details ul { list-style-type: none; } -.details li { margin-left: 30px; padding-top: 6px; } -.details pre.prettyprint { margin: 0 } -.details .object-value { padding-top: 0; } - -.description { - margin-bottom: 1em; - margin-top: 1em; -} - -.code-caption -{ - font-style: italic; - font-size: 107%; - margin: 0; -} - -.source -{ - border: 1px solid #ddd; - width: 80%; - overflow: auto; -} - -.prettyprint.source { - width: inherit; -} - -.source code -{ - font-size: 100%; - line-height: 18px; - display: block; - padding: 4px 12px; - margin: 0; - background-color: #fff; - color: #4D4E53; -} - -.prettyprint code span.line -{ - display: inline-block; -} - -.prettyprint.linenums -{ - padding-left: 70px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.prettyprint.linenums ol -{ - padding-left: 0; -} - -.prettyprint.linenums li -{ - border-left: 3px #ddd solid; -} - -.prettyprint.linenums li.selected, -.prettyprint.linenums li.selected * -{ - background-color: lightyellow; -} - -.prettyprint.linenums li * -{ - -webkit-user-select: text; - -moz-user-select: text; - -ms-user-select: text; - user-select: text; -} - -.params .name, .props .name, .name code { - color: #4D4E53; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - font-size: 100%; -} - -.params td.description > p:first-child, -.props td.description > p:first-child -{ - margin-top: 0; - padding-top: 0; -} - -.params td.description > p:last-child, -.props td.description > p:last-child -{ - margin-bottom: 0; - padding-bottom: 0; -} - -.disabled { - color: #454545; -} diff --git a/Storj/core/docs/styles/prettify-jsdoc.css b/Storj/core/docs/styles/prettify-jsdoc.css deleted file mode 100644 index 5a2526e..0000000 --- a/Storj/core/docs/styles/prettify-jsdoc.css +++ /dev/null @@ -1,111 +0,0 @@ -/* JSDoc prettify.js theme */ - -/* plain text */ -.pln { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* string content */ -.str { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a keyword */ -.kwd { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a comment */ -.com { - font-weight: normal; - font-style: italic; -} - -/* a type name */ -.typ { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* a literal value */ -.lit { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* punctuation */ -.pun { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* lisp open bracket */ -.opn { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* lisp close bracket */ -.clo { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a markup tag name */ -.tag { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a markup attribute name */ -.atn { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a markup attribute value */ -.atv { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a declaration */ -.dec { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a variable name */ -.var { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* a function name */ -.fun { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* Specify class=linenums on a pre to get line numbering */ -ol.linenums { - margin-top: 0; - margin-bottom: 0; -} diff --git a/Storj/core/docs/styles/prettify-tomorrow.css b/Storj/core/docs/styles/prettify-tomorrow.css deleted file mode 100644 index b6f92a7..0000000 --- a/Storj/core/docs/styles/prettify-tomorrow.css +++ /dev/null @@ -1,132 +0,0 @@ -/* Tomorrow Theme */ -/* Original theme - https://github.com/chriskempson/tomorrow-theme */ -/* Pretty printing styles. Used with prettify.js. */ -/* SPAN elements with the classes below are added by prettyprint. */ -/* plain text */ -.pln { - color: #4d4d4c; } - -@media screen { - /* string content */ - .str { - color: #718c00; } - - /* a keyword */ - .kwd { - color: #8959a8; } - - /* a comment */ - .com { - color: #8e908c; } - - /* a type name */ - .typ { - color: #4271ae; } - - /* a literal value */ - .lit { - color: #f5871f; } - - /* punctuation */ - .pun { - color: #4d4d4c; } - - /* lisp open bracket */ - .opn { - color: #4d4d4c; } - - /* lisp close bracket */ - .clo { - color: #4d4d4c; } - - /* a markup tag name */ - .tag { - color: #c82829; } - - /* a markup attribute name */ - .atn { - color: #f5871f; } - - /* a markup attribute value */ - .atv { - color: #3e999f; } - - /* a declaration */ - .dec { - color: #f5871f; } - - /* a variable name */ - .var { - color: #c82829; } - - /* a function name */ - .fun { - color: #4271ae; } } -/* Use higher contrast and text-weight for printable form. */ -@media print, projection { - .str { - color: #060; } - - .kwd { - color: #006; - font-weight: bold; } - - .com { - color: #600; - font-style: italic; } - - .typ { - color: #404; - font-weight: bold; } - - .lit { - color: #044; } - - .pun, .opn, .clo { - color: #440; } - - .tag { - color: #006; - font-weight: bold; } - - .atn { - color: #404; } - - .atv { - color: #060; } } -/* Style */ -/* -pre.prettyprint { - background: white; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - font-size: 12px; - line-height: 1.5; - border: 1px solid #ccc; - padding: 10px; } -*/ - -/* Specify class=linenums on a pre to get line numbering */ -ol.linenums { - margin-top: 0; - margin-bottom: 0; } - -/* IE indents via margin-left */ -li.L0, -li.L1, -li.L2, -li.L3, -li.L4, -li.L5, -li.L6, -li.L7, -li.L8, -li.L9 { - /* */ } - -/* Alternate shading for lines */ -li.L1, -li.L3, -li.L5, -li.L7, -li.L9 { - /* */ } diff --git a/Storj/core/docs/tutorial-command-line-interface.html b/Storj/core/docs/tutorial-command-line-interface.html deleted file mode 100644 index d8a5f33..0000000 --- a/Storj/core/docs/tutorial-command-line-interface.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - - JSDoc: Tutorial: Using the Command Line Tools - - - - - - - - - - -
- -

Tutorial: Using the Command Line Tools

- -
- -
- - -

Using the Command Line Tools

-
- -
-

This package comes equipped with a command line interface for performing a -number of useful operations on the Storj network. The CLI program is generally -focused on interacting with a remote Bridge -service and makes use of the library's BridgeClient class to do so. In -addition to interacting with a bridge node, the tool also exposes some general -purpose utilities.

-

To use the CLI, follow the instructions in the README to install the module -globally or if you are working from within the git repository, you can use:

-
npm link
-
-

Communicating with a Bridge

-

Once you have access to the storj command, register and authenticate with the -bridge:

-
> $ storj register
- [...]  > Enter your email address  >  gordon@storj.io
- [...]  > Enter your password  >  *************
-
- [info]   Registered! Check your email to activate your account.
-
-

Follow the activation link you receive via email and come back to the CLI to -pair with your account:

-
> $ storj login
- [...]  > Enter your email address  >  gordon@storj.io
- [...]  > Enter your password  >  *************
-
- [info]   This device has been successfully paired.
-
-

Now you can create buckets, transfer files, and manage your bridge account.

-

Audits, Proofs, and Verifications

-

The CLI also includes some utility commands for generating file possession -audits, proving possession, and verifying proofs. You can generate a challenge -set and merkle tree for a file easily:

-
> $ storj prepare-audits 2 CONTRIBUTING.md
- [info]   Generating challenges and merkle tree...
- [info]
- [info]   Merkle Root
- [info]   -----------
- [info]   9c8c37935f58d46e3301efe4f44724b8785a81a5
- [info]
- [info]   Challenges
- [info]   ----------
- [info]   c8573773616e072230d40131e7ce8537d384825e337e5903ff7367ddea798c52
- [info]   7c4d4f57f40d5c95f962e7cd72347e4077e1885aaffd8c1ccbbd02c8d7c48dce
- [info]
- [info]   Merkle Leaves
- [info]   -------------
- [info]   aaf42766d87a37e6dffbae7172fd0073006bf5f3
- [info]   ccee086dbc8a16b93b79912cb37f3b037bbf8269
-
-

A farmer can use parts of this data to prove possession of a file shard:

-
> $ storj prove-file aaf42766d87a37e6dffbae7172fd0073006bf5f3,ccee086dbc8a16b93b79912cb37f3b037bbf8269 c8573773616e072230d40131e7ce8537d384825e337e5903ff7367ddea798c52 CONTRIBUTING.md
- [info]   Generating proof of possession...
- [info]
- [info]   Challenge Response
- [info]   ------------------
- [info]   [["153a0d4b1d228043992fec585cadb51974b053f7"],"ccee086dbc8a16b93b79912cb37f3b037bbf8269"]
-
-

The result of this operation can be used by the original renter to verify the -the proof and confirm that the farmer still has possession of the file:

-
> $ storj verify-proof 9c8c37935f58d46e3301efe4f44724b8785a81a5 2 '[["153a0d4b1d228043992fec585cadb51974b053f7"],"ccee086dbc8a16b93b79912cb37f3b037bbf8269"]'
- [info]
- [info]   Expected: 9c8c37935f58d46e3301efe4f44724b8785a81a5
- [info]   Actual:   9c8c37935f58d46e3301efe4f44724b8785a81a5
- [info]
- [info]   The proof response is valid
-
-

For more detailed usage information of the command line interface, run -storj --help.

-

Temporary Files

-

On Windows temporary files are stored:

-
C:\Users\<user>\AppData\Local\Temp
-
-
- -
- -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/tutorial-contract-topics.html b/Storj/core/docs/tutorial-contract-topics.html deleted file mode 100644 index a82d84b..0000000 --- a/Storj/core/docs/tutorial-contract-topics.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - JSDoc: Tutorial: Publishing Storage Contracts - - - - - - - - - - -
- -

Tutorial: Publishing Storage Contracts

- -
- -
- - -

Publishing Storage Contracts

-
- -
-

Nodes solicit storage contracts with the network by publishing information -about their storage requirements as outlined in Protocol Specification. -Storj implements a distributed publish/subscribe system based on an algorithm -called Quasar.

-

Quasar works by allowing nodes to advertise topics of interest to their -neighbors and keeping a record of these topics in their neighborhood by storing -them in an attenuated bloom filter. Each node has a view of the topics in which -their neighbors are interested up to 3 hops away. By the nature of this -design, the network forms gravity wells wherein messages of interest are -efficiently relayed to nodes that are subscribed to the topic without flooding -the network.

-

This approach works well when there is a diverse number of topics. The Storj -protocol leverages this by defining a matrix of criteria and descriptors -in the form of opcodes representing the degree of which the criteria must be -met.

-

Criteria

-

At the time of writing, there are 4 criteria column in the topic matrix:

-
    -
  • Size
  • -
  • Duration
  • -
  • Availability
  • -
  • Speed
  • -
-

Size

-

Refers to the size of the data to be stored.

-

Duration

-

Refers to the length of time for which the data should be stored.

-

Availability

-

Refers to the relative uptime of required by the contract for retrieval of the -stored data.

-

Speed

-

Refers to the throughput desired for retrieval of the stored data.

-

Descriptors

-

At the time of writing, there are 3 descriptor opcodes representing low, -medium, and high degrees of the criteria.

-
    -
  • Low: 0x01
  • -
  • Medium: 0x02
  • -
  • High: 0x03
  • -
-

The ranges represented by these descriptors are advisory and may change based -on network performance and improvements to hardware over time.

-
-------------------------------------------------------------------------------
-| Descriptor      | Size        | Duration   | Availability | Speed           |
-|-----------------|-------------|------------|--------------|-----------------|
-| Low    (`0x01`) | 0mb - 8mb   | 0d - 30d   | 0% - 50%     | 0mbps - 6mbps   |
-|-----------------|-------------|------------|--------------|-----------------|
-| Medium (`0x02`) | 8mb - 16mb  | 30d - 90d  | 50% - 80%    | 6mbps - 12mbps  |
-|-----------------|-------------|------------|--------------|-----------------|
-| High   (`0x03`) | 16mb - 32mb | 90d - 270d | 80% - 99%    | 12mbps - 32mbps |
--------------------------------------------------------------------------------
-
-

Topic Format

-

When publishing or subscribing to a given topic representing the degrees of -these criteria, nodes must serialize the opcodes as the hex representation of -the bytes in proper sequence. This sequence is defined as:

-
prefix|size|duration|availability|speed
-
-

The first byte, "prefix", is the static identifier for a contract -publication. Contracts are not the only type of publication shared in the -network, so the prefix acts as a namespace for a type of publication topic.

-

The prefix for a contract publication is: 0x0f.

-

To illustrate by example, we can determine the proper topic by analyzing the -use case for a given file shard. For instance, if we want to store an asset -that is displayed on a web page we can infer the following:

-
    -
  • The file is small
  • -
  • The file may change often, so we should only store it for medium duration
  • -
  • The file needs to always be available
  • -
  • The file should be transferred quickly
  • -
-

Using the matrix, we can determine the proper opcode sequence:

-
[0x0f, 0x01, 0x02, 0x03, 0x03]
-
-

Serialized as hex, our topic string becomes:

-
0f01020303
-
-

Another example, by contrast, is data backup. Data backup is quite different -than the previous example:

-
    -
  • The file is large (perhaps part of a hard drive backup)
  • -
  • The file will not change and should be stored long term
  • -
  • The file will not be accessed often, if ever
  • -
  • The file does not need to be transferred at high speed
  • -
-

Using the matrix, we can determine the proper opcode sequence:

-
[0x0f, 0x03, 0x03, 0x01, 0x01]
-
-

Serialized as hex, our topic string becomes:

-
0f03030101
-
-

The resulting hex string from the serialized opcode byte sequence should be -used as the topic parameter of a PUBLISH RPC as defined in the -Protocol Specification. Nodes that are subscribed to the topic will receive -the proposed storage contract and may begin contract negotiation with you -directly.

-
- -
- -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/tutorial-data-transfer.html b/Storj/core/docs/tutorial-data-transfer.html deleted file mode 100644 index 1156973..0000000 --- a/Storj/core/docs/tutorial-data-transfer.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - JSDoc: Tutorial: Transferring File Shards - - - - - - - - - - -
- -

Tutorial: Transferring File Shards

- -
- -
- - -

Transferring File Shards

-
- -
-

Transfering file shards to farmers is a simple process. After a successful -CONSIGN or RETRIEVE RPC yields a token, the renter may construct an HTTP -request to the farmer, to push or pull the data.

-

Uploading Shards

-

To upload a shard to a given farmer, construct an HTTP request:

-
    -
  • Method: POST
  • -
  • Path: /shards/{hash}?token={token}
  • -
  • Headers: -
      -
    • content-type: application/octet-stream
    • -
    • x-storj-node-id: {farmer node id}
    • -
    -
  • -
-

Then simply write the encrypted shard to the request. Farmers will respond with -appropriate status codes and messages to indicate the result.

-

Downloading Shards

-

To download a shard from a given farmer, construct an HTTP request:

-
    -
  • Method: GET
  • -
  • Path: /shards/{hash}?token={token}
  • -
  • Headers: -
      -
    • content-type: application/octet-stream
    • -
    • x-storj-node-id: {farmer node id}
    • -
    -
  • -
-

You will receive the shard as a response of type application/octet-stream if -you are authorized.

-
- -
- -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/tutorial-environment-variables.html b/Storj/core/docs/tutorial-environment-variables.html deleted file mode 100644 index 2fffa6f..0000000 --- a/Storj/core/docs/tutorial-environment-variables.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - - JSDoc: Tutorial: Environment Variables - - - - - - - - - - -
- -

Tutorial: Environment Variables

- -
- -
- - -

Environment Variables

-
- -
-

Below is a list of environment variables that can be used to alter the -behavior of the core library and associated tooling.

-

STORJ_NETWORK

-

This value will be postfixed to your announced protocol version in the network. -A value of testnet would advertise to the network you are running -0.7.0-testnet, which will isolate you to other nodes running the same exact -version. See Running a Test Network for more information.

-

STORJ_ALLOW_LOOPBACK

-

By default, the Network class will drop and ignore message from nodes -who identify themeselves as a loopback interface like localhost, 127.0.0.1, -etc. This is a security precaution to prevent others from causing you to send -messages to yourself as well as prevent invalid contacts in your routing table.

-

To disable this feature (primarily for local testing), set this variable to 1.

-

STORJ_BRIDGE

-

This variable will change the default URI for the BridgeClient class. -The default value is https://api.storj.io. If you run your own bridge, -testing one locally, or otherwise would like to default to a different host, -set this variable.

-

This works well with the CLI (see Using the Command Line Tools) when -testing against other bridges.

-

STORJ_KEYPASS

-

This variable will set the --keypass used to unlock the keyring.

-

Setting your password will make it so other users can't grep it with ps -a.

-

STORJ_TEMP

-

This variable will set the folder to which the encrypted file will be placed -when uploading a file. Shards will also be placed in this folder during upload.

-
- -
- -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/tutorial-file-encryption.html b/Storj/core/docs/tutorial-file-encryption.html deleted file mode 100644 index f449208..0000000 --- a/Storj/core/docs/tutorial-file-encryption.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - JSDoc: Tutorial: File Encryption Standards - - - - - - - - - - -
- -

Tutorial: File Encryption Standards

- -
- -
- - -

File Encryption Standards

-
- -
-

This document serves to provide a detailed account of how files are encrypted -by default by Storj Core to promote interoperability between different -implementations of clients.

-

Sharding and Encryption Scheme

-

Before data is stored in the network, the Storj Core library automatically -handles file encryption, sharding, and key management for you.

-

In order of operations:

-
    -
  1. Complete file is encrypted with a unique key and initialization vector
  2. -
  3. File is demultiplexed (or "sharded") into individual chunks
  4. -
  5. Each shard is offered to the network and transferred
  6. -
  7. Key and IV are encrypted with a passphrase and stored locally
  8. -
-

Key and Initialization Vector Generation

-

Files are encrypted using AES-256-CTR. Use -of CTR allows for random read-access to known indices. File keys are -generated via one of two methods:

-
    -
  • Local PBKDF2 key derivation (default)
  • -
  • Passphrase-based deterministic key derivation (recommended)
  • -
-
PBKDF2 Key Derivation
-

By default, the key for each file is the result of a standard key derivation -function, PBKDF2. PBKDF2 generates a -key from a password and a salt. These two values are randomly generated bytes:

-
    -
  • Password: 512 random bytes
  • -
  • Salt: 32 random bytes
  • -
-

The key length of the PBKDF2 is 512 bytes, should use 25000 iterations, and use -SHA-512 as the digest. To create the cipher/decipher and initialization vector, -derive the SHA-256 hash of the resulting PBKDF2 for the cipher/decipher key -and use the first 16 bytes of the original salt as the iv. The -DataCipherKeyIv class represents these values, and provides methods for -their generation.

-

The KeyRing class stores the original password and salt locally in -an encrypted JSON document keyed by the ObjectId returned from -Storj Bridge for the file object. The -cleartext JSON document has two properties: pass and salt.

-
{
-  "pass": "c7c311ee213d10baefd620a004d76485190d82...",
-  "salt": "6d33490c999e9d613ccf4b146446763df15de2..."
-}
-
-

This JSON string is encrypted with AES-256-CBC using a user-defined passphrase, -and encoded as Base58. Each of those -encrypted JSON documents is stored in a directory called key.ring/, where the -file name is the ObjectId returned from Storj Bridge for the file object.

-
Portable Key Ring Format
-

Because the keys in the key ring are generated and stored locally, files -encrypted with these keys cannot be accessed by other machines without first -duplicating the key files onto that machine. To mitigate this, Storj Core can -create a simple portable key ring archive.

-

A KeyRing created by Storj Core can be exported into a portable format, -which is simply a gzipped tape archive (.tar.gz or .tgz). Importing this -archive simply entails:

-
    -
  1. Decompress and unpack the archive
  2. -
  3. Decrypt each JSON document using the original passphrase
  4. -
  5. Encrypt each document with the passphrase of the target keyring
  6. -
  7. Move the files into the target keyring, optionally overwriting conflicts
  8. -
-
Passphrase-based Key Derivation
-

Rather than relying on locally-generated keys, it is recommended that the user -generate a high-entropy passphrase, and generate keys from it via a -deterministic key derivation process. Using this method, the user may grant -access to all encrypted files by simply transferring the passphrase. Storj Core -offers tools for this based on Bitcoin's BIP39 Mnemonic passphrases.

-

KeyRing provides tools for generating a mnemonic passphrase and -writing it to disk. If a mnemonic is found, Storj Core will prefer -passphrase-based key derivation to PBKDF2 derivation. Storj clients should -create a file key as follows:

-
    -
  1. Prepend the passphrase to the Bucket ID
  2. -
  3. Calculate the sha512 hash of the resulting string
  4. -
  5. Take the first 64 bits of the resulting hash to make the Bucket Key
  6. -
  7. Prepend the Bucket Key to the File ID
  8. -
  9. Calculate the sha512 hash of the resulting string
  10. -
  11. Take the first 64 bits of the resulting hash to make the File Key
  12. -
-

As any client with access to the passphrase can easily generate file keys on -demand, this provides additional portability of files between machines and -applications.

-

It is strongly recommended that users write down the passphrase, and keep it in -a secure place.

-
Public Bucket Key Storage
-

Public Buckets are a feature of Bridge, not a feature of Storj. When a Public -Bucket is created, the Bucket Key is stored with Bridge. It is then provided to -clients requesting PUSH or PULL tokens from that bucket.

-

References

- -
- -
- -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/tutorial-private-testnet.html b/Storj/core/docs/tutorial-private-testnet.html deleted file mode 100644 index 7624234..0000000 --- a/Storj/core/docs/tutorial-private-testnet.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - JSDoc: Tutorial: Running a Test Network - - - - - - - - - - -
- -

Tutorial: Running a Test Network

- -
- -
- - -

Running a Test Network

-
- -
-

Setting up a private or partitioned version of the Storj network is very simple. -The Storj protocol requires the inclusion of a protocol property nested -inside the contact data included in every RPC message. See -Protocol Specification for more information on the RPC message format.

-

Protocol Identifier Format

-

Nodes on the Storj network identify the version of the protocol they are -running with the use of a semantic version tag. When a -node is trying to determine whether or not another node is compatible with her -version of the protocol, she checks the following:

-
    -
  • Is the MAJOR version the same?
  • -
  • Is the MAJOR version 0?
  • -
  • Is the MINOR version the same?
  • -
-

If both nodes are running the same MAJOR version and that version is -not 0, then the nodes are compatible. If the MAJOR version is 0, -then the nodes are compatible only if the MINOR version is the same.

-

For example:

-
    -
  • 0.5.1 is compatible with 0.5.3
  • -
  • 0.5.1 is not compatible with 0.6.0
  • -
  • 1.5.1 is compatible with 1.13.0
  • -
  • 2.1.0 is not compatible with 1.13.0
  • -
-

Special Identifiers

-

The semantic versions specification also allows for special identifiers by -postfixing the version with a hyphen followed by some identifier. This is where -the network partitioning magic happens.

-

Let's say, for example, I work for "Widgets Ltd" and I want to deploy a Storj -network within the Widgets Ltd private network. Every workstation would run a -modified version of storj/farmer or maybe -my own custom interface built atop storj/core.

-

I would simply change my Storj-based software to use the version -1.5.0-widgetsltd. The Storj protocol sees this identifies as a strict match -and therefore any nodes running this version of the software will only -communicate with nodes running the exact protocol identifier.

-

Changing the Version

-

Changing the version in storj/core is easy as pie. In your code, simply -import the module and change the identifier like so:

-
// Import core library
-var storj = require('storj');
-
-// Modify protocol version
-storj.version.protocol = '1.5.0-widgetsltd';
-
-// Get on with your stuff...
-
-

If you are running "vanilla" Storj software, you can change the protocol -version by setting the STORJ_NETWORK environment variable. This will add a -postfix to the protocol version, which will partition the network to nodes -that are running that exact version:

-
STORJ_NETWORK=testnet storjshare --datadir /path/to/shards
-
-

This concept applies broadly to deploying a custom Storj network for any -purpose. This could be used for a public testnet (x.x.x-testnet) or for the -private network example above.

-
- -
- -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/tutorial-protocol-spec.html b/Storj/core/docs/tutorial-protocol-spec.html deleted file mode 100644 index 4a4b0a1..0000000 --- a/Storj/core/docs/tutorial-protocol-spec.html +++ /dev/null @@ -1,996 +0,0 @@ - - - - - JSDoc: Tutorial: Protocol Specification - - - - - - - - - - -
- -

Tutorial: Protocol Specification

- -
- -
- - -

Protocol Specification

-
- -
-

Nodes communicate with each other using -JSON-RPC 2.0 over HTTPS. This requires -farmers (nodes who are contracted by renter to store data) to be publicly -addressable and enables access to content from web browsers, mobile phones, and -any other devices that speak HTTP (hint: everything).

-

This document outlines the specification for the RPC interface by defining the -message structure, required methods, and expected response formats that are -needed for a Storj protocol compliant implementation.

-
-

Note that there may be other aspects of the protocol that are implemented as -SIPs (Storj Improvement Proposals). See the end of this document for a list -of implemented SIPs.

-
-

Request Format

-

Requests are formed according to the JSON-RPC 2.0 specification and are issued -via HTTP POST. The Storj protocol requires the use of named parameters - -positional parameters are not supported. Example:

-
{
-  "method": "PING",
-  "params": {
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "89cc3ddb4209c6e7e301c10c0257adf4fd85f253",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "3045022100de2e162d017a1e9d0ebfe2a94df3fc847b68281a9882..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

The receiving node for this request would then respond with the result, which -in the case of a PING message, is simply an acknowledgement that includes -the recipient's contact information and required signature and nonce:

-
{
-  "result": {
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

In the event that an error occurs, an error property must be added to the -response. You still need to include your contact data in the result -property of the response:

-
{
-  "result": {
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "error": {
-    "code": -32603,
-    "message": "OH GOD THERE'S SO MUCH BLOOD"
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Joining the Network

-

To join the Storj network, one must only know the contact information for a -single "seed" node. A node's contact information is defined as the following -three properties:

-
    -
  • address - hostname, domain, or IP
  • -
  • port - port number on which the node is listening
  • -
  • nodeID - hash of the node's public key (see below)
  • -
  • protocol - version of the protocol implementation
  • -
-

This information can be expressed as a URI in the following format:

-
storj://10.0.0.2:1337/89cc3ddb4209c6e7e301c10c0257adf4fd85f253
-
-

In addition to knowing this information about the seed, you also will need to -know this information about yourself, so that it can be provided to the nodes -with which you are communicating. Your "contact card" must be provided as the -contact parameter in every message sent (both requests and responses). This -is because messages must be signed with your private key and your nodeID is -used by recipients to verify two things:

-
    -
  1. That you own the private key corresponding to your claimed nodeID
  2. -
  3. That the message was in fact sent by you and not an attacker
  4. -
-

In the Storj network, nodes are identified by the hash of the public portion of -an ECDSA key pair. Key pairs are generated using curve SECP256K1 and a node's -nodeID is the "pubkeyhash", defined as:

-
RIPEMD160(SHA256(public_key))
-
-

This pubkeyhash, combined with a message and signature is enough data to -reconstruct the complete public key and is used in the Storj network to sign -and verify messages. This ensures that nodes are unable to assume the identity -of another node by claiming it has the same nodeID.

-

Special Headers

-
x-storj-node-id
-

Every request sent should include this header. It's value should equal the -expected Node ID of the destination. This allows nodes who are tunneling -other nodes to determine who the message is intended for.

-

PROBE

-

Before a node can join the network, it must determine whether or not it is -reachable (or publicly addressable). This can be determined by sending a -PROBE request to a known seed.

-
{
-  "method": "PROBE",
-  "params": {
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.6.0"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

The PROBE RPC message triggers the recipient to attempt to reach the -supplied Contact directly by sending a PING RPC message. If the -target Contact reponds to the PING, then the PROBE should yield -a success response, which is indicated by simply responding to the RPC -message with only the required parameters and no error property.

-
{
-  "result": {
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.6.0"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

If the PING message triggered by the PROBE fails, then the recipient of the -PROBE RPC must respond with an error indicating to the sender that she is not -addressable.

-
{
-  "result": {
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.6.0"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "error": {
-    "code": -32603,
-    "message": "PROBE FAILED"
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

If the PROBE fails, you cannot successfully join the overlay and need to -establish a tunnel through a node that is addressable on the network.

-

FIND_TUNNEL

-

Finding a node that is willing to tunnel your connection to the overlay begins -with a FIND_TUNNEL RPC message sent to a known seed. Nodes on the network -maintain a record of known nodes that are willing to tunnel, by subscribing to -"tunnel announcements" over the publish/subscribe system.

-
-

For more information on how nodes announce willingness to tunnel, see the -documentation for Tunnelling Connections.

-
-
{
-  "method": "FIND_TUNNEL",
-  "params": {
-    "relayers": [],
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

When a node receives a FIND_TUNNEL message, it should respond with ALPHA -(3) contacts that are close the the sender's nodeID who have previously -published their willingness to tunnel. If the recipient herself is willing to -tunnel the connection, she may include herself in the response even if her -nodeID is not closer to the sender's nodeID than her known tunnels.

-
{
-  "result": {
-    "tunnels": [
-      {
-        "address": "10.0.0.4",
-        "port": 1337,
-        "nodeID": "58dc026fa01ae26822bfb23f98e725444d6775b0",
-        "protocol": "0.6.0"
-      },
-      {
-        "address": "10.0.0.5",
-        "port": 1337,
-        "nodeID": "68dc026fa01ae26822bfb23f98e725444d6775b0",
-        "protocol": "0.6.0"
-      },
-      {
-        "address": "10.0.0.6",
-        "port": 1337,
-        "nodeID": "78dc026fa01ae26822bfb23f98e725444d6775b0",
-        "protocol": "0.6.0"
-      }
-    ],
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.6.0"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

The result of a FIND_TUNNEL message looks almost identical to the result of a -FIND_NODE message, with the exception being the name of the result key is -tunnels instead of nodes. Now that the original sender possesses the -contact information for some known tunnels, she should keep them in her record -so that she can later respond to other's FIND_TUNNEL requests appropriately.

-

Before the node can join the overlay (after determining it is not publicly -addressable), it needs to establish a connection tunnel through one of the -Contacts received from the FIND_TUNNEL request.

-

OPEN_TUNNEL

-

Establishing a tunnel is initiated by sending an OPEN_TUNNEL RPC message to a -node who has indicated their willingness to tunnel. Only the minimum required -parameters need to be sent.

-
-

In the future, the protocol may be enhanced to include additional information -in the OPEN_TUNNEL RPC for negotiating payment channels or other conditions.

-
-
{
-  "method": "OPEN_TUNNEL",
-  "params": {
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "1.0.0"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

The recipient of the OPEN_TUNNEL message must determine whether or not she -can satisfy the request. This decision may be based upon an arbitrary limit -set by the node regarding how many concurrent tunnels she wishes to open, -available bandwidth, etc. If the node is capable of establishing the tunnel, -she must do so, assigning a dedicated address or port to receive messages and -data channel requests (see data-channels).

-

Once the tunnel's dedicated entry point has been established, she responds to -the sender of the OPEN_TUNNEL request with a proxyPort to which the client -may connect to receive messages.

-
{
-  "result": {
-    "proxyPort": 12000,
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "1.0.0"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

This response indicates that a proxy has been established and the original -sender can receive messages from the overlay by opening a TCP connection -to the proxyPort and contact address in the reply. In addition, the sender -must update it's Contact information to mirror the remote tunneler's -address and port.

-

If the recipient of the OPEN_TUNNEL message is not able to establish a tunnel -for the sender, then she may respond with an error so that the sender can -attempt to open a tunnel with other known contact.

-
{
-  "result": {
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.6.0"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "error": {
-    "code": -32603,
-    "message": "Failed to establish tunnel, multiplexer full"
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Once your node has determined that it is publicly addressable on the network -or has successfully established a tunnel, it can join the overlay network by -issuing a FIND_NODE request sent to one or more known seeds. The request must -include a key, contact (you), along with a signature and nonce.

-

FIND_NODE

-

When issuing a FIND_NODE request, you provide a key that represents the -nodeID of the contact of which you would like to know their neighbors. When -joining the network, this value is your own nodeID.

-
{
-  "method": "FIND_NODE",
-  "params": {
-    "key": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

When a node receives a FIND_NODE RPC message, it must perform a lookup in -it's routing table and respond with a nodes array containing the known -contacts that are "closest" to the provided key. This is based on the XOR -metric as the Storj network uses a -Kademlia-based overlay. In addition, -if the receiving node is not already aware of the requesting node, it may add -the requester to it's own routing table to later inform other requesters.

-
{
-  "result": {
-    "nodes": [
-      {
-        "address": "10.0.0.4",
-        "port": 1337,
-        "nodeID": "58dc026fa01ae26822bfb23f98e725444d6775b0",
-        "protocol": "0.8.1"
-      },
-      {
-        "address": "10.0.0.5",
-        "port": 1337,
-        "nodeID": "68dc026fa01ae26822bfb23f98e725444d6775b0",
-        "protocol": "0.8.1"
-      },
-      {
-        "address": "10.0.0.6",
-        "port": 1337,
-        "nodeID": "78dc026fa01ae26822bfb23f98e725444d6775b0",
-        "protocol": "0.8.1"
-      }
-    ],
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Upon receipt of the FIND_NODE response, the node attempting to join the -network may iteratively send the same FIND_NODE request to contacts that have -been newly added to the routing table to build out a wider view of the network. -Once the joining node is satisfied with the size of the routing table (or there -are no more nodes to discover), this is considered a successful join.

-

Soliciting Storage

-

Once a node has a sufficiently complete routing table and view of the network, -it's time to buddy up with it's neighbors to cooperate in the sharing and relay -of publications. A "publication" is essentially a request for storage. When -a node in the network wishes to store some data, it notifies it's closest -neighbors who, if interested, will respond to negotiate a storage contract.

-

If the neighbors are not offering storage or do not wish to fulfill the terms of -the storage contract, they must check to see if any of their neighbors are and -forward the publication to them. If no known neighbors are interested, then the -publication is sent to a random node in that neighbor's routing table and the -process repeats until an interested node fulfills the contract.

-

SUBSCRIBE

-

In order to know what publications in which your neighbors are interested, we -select the 3 nodes in our routing table that are identified by a nodeID that -is closest to ours and we issue a SUBSCRIBE message to each of them:

-
{
-  "method": "SUBSCRIBE",
-  "params": {
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

To properly handle a SUBSCRIBE message, the recipient must respond with an -attenuated bloom filter, with a size 160 bits and a depth of 3. This data -structure represents 3 sets of topics to which the recipient's neighbors are -subscribed 3 "hops" away.

-
{
-  "result": {
-    "filters": [
-      "0000000000000000000000000000000000000000",
-      "0000000000000000000000000000000000000000",
-      "0000000000000000000000000000000000000000"
-    ],
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "58dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

When the original requesting node receives this response, it must update it's -local attenuated bloom filter to reflect this response, starting at it's filter -at index 1 (since index 0 is reserved for topic to which the node itself is -interested).

-

UPDATE

-

After the requester updates it's local view of it's neighbor's publication -subscriptions, it must in turn update it's neighbors with it's own publication -subscriptions by providing it's own attenuated bloom filter:

-
{
-  "method": "UPDATE",
-  "params": {
-    "filters": [
-      "0000000000000000000000000000000000000000",
-      "0000000000000000000000000000000000000000",
-      "0000000000000000000000000000000000000000"
-    ],
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

This method is essentially the "push" version of the SUBSCRIBE message, where -instead of providing subscription information as a response, we provide it as a -request. Whenever a node subscribes to a new publication topic, it should -initiate another SUBSCRIBE/UPDATE loop with it's neighbors to ensure that -it may cooperate in publication relay effectively.

-

PUBLISH

-

Once a node has a view of the publications to which it's neighbors are -subscribed, it is capable of issuing a PUBLISH message containing a topic -and some content. This message is sent to the node's nearest neighbors, who -then relay it to their neighbors based upon their own view of nearby -subscriptions.

-

The topic property and the corresponding contents data is arbitrary, but -this mechanism is used for publishing "asks" for storage contracts. In this -case, the topic is equal to the Contract type and the contents is -equal to the proposed contract itself. See Publishing Storage Contracts for more -information on how to choose a valid contract type for your storage needs.

-
{
-  "method": "PUBLISH",
-  "params": {
-    "uuid": "7f0c40a2-e465-4f3e-b617-3d53460e34f7",
-    "topic": "0f02010303",
-    "contents": {
-      "type": "56ce3e837f575827cb5a94e2b609756a48fa4a3882f5e762b262af31f432878d",
-      "renter_id": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "renter_signature": null,
-      "farmer_id": null,
-      "farmer_signature": null,
-      "data_size": 4906,
-      "data_hash": "4efc1c36d3349189fb3486d2914f56e05d3e66f8",
-      "store_begin": 1455228907665,
-      "store_end": 2910457830468,
-      "audit_count": 10,
-      "payment_storage_price": 1200,
-      "payment_download_price": 2,
-      "payment_destination": null
-    },
-    "publishers": [
-      "48dc026fa01ae26822bfb23f98e725444d6775b0"
-    ],
-    "ttl": 1455228597837,
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Upon receipt of a PUBLISH message, a node must first check to make sure it -has not already received the publication. This is done by caching the uuid of -received publications. If the node has already seen the publication, it should -respond with an error message indicating such. The node should also make sure -that the publication has not expired by checking that the ttl is a positive -integer.

-

If the node has not previously seen the publication and the message has not -expired, then it must check to see if the publication topic is of interest to -itself by testing it's attenuated bloom filter at index 0 for the topic. If -the node is interested in the publication, it may take action accordingly. In -the case of storage contract, the node may begin communicating directly with -the original publisher to finalize the contract.

-

Regardless of whether or not the node is interested in the publication, it -should acknowledge receipt of the publication to the forwarder:

-
{
-  "result": {
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Then, it must append negative information to the publication message by -adding it's own nodeID to the publishers property as well as decrementing -the ttl. Once the message has been updated with the negative information, -the node must check it's attenuated bloom filter to see if any of it's -neighbors are also interested and, if so, forward the message along to them. -If no neighbors are interested, the node must select a random contact from the -routing table and forward the message to that contact.

-

Negotiating Storage Contracts

-

When a node receives a contract proposal in the form of a PUBLISH message and -that proposal meets the recipient's criteria, it can send an OFFER message to -the original publisher.

-

OFFER

-

The offer message must contain the original contract, supplemented with the -information that is required of the offering node, which at minimum must -include farmer_id, farmer_signature, and payment_destination.

-
-

The *_signature property value should be the hex-encoded signature of the -JSON string representation of the contract, minus both signature fields and -with keys sorted alphanumerically.

-
-

In addition to these fields, the offering node (or "farmer") may modify the -other fields in the contract to their liking if they wish to counter the -original offer:

-
{
-  "method": "OFFER",
-  "params": {
-    "contract": {
-      "type": "56ce3e837f575827cb5a94e2b609756a48fa4a3882f5e762b262af31f432878d",
-      "renter_id": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "renter_signature": null,
-      "farmer_id": "58dc026fa01ae26822bfb23f98e725444d6775b0",
-      "farmer_signature": "304502203f2be986f4213c45bf2f78c57cbf4001b049c4fd...",
-      "data_size": 4906,
-      "data_hash": "4efc1c36d3349189fb3486d2914f56e05d3e66f8",
-      "store_begin": 1455228907665,
-      "store_end": 2910457830468,
-      "audit_count": 10,
-      "payment_storage_price": 1200,
-      "payment_download_price": 2,
-      "payment_destination": "1JUhMAZj2Mkb4mRaGxbBYPsStryPyDxPuj"
-    },
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

The receiving node must check the offer and determine whether or not the -modified contract terms are satisfactory. If so, it may finalize the contract -by adding it's signature to the renter_signature field:

-
{
-  "result": {
-    "contract": {
-      "type": "56ce3e837f575827cb5a94e2b609756a48fa4a3882f5e762b262af31f432878d",
-      "renter_id": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "renter_signature": "304402202ccc152ee81fbff7e802c290cabea0c62384bb12...",
-      "farmer_id": "58dc026fa01ae26822bfb23f98e725444d6775b0",
-      "farmer_signature": "304502203f2be986f4213c45bf2f78c57cbf4001b049c4fd...",
-      "data_size": 4906,
-      "data_hash": "4efc1c36d3349189fb3486d2914f56e05d3e66f8",
-      "store_begin": 1455228907665,
-      "store_end": 2910457830468,
-      "audit_count": 10,
-      "payment_storage_price": 1200,
-      "payment_download_price": 2,
-      "payment_destination": "1JUhMAZj2Mkb4mRaGxbBYPsStryPyDxPuj"
-    },
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Alternatively, the receiving node may counter the offer by modifying any of the -fields and returning those in the response. The farmer must check the contract -against it's signature to determine if the terms of the contract have been -changed. This counter offer loop can continue until one party abandons the -offer loop or until both parties have signed the same contract.

-
-

Once a contract has been finalized, each node should store a copy locally -that can be keyed by the data_hash.

-
-

Executing a Storage Contract

-

Once a storage contract has been signed by both parties, the renter may execute -the terms of the contract by issuing a CONSIGN message to the farmer. The -purpose of this message is to deliver the data referenced by the contract for -the farmer to store.

-

CONSIGN

-

The consign message must contain the hex-encoded -data_shard itself, the contract_hash, as well as an audit_tree that -contains the bottom leaves of the audit strategy's merkle tree (see Auditing -a Storage Contract below).

-
{
-  "method": "CONSIGN",
-  "params": {
-    "data_hash": "4efc1c36d3349189fb3486d2914f56e05d3e66f8",
-    "audit_tree": [
-      "40a98e19c298631cba19d6c19691360ce08ccf36",
-      "02f0d971096305e797da9165cd50d4d1bb19590b",
-      "a44ad75d8aa118cdd73df77ae2543d3e87f94576",
-      "d84e8bfac28a98df418d0c3029f77a4d9f338e9e",
-      "7408bb5b0a9eefa56f3234fc83d2423f76c4b857",
-      "d1b71886c910d34b31cee9e23316abded9ef3fe0",
-      "0ac89686a12e26aaf952180c0fec5373224c4c1e",
-      "98c304116e7eb89839ff6c96202eb4c3cbdaf8e0",
-      "c7937b8a1be9da426e076eff70c5b4edf8a66270",
-      "c6c2c5cdafb99e4d62185d42e59522d15c33d676",
-      "1f87ca29e75944aa36e676b3ddf27e49a8ca4fe2",
-      "8585e356a517535b8a36ec9222b955c5b61a5227",
-      "ba084d3f143f2896809d3f1d7dffed472b39d8de",
-      "ba084d3f143f2896809d3f1d7dffed472b39d8de",
-      "ba084d3f143f2896809d3f1d7dffed472b39d8de",
-      "ba084d3f143f2896809d3f1d7dffed472b39d8de"
-    ],
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Upon receipt of a CONSIGN message, the farmer must lookup the reference -contract by the supplied data_hash and verify that the renter is authorized -to store the data and that the number of items in the audit_tree is equal to -the next power of 2 of the audit_count supplied in the original contract.

-

Once verified, the farmer must respond with a generated token that the renter -or another authorized party can use to open a data channel with the farmer -(via websocket) to deliver the data as a binary stream.

-
-

For more information on the Data Channel specification see the tutorial for -data-channels.

-
-

In addition, the farmer should verify that the current UNIX time is greater -than or equal to the agreed upon store_begin and less than the agreed upon -store_end. If everything checks out, the farmer must store the consigned data -in such a way that it may later be retrieved by it's hash. Once the farmer has -done this, it must acknowledge the renter to confirm:

-
{
-  "result": {
-    "token": "3f62b781e3b5b5288dca587807248261d109bbfb",
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Using Mirrors for Redundancy

-

In most cases it is desirable for the renter to store multiple copies of the -shard across a number of farmers in the event that one of the contracted -farmers leaves the network, loses the data, or otherwise breaches the terms of -the storage contract. This can be accomplished by simply performing an -iterative PUBLISH - OFFER - CONSIGN loop for the desired level of redundancy, -followed by the establishment of a data channel as described in -data-channels.

-

However, this method can introduce a significant amount of latency for -completing a full upload that increases linearly with the number of redundant -shards. Additionally, the amount of bandwidth consumed by the renter increases -in the same way as the renter will have to upload the data for each redundant -shard.

-

MIRROR

-

In these scenarios, renters can offload the burden of storing multiple copies -of a shard to the farmers by issuing a MIRROR RPC in lieu of establishing -a data channel. A MIRROR RPC instructs a contracted farmer to retrieve the -data already uploaded to another farmer by providing them with a retrieval -token authorized by another farmer (this is performed by issuing a RETRIEVE -RPC message - see Downloading Consigned Data later in this document). This -allows the renter to incur the bandwidth and latency once and instead pay the -recently contracted farmer to transfer the data to another farmer for -redundancy.

-

To initiate this process, instead of opening a data channel, issue a MIRROR -RPC message to the farmer after contract negotiation is complete:

-
{
-  "method": "MIRROR",
-  "params": {
-    "data_hash": "4efc1c36d3349189fb3486d2914f56e05d3e66f8",
-    "token": "ce898e520cede42fd847ba5176b6d6b6ea47481f",
-    "farmer": {
-      "address": "remote.farmer.host",
-      "port": 4000,
-      "nodeID": "e77e46ceb7f8dbf2904eff254a479f90a4f8ddbd",
-      "protocol": "0.8.1"
-    },
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-
-

Note that you should wait until data is successfully consigned to the first -farmer before sending a MIRROR RPC for replication.

-
-

Once the mirroring farmer receives the request, it should open a data channel -to the original farmer and pass along the supplied token and data hash in the -initial authorization frame. Once the mirroring farmer begins receiving data -it must respond to the renter's request with a simple acknowledgement to -indicate that the mirror operation was successfully initiated.

-
{
-  "result": {
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-
-

Note that data transfer may fail after the original acknowledgement. It is -important to regularly issue AUDIT messages to farmers storing your data. -If a mirror farmer later fails an audit, the renter should negotiate a new -contract and attempt to create a new mirror to retain the expected level of -redundancy.

-
-

Auditing a Storage Contract

-

Before a renter issues a CONSIGN RPC, it must pre-calculate a series of -"challenges", the number of which must equal the audit_count defined in the -negotiated contract. A challenge is simply 32 random bytes encoded as hex. The -generated challenges must not be shared until the renter wishes to issue an -AUDIT request.

-

When issuing a CONSIGN request, the renter must include an audit_tree which -contains the bottom leaves of a merkle tree. Each of the bottom leaves of the -tree must be equal to the double RIPEMD160(SHA256(challenge + shard)) encoded -as hex. In order to ensure that the resulting merkle tree is properly -"balanced", the number of bottom leaves must be equal to the next power of 2 of -the audit count. To ensure this, the additional leaves can simply be the double -RIPEMD160(SHA256('')) (the same hash function for an audit, but applied to an -empty buffer).

-

AUDIT

-

To audit a farmer is to request proof that it is still honoring the terms of -the storage contract without the need to have them supply the entire -data_shard. To do this, the renter must supply the farmer with one of the -secret pre-calculated challenges:

-
{
-  "method": "AUDIT",
-  "params": {
-    "audits": [
-      {
-        "data_hash": "4efc1c36d3349189fb3486d2914f56e05d3e66f8",
-        "challenge": "6290bb9e1766bf3fc00eea3bb14146925611026d453e1aa95c32973f8baa5c98"
-      }
-    ],
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Upon receipt of an AUDIT request, the farmer must lookup the data_shard by -the supplied data_hash, then calculate the single -RIPEMD160(SHA256(challenge + shard)).

-
-

The result of this operation should hash again to match one of the items -supplied in the audit_tree property of the original CONSIGN request.

-
-

In addition to supplying this single-hashed value as proof that the farmer is still honoring -the terms of the contract, the farmer must also provide the uncles required -to rebuild the merkle tree. This proof response is specified as a series -of nested JSON arrays:

-
{
-  "result": {
-    "proofs": [
-      [[[
-      [["6a2f02144c461e178dc4496c263313e64d7a56ab"
-      ],"efb0dfa48813e3289ba8d16e9e23cf1efa1a99fd"
-      ],"dfb8877b84e7a7496a4b08b2aef6ffd02ccbfccc"
-      ],"82c60f546bcaaabeb908c911b1fadb816e039409"
-      ],"5e265b0256cd471c6af22bd66b59ed9242067654"]
-    ],
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

For clarification, given a simple merkle tree:

-
+-- Hash_0 (Root)
-|   +-- Hash_1
-|   |   +-- Hash_3
-|   |   +-- Hash_4
-|   +-- Hash_2
-|   |   +-- Hash_5
-|   |   +-- Hash_6 = RIPEMD160(SHA256(RIPEMD160(SHA256(challenge + shard))))
-
-

The resulting format of a proof for an audit matching Hash_6 would appear as:

-
[Hash_1, [Hash_5, [RIPEMD160(SHA256(challenge + shard))]]]
-
-

And, the resulting format of a proof for an audit matching Hash_3 would appear as:

-
[[[RIPEMD160(SHA256(challenge + shard))], Hash_5], Hash_2]
-
-

Upon receipt of the farmer's proof, the renter must verify that the proof is -valid by using it to rebuild the merkle tree. See Verification#verify -for an implementation example. If the proof is verified successfully, then the -renter is expected to issue a payment to the payment_destination defined in -the original contract. The amount of the payment should be equal to:

-
(payment_storage_price / audit_count) + (payment_download_price * downloads_since_last_audit)
-
-

If the verification fails then the contract is null and no payment is required. -Conversely, if the verification succeeds and the renter does not issue the -payment in a timely manner, then the contract is also null and the farmer may -decide to cease storage of the data.

-

RETRIEVE

-

When a renter wishes to retrieve data that is stored under contract, it can -issue a RETRIEVE RPC message that includes the data_hash to the farmer -storing the data:

-
{
-  "method": "RETRIEVE",
-  "params": {
-    "data_hash": "4efc1c36d3349189fb3486d2914f56e05d3e66f8",
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

After the recipient of the RETRIEVE message verifies the sender's signature -it must lookup the storage contract by the supplied data_hash and verify that -the sender is the party with which the contract was negotiated. If all tests -pass, then the farmer must respond with a generated token to allow the renter -to open a data channel (via websocket) to retrieve the data as a binary stream. -After the data shard is delivered successfully, the farmer must increment -it's record of the downloads_since_last_audit (which must be reset after the -next audit).

-
-

For more information on the Data Channel specification see the tutorial for -data-channels.

-
-
{
-  "result": {
-    "token": "3f62b781e3b5b5288dca587807248261d109bbfb",
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.8.1"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

In addition, the renter must check the integrity of the returned data_shard -by calculating the hash and checking it against the expected data_hash. If -the test fails, then this effectively a failed audit and the contract is null.

-

Implemented SIPs

- -
- -
- -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/tutorial-renting-data.html b/Storj/core/docs/tutorial-renting-data.html deleted file mode 100644 index 5507557..0000000 --- a/Storj/core/docs/tutorial-renting-data.html +++ /dev/null @@ -1,314 +0,0 @@ - - - - - JSDoc: Tutorial: Renting Data to the Network - - - - - - - - - - -
- -

Tutorial: Renting Data to the Network

- -
- -
- - -

Renting Data to the Network

-
- -
-

This tutorial covers the process for using StorjCORE to rent data to farmers on -the network programmatically using a number of tools included in the library. -This walkthrough should also serve as an overview for a number of the tools -included in the library and how they work together.

-

Bootstrapping

-

Before we can join the network, we need to set up a few required components:

-
    -
  • KeyPair - for representing our identity on the network
  • -
  • StorageAdapter - for persisting our contracts and shard metadata
  • -
  • StorageManager - for managing our persistence layer
  • -
-

Start by importing the storj module and instantiating these objects:

-
var storj = require('storj');
-var keypair = new storj.KeyPair();
-var persistence = new storj.EmbeddedStorageAdapter('/path/to/datadir');
-var manager = new storj.StorageManager(persistence);
-
-

Now that we have a way of identifying ourselves to the network and keeping a -record of our contracts, we can use the RenterInterface to join the -network.

-
var renter = new storj.RenterInterface({
-  keyPair: keypair,
-  storageManager: manager,
-  rpcAddress: 'ip.or.hostname',
-  rpcPort: 1337
-});
-
-renter.join(function(err) {
-  if (err) {
-    return console.error('Failed to join the network');
-  }
-
-  // CONTINUED IN NEXT EXAMPLE...
-});
-
-

File Preparation

-

Now that we have a connection to the network, we are ready to store some data. -Before we can actually store the data, we need to get some information about -the shards we need to store. We need to know:

-
    -
  • The hash of each shard that will be stored
  • -
  • The size of each shard that will be stored
  • -
  • The length of time we wish to store the data
  • -
  • The number of audits we intend to issue over the life of the contract
  • -
-

To get this information we need to process the file using a few more of the -core components:

- -

We will start by demultiplexing the file into several shard streams. Let's -break our file into 6 shards. We will start by creating a FileDemuxer:

-
var demuxer = new storj.FileDemuxer('/path/to/file');
-
-

Now that we have prepared to shard a file, we need to set up event listeners on -the demuxer for whenever a new shard stream is available. Once a shard stream -is available, we need to encrypt it and calculate it's hash and size so we can -create an appropriate Contract to offer the network. In addition we -will write the encrypted shard to temporary storage so we don't have to process -the file again when we are ready to transfer the data:

-
var tmpdir = require('os').tmpdir();
-var crypto = require('crypto');
-var path = require('path');
-
-demuxer.on('shard', function(shardStream) {
-  var tmpName = path.join(tmpdir, crypto.randomBytes(6).toString('hex'));
-  var tmpFile = fs.createWriteStream(tmpName);
-  var key = new storj.DataCipherKeyIv('password', 'salt');
-  var encrypter = new storj.EncryptStream(key);
-  var hasher = crypto.createHash('sha256');
-  var size = 0;
-
-  encrypter.on('data', function(bytes) {
-    hasher.update(bytes);
-    size += bytes.length;
-  });
-
-  tmpFile.on('finish', function() {
-    // CONTINUED IN NEXT EXAMPLE...
-  });
-
-  shardStream.pipe(encrypter).pipe(tmpFile);
-});
-
-

Contract Negotiation

-

When each shard is finished being encrypted and we know it's size and hash, it -is time to create a Contract and offer it to the network. The example -below is continued from inside the tmpFile.on('finish', callback) in the -example above:

-
var hash = utils.rmd160sha256(hasher.digest());
-var contract = new storj.Contract({
-  renter_id: keypair.getNodeID(),
-  data_size: size,
-  data_hash: hash,
-  store_begin: Date.now(),
-  store_end: Date.now() + 604800000, // 7 days from now
-  audit_count: 12
-});
-
-renter.getStorageOffer(contract, function(err, farmer, contract) {
-  // CONTINUED IN NEXT EXAMPLE...
-});
-
-

Now we have created a Contract for the shard and we are waiting for an -offer from a farmer on the network. When we receive one, the callback supplied -to RenterInterface#getStorageOffer above will trigger and we can -proceed to transfer the shard to the farmer, but first we need to tell the -farmer we are ready to transfer the shard to them and include the audit -information they will need in the future. We will be using:

-
    -
  • AuditStream - for generating audit challenges and merkle tree
  • -
  • StorageItem - for storing our private record of challenges
  • -
-

Let's continue by reading the encrypted shard temporary file we just created -and generating the challenges and merkle tree and saving a copy of the contract -and associated challenges:

-
var item = new storj.StorageItem({ hash: hash });
-var auditGenerator = new storj.AuditStream(12);
-var encryptedShard = fs.createReadStream(tmpName);
-
-auditGenerator.on('finish', function() {
-  item.addContract(farmer, contract);
-  item.addAuditRecords(farmer, auditGenerator);
-
-  manager.save(item, function(err) {
-    if (err) {
-      return console.error(err);
-    }
-
-    // CONTINUED IN NEXT EXAMPLE...
-  });
-});
-
-encryptedShard.pipe(auditGenerator);
-
-

Transferring Shards

-

Now that we have stored a copy of our contract and challenges, it's time to -authorize a "data channel" (as described in data-channels) and -transfer the shard to the farmer.

-
renter.getConsignToken(farmer, contract, auditGenerator, function(err, token) {
-  if (err) {
-    return console.error(err);
-  }
-
-  var upload = storj.utils.createShardUploader(farmer, hash, token);
-  var encryptedShard = fs.createReadStream(tmpName);
-
-  encryptedShard.pipe(upload).on('end', () => {
-    // CONTINUED IN THE NEXT EXAMPLE
-  });
-});
-
-

Remember that these operations for contract negotiation and shard transfer are -taking place for each shard in the original file. You'll want to keep track -of shards and their associated contracts by grouping references to them -logically as the file that they compose. This is the responsibility of -implementing clients. If you do not wish to manage this yourself, consider -running a Bridge or using the -Storj API.

-

Replicating Shards for Redundancy

-

Once we have successfully consigned our data to a farmer, we can ensure that in -the event that farmer disappears, our data can be recovered from elsewhere. We -use mirrors to accomplish this. Mirroring is a method for passively -replicating our data, meaning that instead of uploading it again, we instruct a -new farmer to retrieve it from the location we already stored it.

-
-

We are also going to use the async module -for managing flow control.

-
-

First we'll need to negotiate a few more contracts, then authorize some -retrieval tokens (outlined later in this document), and finally request some -mirrors.

-
var redundancy = 3;
-var mirrors = [];
-
-function _getMirroringContract(n, next) {
-  renter.getStorageOffer(contract, function(err, mirror, contract) {
-    renter.getRetrieveToken(farmer, contract, function(err, token) {
-      if (err) {
-        return next(err);
-      }
-
-      mirrors.push(mirror);
-      next(null, { farmer: farmer, hash: hash, token: token });
-    });
-  });
-}
-
-async.timesSeries(redundancy, _getMirroringContract, function(err, sources) {
-  if (err) {
-    return console.error(err);
-  }
-
-  renter.getMirrorNodes(sources, mirrors, function(err, completed) {
-    if (err) {
-      return console.error('Failed to replicate to all mirrors');
-    }
-
-    console.info('Replicated to %s mirrors', completed.length);
-  });
-});
-
-

Auditing Farmer Storage

-

Now that we have successfully consigned a shard, we will want to be sure that -the farmer is being honest about storing it. We can verify this by requesting -a proof using the challenges we generated previously. We will be using:

-
    -
  • Verification - for validating the farmer's challenge response
  • -
-
var merkleRoot = auditGenerator.getPrivateRecord().root;
-var treeDepth = auditGenerator.getPrivateRecord().depth;
-
-renter.getStorageProof(farmer, item, function(err, proof) {
-  if (err) {
-    return console.error(err);
-  }
-
-  var verification = new storj.Verification(proof);
-  var verifyResult = verification.verify(merkleRoot, treeDepth);
-
-  if (verifyResult[0] !== verifyResult[1]) {
-    return console.error('The proof is not valid');
-  }
-
-  manager.save(item, function(err) {
-    if (err) {
-      return console.error(err);
-    }
-
-    // CONTINUED IN NEXT EXAMPLE
-  });
-});
-
-

Retrieving Shards

-

Now that we have verified that the farmer is storing the shard, we know that we -can later retrieve it when needed. The process for doing this is very similar -to the process for storing the shard, only this time we'll be asking for a -retrieval token and we will be receiving data over the data channel instead of -sending. We'll also be using:

- -
renter.getRetrieveToken(farmer, contract, function(err, token) {
-  if (err) {
-    return console.error(err);
-  }
-
-  var download = utils.createShardDownloader(farmer, hash, token);
-  var decrypter = new storj.DecryptStream(keypair);
-  var fileDestination = fs.createWriteStream('/path/to/download/shard');
-
-  download.pipe(decrypter).pipe(fileDestination);
-
-  fileDestination.on('finish', function() {
-    console.info('Successfully downloaded shard!');
-  });
-});
-
-

This concludes the tutorial. To dive deeper, follow the reference links -throughout this walkthrough and read the documentation on each of the classes -used here.

-
- -
- -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/docs/tutorial-tunnel-connections.html b/Storj/core/docs/tutorial-tunnel-connections.html deleted file mode 100644 index 6a85938..0000000 --- a/Storj/core/docs/tutorial-tunnel-connections.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - JSDoc: Tutorial: Tunnelling Connections - - - - - - - - - - -
- -

Tutorial: Tunnelling Connections

- -
- -
- - -

Tunnelling Connections

-
- -
-

One of the most daunting problems to tackle when designing a stable and -reliable distributed network is the traversal of various constraints such as -NAT and firewalls. In some cases, software can use various strategies to -"punch out" of these constraints and become publicly addressable on the -Internet. The StorjCORE library makes use of these strategies, but when they -fail we must devise more complex tactics for ensuring that network participants -are reachable by their peers.

-

The Storj protocol defines a series of RPC messages that can be exchanged -in order to establish a "tunnel". See the Protocol Specification for more -detail on these RPC messages and their purposes. A tunnel is, in essence, a -proxy that allows a client that is not exposed to the Internet to be -addressable as if it were.

-

This works by a private node opening a long-lived connection to a public node -who establishes a dedicated means for accepting messages on behalf of the -private node and "pipes" any data received via those means directly back to the -private node over the previously established connection.

-

Once a tunnel has been established, the private node can begin identifying -herself to the network using her tunnel's address, instead of her own. Private -nodes do not need to use the tunnel to contact other nodes on the network, but -rather only to be contacted.

-

Announcing Willingness

-

When a node joins the network and is publicly addressable, it has the ability -to announce to the network that it is willing and capable of tunneling -connections on behalf on nodes who are private or unable to punch out to -become addressable on the Internet. The process of doing this uses the same -publish/subscribe system described in the Publishing Storage Contracts -specification which enables nodes to maintain a view of subscriptions in their -neighborhood of the network as described in the Protocol Specification.

-

The difference between a contract publication and a tunnel announcement is in -the opcode used for the topic and in the contents of the publication. Tunnel -announcement publications use the opcode prefix 0x0e followed by a single -criteria degree opcode to indicate their willingness to tunnel (0x00 to -indicate "I am no longer tunneling" and 0x01 to indicate "I am ready to -tunnel").

-

Whenever the condition changes, such as a node's maximum number of tunnels is -reached or when a tunnel becomes available, it should issue a PUBLISH RPC -message to it's nearest neighbors.

-
{
-  "method": "PUBLISH",
-  "params": {
-    "uuid": "7f0c40a2-e465-4f3e-b617-3d53460e34f7",
-    "topic": "0e01",
-    "contents": {
-      "address": "10.0.0.2",
-      "port": 1337
-    },
-    "publishers": [
-      "48dc026fa01ae26822bfb23f98e725444d6775b0"
-    ],
-    "ttl": 1455228597837,
-    "contact": {
-      "address": "10.0.0.2",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.6.0"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Public nodes should subscribe to these topics so that they can maintain an -up-to-date list of nodes who are capable and willing to tunnel connections, so -they can respond accurately to FIND_TUNNEL messages from private nodes.

-

Establishing a Tunnel

-

After a private node has discovered some willing tunnels using the FIND_TUNNEL -RPC message defined in the Protocol Specification, it can now begin the -handshake to establish the tunnel. This begins by sending the OPEN_TUNNEL RPC -message to the desired tunneler node. The recipient of OPEN_TUNNEL will -check:

-
    -
  • Do I have enough remaining tunnels? (based on arbitrary limit set by node)
  • -
  • Am I already tunneling for this nodeID?
  • -
  • Has a payment channel been opened? (future spec)
  • -
-

If the tunneling node has enough tunnels, is not already tunneling the node, -and (in a future spec) if a payment channel has been opened for bandwidth, then -the tunneling node opens a new dedicated TCP socket on an available port -that will be used by the requester to send/receive HTTP messages.

-
{
-  "result": {
-    "proxyPort": 12000,
-    "contact": {
-      "address": "10.0.0.3",
-      "port": 1337,
-      "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0",
-      "protocol": "0.6.0"
-    },
-    "nonce": 1455216323786,
-    "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..."
-  },
-  "id": "7b6a2ab35da6826995abf3310a4875097df88cdb"
-}
-
-

Now the private node can open a TCP connect to the proxyPort provided and -messages sent to the tunneler that specify your node ID in the -x-storj-node-id header will be written to the connected socket. From there, -you may pipe this socket directly to your locally running node.

-
- -
- -
- - - -
- -
- Documentation generated by JSDoc 3.6.11 on Sat Nov 09 2024 22:26:40 GMT-0800 (Pacific Standard Time) -
- - - - - \ No newline at end of file diff --git a/Storj/core/script/publishdoc.js b/Storj/core/script/publishdoc.js deleted file mode 100644 index f65cfd9..0000000 --- a/Storj/core/script/publishdoc.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -var ghpages = require('gh-pages'); -var path = require('path'); - -ghpages.publish(path.join(__dirname, '../jsdoc'), { - repo: 'git@github.com:Storj/core.git' -}, function(err) { - console.log(err || 'Published to http://storj.github.io/core'); -}); diff --git a/Storj/core/.eslintignore b/Storj/protocol-v2/.eslintignore similarity index 100% rename from Storj/core/.eslintignore rename to Storj/protocol-v2/.eslintignore diff --git a/Storj/core/.eslintrc b/Storj/protocol-v2/.eslintrc similarity index 100% rename from Storj/core/.eslintrc rename to Storj/protocol-v2/.eslintrc diff --git a/Storj/core/.gitignore b/Storj/protocol-v2/.gitignore similarity index 100% rename from Storj/core/.gitignore rename to Storj/protocol-v2/.gitignore diff --git a/Storj/core/.jsdoc.json b/Storj/protocol-v2/.jsdoc.json similarity index 100% rename from Storj/core/.jsdoc.json rename to Storj/protocol-v2/.jsdoc.json diff --git a/Storj/core/.jshintrc b/Storj/protocol-v2/.jshintrc similarity index 100% rename from Storj/core/.jshintrc rename to Storj/protocol-v2/.jshintrc diff --git a/Storj/core/.nvmrc b/Storj/protocol-v2/.nvmrc similarity index 100% rename from Storj/core/.nvmrc rename to Storj/protocol-v2/.nvmrc diff --git a/Storj/core/.travis.yml b/Storj/protocol-v2/.travis.yml similarity index 100% rename from Storj/core/.travis.yml rename to Storj/protocol-v2/.travis.yml diff --git a/Storj/core/LICENSE-AGPL-3.0 b/Storj/protocol-v2/LICENSE-AGPL-3.0 similarity index 100% rename from Storj/core/LICENSE-AGPL-3.0 rename to Storj/protocol-v2/LICENSE-AGPL-3.0 diff --git a/Storj/core/LICENSE-LGPL-3.0 b/Storj/protocol-v2/LICENSE-LGPL-3.0 similarity index 100% rename from Storj/core/LICENSE-LGPL-3.0 rename to Storj/protocol-v2/LICENSE-LGPL-3.0 diff --git a/Storj/core/doc/protocol-spec.md b/Storj/protocol-v2/README.md similarity index 61% rename from Storj/core/doc/protocol-spec.md rename to Storj/protocol-v2/README.md index c76ad66..d852ba3 100644 --- a/Storj/core/doc/protocol-spec.md +++ b/Storj/protocol-v2/README.md @@ -1,3 +1,9 @@ +# Storj Core *protocol specification version 2* + +> Authored by Lily Anne Hall with contributions from Braydon Fuller + +## remote procedure calls + Nodes communicate with each other using [JSON-RPC 2.0](http://www.jsonrpc.org/specification) over HTTPS. This requires farmers (nodes who are contracted by renter to store data) to be publicly @@ -1086,6 +1092,638 @@ the test fails, then this effectively a failed audit and the contract is null. ### Implemented SIPs -* [SIP0003 Remote Notifications and Triggers](https://github.com/Storj/sips/blob/master/sip-0003.md) -* [SIP0004 Contract Transfers and Renewals](https://github.com/Storj/sips/blob/master/sip-0004.md) -* [SIP0032 Hierarchically Deterministic Node IDs](https://github.com/Storj/sips/blob/master/sip-0032.md) +* [SIP0003 Remote Notifications and Triggers](../sip-0003) +* [SIP0004 Contract Transfers and Renewals](../sip-0004) +* [SIP0032 Hierarchically Deterministic Node IDs](../sip-0032) + +## contract topics + +Nodes solicit storage contracts with the network by publishing information +about their storage requirements as outlined in {@tutorial protocol-spec}. +Storj implements a distributed publish/subscribe system based on an algorithm +called [Quasar](https://github.com/kadtools/kad-quasar). + +Quasar works by allowing nodes to advertise topics of interest to their +neighbors and keeping a record of these topics in their neighborhood by storing +them in an attenuated bloom filter. Each node has a view of the topics in which +their neighbors are interested up to 3 hops away. By the nature of this +design, the network forms gravity wells wherein messages of interest are +efficiently relayed to nodes that are subscribed to the topic without flooding +the network. + +This approach works well when there is a diverse number of topics. The Storj +protocol leverages this by defining a matrix of *criteria* and *descriptors* +in the form of opcodes representing the degree of which the criteria must be +met. + +### Criteria + +At the time of writing, there are 4 criteria column in the topic matrix: + +* Size +* Duration +* Availability +* Speed + +#### Size + +Refers to the size of the data to be stored. + +#### Duration + +Refers to the length of time for which the data should be stored. + +#### Availability + +Refers to the relative uptime of required by the contract for retrieval of the +stored data. + +#### Speed + +Refers to the throughput desired for retrieval of the stored data. + +### Descriptors + +At the time of writing, there are 3 descriptor opcodes representing *low*, +*medium*, and *high* degrees of the criteria. + +* Low: `0x01` +* Medium: `0x02` +* High: `0x03` + +The ranges represented by these descriptors are advisory and may change based +on network performance and improvements to hardware over time. + +``` +------------------------------------------------------------------------------- +| Descriptor | Size | Duration | Availability | Speed | +|-----------------|-------------|------------|--------------|-----------------| +| Low (`0x01`) | 0mb - 8mb | 0d - 30d | 0% - 50% | 0mbps - 6mbps | +|-----------------|-------------|------------|--------------|-----------------| +| Medium (`0x02`) | 8mb - 16mb | 30d - 90d | 50% - 80% | 6mbps - 12mbps | +|-----------------|-------------|------------|--------------|-----------------| +| High (`0x03`) | 16mb - 32mb | 90d - 270d | 80% - 99% | 12mbps - 32mbps | +------------------------------------------------------------------------------- +``` + +### Topic Format + +When publishing or subscribing to a given topic representing the degrees of +these criteria, nodes must serialize the opcodes as the hex representation of +the bytes in proper sequence. This sequence is defined as: + +``` +prefix|size|duration|availability|speed +``` + +The first byte, "prefix", is the **static identifier** for a contract +publication. Contracts are not the only type of publication shared in the +network, so the prefix acts as a namespace for a type of publication topic. + +**The prefix for a contract publication is:** `0x0f`. + +To illustrate by example, we can determine the proper topic by analyzing the +*use case* for a given file shard. For instance, if we want to store an asset +that is displayed on a web page we can infer the following: + +* The file is small +* The file may change often, so we should only store it for medium duration +* The file needs to always be available +* The file should be transferred quickly + +Using the matrix, we can determine the proper opcode sequence: + +``` +[0x0f, 0x01, 0x02, 0x03, 0x03] +``` + +Serialized as hex, our topic string becomes: + +``` +0f01020303 +``` + +Another example, by contrast, is data *backup*. Data backup is quite different +than the previous example: + +* The file is large (perhaps part of a hard drive backup) +* The file will not change and should be stored long term +* The file will not be accessed often, if ever +* The file does not need to be transferred at high speed + +Using the matrix, we can determine the proper opcode sequence: + +``` +[0x0f, 0x03, 0x03, 0x01, 0x01] +``` + +Serialized as hex, our topic string becomes: + +``` +0f03030101 +``` + +The resulting hex string from the serialized opcode byte sequence should be +used as the `topic` parameter of a `PUBLISH` RPC as defined in the +{@tutorial protocol-spec}. Nodes that are subscribed to the topic will receive +the proposed storage contract and may begin contract negotiation with you +directly. + +## data transfer + +Transfering file shards to farmers is a simple process. After a successful +`CONSIGN` or `RETRIEVE` RPC yields a token, the renter may construct an HTTP +request to the farmer, to push or pull the data. + +#### Uploading Shards + +To upload a shard to a given farmer, construct an HTTP request: + +* Method: `POST` +* Path: `/shards/{hash}?token={token}` +* Headers: + * `content-type: application/octet-stream` + * `x-storj-node-id: {farmer node id}` + +Then simply write the encrypted shard to the request. Farmers will respond with +appropriate status codes and messages to indicate the result. + +#### Downloading Shards + +To download a shard from a given farmer, construct an HTTP request: + +* Method: `GET` +* Path: `/shards/{hash}?token={token}` +* Headers: + * `content-type: application/octet-stream` + * `x-storj-node-id: {farmer node id}` + +You will receive the shard as a response of type `application/octet-stream` if +you are authorized. + +## file encryption + +This document serves to provide a detailed account of how files are encrypted +by default by Storj Core to promote interoperability between different +implementations of clients. + +### Sharding and Encryption Scheme + +Before data is stored in the network, the Storj Core library automatically +handles file encryption, sharding, and key management for you. + +In order of operations: + +1. Complete file is encrypted with a unique key and initialization vector +2. File is demultiplexed (or "sharded") into individual chunks +3. Each shard is offered to the network and transferred +4. Key and IV are encrypted with a passphrase and stored locally + +### Key and Initialization Vector Generation + +Files are encrypted using [AES-256-CTR](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard). Use +of CTR allows for random read-access to known indices. File `keys` are +generated via one of two methods: + +* Local PBKDF2 key derivation (default) +* Passphrase-based deterministic key derivation (recommended) + +### PBKDF2 Key Derivation + +By default, the `key` for each file is the result of a standard key derivation +function, [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2). PBKDF2 generates a +key from a password and a salt. These two values are randomly generated bytes: + +* Password: 512 random bytes +* Salt: 32 random bytes + +The key length of the PBKDF2 is 512 bytes, should use 25000 iterations, and use +SHA-512 as the digest. To create the cipher/decipher and initialization vector, +derive the SHA-256 hash of the resulting PBKDF2 for the cipher/decipher `key` +and use the first 16 bytes of the original salt as the `iv`. The +{@link DataCipherKeyIv} class represents these values, and provides methods for +their generation. + +The {@link KeyRing} class stores the original `password` and `salt` locally in +an encrypted JSON document keyed by the ObjectId returned from +[Storj Bridge](https://github.com/Storj/bridge) for the file object. The +cleartext JSON document has two properties: `pass` and `salt`. + +``` +{ + "pass": "c7c311ee213d10baefd620a004d76485190d82...", + "salt": "6d33490c999e9d613ccf4b146446763df15de2..." +} +``` + +This JSON string is encrypted with AES-256-CBC using a user-defined passphrase, +and encoded as [Base58](https://en.wikipedia.org/wiki/Base58). Each of those +encrypted JSON documents is stored in a directory called `key.ring/`, where the +file name is the ObjectId returned from [Storj Bridge](https://github.com/Storj/bridge) for the file object. + +### Portable Key Ring Format + +Because the keys in the key ring are generated and stored locally, files +encrypted with these keys cannot be accessed by other machines without first +duplicating the key files onto that machine. To mitigate this, Storj Core can +create a simple portable key ring archive. + +A {@link KeyRing} created by Storj Core can be exported into a portable format, +which is simply a gzipped tape archive (`.tar.gz` or `.tgz`). Importing this +archive simply entails: + +1. Decompress and unpack the archive +2. Decrypt each JSON document using the original passphrase +3. Encrypt each document with the passphrase of the target keyring +4. Move the files into the target keyring, optionally overwriting conflicts + +### Passphrase-based Key Derivation + +Rather than relying on locally-generated keys, it is recommended that the user +generate a high-entropy passphrase, and generate keys from it via a +deterministic key derivation process. Using this method, the user may grant +access to all encrypted files by simply transferring the passphrase. Storj Core +offers tools for this based on Bitcoin's BIP39 Mnemonic passphrases. + +{@link KeyRing} provides tools for generating a mnemonic passphrase and +writing it to disk. If a mnemonic is found, Storj Core will prefer +passphrase-based key derivation to PBKDF2 derivation. Storj clients should +create a file key as follows: + +1. Prepend the passphrase to the Bucket ID +2. Calculate the `sha512` hash of the resulting string +3. Take the first 64 bits of the resulting hash to make the **Bucket Key** +4. Prepend the Bucket Key to the File ID +5. Calculate the `sha512` hash of the resulting string +6. Take the first 64 bits of the resulting hash to make the **File Key** + +As any client with access to the passphrase can easily generate file keys on +demand, this provides additional portability of files between machines and +applications. + +It is strongly recommended that users write down the passphrase, and keep it in +a secure place. + +### Public Bucket Key Storage + +Public Buckets are a feature of Bridge, not a feature of Storj. When a Public +Bucket is created, the Bucket Key is stored with Bridge. It is then provided to +clients requesting PUSH or PULL tokens from that bucket. + +## tunnel connections + +One of the most daunting problems to tackle when designing a stable and +reliable distributed network is the traversal of various constraints such as +NAT and firewalls. In some cases, software can use various strategies to +"punch out" of these constraints and become publicly addressable on the +Internet. The StorjCORE library makes use of these strategies, but when they +fail we must devise more complex tactics for ensuring that network participants +are reachable by their peers. + +The Storj protocol defines a series of RPC messages that can be exchanged +in order to establish a "tunnel". See the {@tutorial protocol-spec} for more +detail on these RPC messages and their purposes. A tunnel is, in essence, a +proxy that allows a client that is not exposed to the Internet to be +addressable as if it were. + +This works by a private node opening a long-lived connection to a public node +who establishes a dedicated means for accepting messages on behalf of the +private node and "pipes" any data received via those means directly back to the +private node over the previously established connection. + +Once a tunnel has been established, the private node can begin identifying +herself to the network using her tunnel's address, instead of her own. Private +nodes do not need to use the tunnel to contact other nodes on the network, but +rather only *to be contacted*. + +### Announcing Willingness + +When a node joins the network and is publicly addressable, it has the ability +to announce to the network that it is willing and capable of tunneling +connections on behalf on nodes who are private or unable to punch out to +become addressable on the Internet. The process of doing this uses the same +publish/subscribe system described in the {@tutorial contract-topics} +specification which enables nodes to maintain a view of subscriptions in their +neighborhood of the network as described in the {@tutorial protocol-spec}. + +The difference between a contract publication and a tunnel announcement is in +the opcode used for the topic and in the contents of the publication. Tunnel +announcement publications use the opcode prefix `0x0e` followed by a single +criteria degree opcode to indicate their willingness to tunnel (`0x00` to +indicate "I am no longer tunneling" and `0x01` to indicate "I am ready to +tunnel"). + +Whenever the condition changes, such as a node's maximum number of tunnels is +reached or when a tunnel becomes available, it should issue a `PUBLISH` RPC +message to it's nearest neighbors. + +``` +{ + "method": "PUBLISH", + "params": { + "uuid": "7f0c40a2-e465-4f3e-b617-3d53460e34f7", + "topic": "0e01", + "contents": { + "address": "10.0.0.2", + "port": 1337 + }, + "publishers": [ + "48dc026fa01ae26822bfb23f98e725444d6775b0" + ], + "ttl": 1455228597837, + "contact": { + "address": "10.0.0.2", + "port": 1337, + "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0", + "protocol": "0.6.0" + }, + "nonce": 1455216323786, + "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..." + }, + "id": "7b6a2ab35da6826995abf3310a4875097df88cdb" +} +``` + +Public nodes should subscribe to these topics so that they can maintain an +up-to-date list of nodes who are capable and willing to tunnel connections, so +they can respond accurately to `FIND_TUNNEL` messages from private nodes. + +### Establishing a Tunnel + +After a private node has discovered some willing tunnels using the `FIND_TUNNEL` +RPC message defined in the {@tutorial protocol-spec}, it can now begin the +handshake to establish the tunnel. This begins by sending the `OPEN_TUNNEL` RPC +message to the desired tunneler node. The recipient of `OPEN_TUNNEL` will +check: + +* Do I have enough remaining tunnels? (based on arbitrary limit set by node) +* Am I already tunneling for this nodeID? +* Has a payment channel been opened? (**future spec**) + +If the tunneling node has enough tunnels, is not already tunneling the node, +and (in a future spec) if a payment channel has been opened for bandwidth, then +the tunneling node opens a new dedicated TCP socket on an available port +that will be used by the requester to send/receive HTTP messages. + +``` +{ + "result": { + "proxyPort": 12000, + "contact": { + "address": "10.0.0.3", + "port": 1337, + "nodeID": "48dc026fa01ae26822bfb23f98e725444d6775b0", + "protocol": "0.6.0" + }, + "nonce": 1455216323786, + "signature": "304502207e8a439f2cb33055e0b2e2d90e775f29d90b3ad85aec0c..." + }, + "id": "7b6a2ab35da6826995abf3310a4875097df88cdb" +} +``` + +Now the private node can open a TCP connect to the `proxyPort` provided and +messages sent to the tunneler that specify your node ID in the +`x-storj-node-id` header will be written to the connected socket. From there, +you may pipe this socket directly to your locally running node. + +![tunnel diagram](assets/images/tunneling.png) + +## private testnet + +Setting up a private or partitioned version of the Storj network is very simple. +The Storj protocol requires the inclusion of a `protocol` property nested +inside the `contact` data included in every RPC message. See +{@tutorial protocol-spec} for more information on the RPC message format. + +### Protocol Identifier Format + +Nodes on the Storj network identify the version of the protocol they are +running with the use of a [semantic version](http://semver.org/) tag. When a +node is trying to determine whether or not another node is compatible with her +version of the protocol, she checks the following: + +* Is the `MAJOR` version the same? +* Is the `MAJOR` version `0`? +* Is the `MINOR` version the same? + +If both nodes are running the *same* `MAJOR` version and that version is +**not** `0`, then the nodes are compatible. If the `MAJOR` version **is** `0`, +then the nodes are compatible *only* if the `MINOR` version is the same. + +For example: + +* `0.5.1` **is** compatible with `0.5.3` +* `0.5.1` **is not** compatible with `0.6.0` +* `1.5.1` **is** compatible with `1.13.0` +* `2.1.0` **is not** compatible with `1.13.0` + +### Special Identifiers + +The semantic versions specification also allows for special identifiers by +postfixing the version with a hyphen followed by some identifier. This is where +the network partitioning magic happens. + +Let's say, for example, I work for "Widgets Ltd" and I want to deploy a Storj +network within the Widgets Ltd private network. Every workstation would run a +modified version of [`storj/farmer`](https://github.com/storj/farmer) or maybe +my own custom interface built atop `storj/core`. + +I would simply change my Storj-based software to use the version +`1.5.0-widgetsltd`. The Storj protocol sees this identifies as a *strict* match +and therefore any nodes running this version of the software will only +communicate with nodes running the **exact** protocol identifier. + +### Changing the Version + +Changing the version in `storj/core` is easy as pie. In your code, simply +import the module and change the identifier like so: + +``` +// Import core library +var storj = require('storj'); + +// Modify protocol version +storj.version.protocol = '1.5.0-widgetsltd'; + +// Get on with your stuff... +``` + +If you are running "vanilla" Storj software, you can change the protocol +version by setting the `STORJ_NETWORK` environment variable. This will add a +postfix to the protocol version, which will partition the network to nodes +that are running that *exact* version: + +``` +STORJ_NETWORK=testnet storjshare --datadir /path/to/shards +``` + +This concept applies broadly to deploying a custom Storj network for any +purpose. This could be used for a public testnet (`x.x.x-testnet`) or for the +private network example above. + +## environment variables + +Below is a list of environment variables that can be used to alter the +behavior of the core library and associated tooling. + +### `STORJ_NETWORK` + +This value will be postfixed to your announced protocol version in the network. +A value of `testnet` would advertise to the network you are running +`0.7.0-testnet`, which will isolate you to other nodes running the same exact +version. See {@tutorial private-testnet} for more information. + +### `STORJ_ALLOW_LOOPBACK` + +By default, the {@link Network} class will drop and ignore message from nodes +who identify themeselves as a loopback interface like `localhost`, `127.0.0.1`, +etc. This is a security precaution to prevent others from causing you to send +messages to yourself as well as prevent invalid contacts in your routing table. + +To disable this feature (primarily for local testing), set this variable to `1`. + +### `STORJ_BRIDGE` + +This variable will change the default URI for the {@link BridgeClient} class. +The default value is `https://api.storj.io`. If you run your own bridge, +testing one locally, or otherwise would like to default to a different host, +set this variable. + +This works well with the CLI (see {@tutorial command-line-interface}) when +testing against other bridges. + +### `STORJ_KEYPASS` + +This variable will set the `--keypass` used to unlock the keyring. + +Setting your password will make it so other users can't grep it with `ps -a`. + +### `STORJ_TEMP` + +This variable will set the folder to which the encrypted file will be placed +when uploading a file. Shards will also be placed in this folder during upload. + +## command line interface + +This package comes equipped with a command line interface for performing a +number of useful operations on the Storj network. The CLI program is generally +focused on interacting with a remote [Bridge](https://github.com/Storj/bridge) +service and makes use of the library's {@link BridgeClient} class to do so. In +addition to interacting with a bridge node, the tool also exposes some general +purpose utilities. + +To use the CLI, follow the instructions in the [README](https://github.com/Storj/core/blob/master/README.md) to install the module +**globally** or if you are working from within the git repository, you can use: + +``` +npm link +``` + +### Communicating with a Bridge + +Once you have access to the `storj` command, register and authenticate with the +bridge: + +``` +> $ storj register + [...] > Enter your email address > user@storj.io + [...] > Enter your password > ************* + + [info] Registered! Check your email to activate your account. +``` + +Follow the activation link you receive via email and come back to the CLI to +pair with your account: + +``` +> $ storj login + [...] > Enter your email address > user@storj.io + [...] > Enter your password > ************* + + [info] This device has been successfully paired. +``` + +Now you can create buckets, transfer files, and manage your bridge account. + +### Audits, Proofs, and Verifications + +The CLI also includes some utility commands for generating file possession +audits, proving possession, and verifying proofs. You can generate a challenge +set and merkle tree for a file easily: + +``` +> $ storj prepare-audits 2 CONTRIBUTING.md + [info] Generating challenges and merkle tree... + [info] + [info] Merkle Root + [info] ----------- + [info] 9c8c37935f58d46e3301efe4f44724b8785a81a5 + [info] + [info] Challenges + [info] ---------- + [info] c8573773616e072230d40131e7ce8537d384825e337e5903ff7367ddea798c52 + [info] 7c4d4f57f40d5c95f962e7cd72347e4077e1885aaffd8c1ccbbd02c8d7c48dce + [info] + [info] Merkle Leaves + [info] ------------- + [info] aaf42766d87a37e6dffbae7172fd0073006bf5f3 + [info] ccee086dbc8a16b93b79912cb37f3b037bbf8269 +``` + +A farmer can use parts of this data to prove possession of a file shard: + +``` +> $ storj prove-file aaf42766d87a37e6dffbae7172fd0073006bf5f3,ccee086dbc8a16b93b79912cb37f3b037bbf8269 c8573773616e072230d40131e7ce8537d384825e337e5903ff7367ddea798c52 CONTRIBUTING.md + [info] Generating proof of possession... + [info] + [info] Challenge Response + [info] ------------------ + [info] [["153a0d4b1d228043992fec585cadb51974b053f7"],"ccee086dbc8a16b93b79912cb37f3b037bbf8269"] +``` + +The result of this operation can be used by the original renter to verify the +the proof and confirm that the farmer still has possession of the file: + +``` +> $ storj verify-proof 9c8c37935f58d46e3301efe4f44724b8785a81a5 2 '[["153a0d4b1d228043992fec585cadb51974b053f7"],"ccee086dbc8a16b93b79912cb37f3b037bbf8269"]' + [info] + [info] Expected: 9c8c37935f58d46e3301efe4f44724b8785a81a5 + [info] Actual: 9c8c37935f58d46e3301efe4f44724b8785a81a5 + [info] + [info] The proof response is valid +``` + +For more detailed usage information of the command line interface, run +`storj --help`. + +### Temporary Files +On Windows temporary files are stored: + +``` +C:\Users\\AppData\Local\Temp +``` + +## license + +> Storj Core - Implementation of the Storj protocol for Node.js +> Copyright (C) 2016 Storj Labs, Inc + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +*Certain parts of this program are licensed under the GNU Lesser General +Public License as published by the Free Software Foundation. You can +redistribute it and/or modify it under the terms either version 3 of the +License, or (at your option) any later version.* + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see +[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/). diff --git a/Storj/core/doc/assets/tunneling.png b/Storj/protocol-v2/assets/images/tunneling.png similarity index 100% rename from Storj/core/doc/assets/tunneling.png rename to Storj/protocol-v2/assets/images/tunneling.png diff --git a/Storj/core/bench/index.js b/Storj/protocol-v2/bench/index.js similarity index 100% rename from Storj/core/bench/index.js rename to Storj/protocol-v2/bench/index.js diff --git a/Storj/core/example/1-create-user.js b/Storj/protocol-v2/example/1-create-user.js similarity index 100% rename from Storj/core/example/1-create-user.js rename to Storj/protocol-v2/example/1-create-user.js diff --git a/Storj/core/example/2-generate-keypair.js b/Storj/protocol-v2/example/2-generate-keypair.js similarity index 100% rename from Storj/core/example/2-generate-keypair.js rename to Storj/protocol-v2/example/2-generate-keypair.js diff --git a/Storj/core/example/3-authenticate-with-keypair.js b/Storj/protocol-v2/example/3-authenticate-with-keypair.js similarity index 100% rename from Storj/core/example/3-authenticate-with-keypair.js rename to Storj/protocol-v2/example/3-authenticate-with-keypair.js diff --git a/Storj/core/example/4a-list-keys.js b/Storj/protocol-v2/example/4a-list-keys.js similarity index 100% rename from Storj/core/example/4a-list-keys.js rename to Storj/protocol-v2/example/4a-list-keys.js diff --git a/Storj/core/example/4b-add-remove-keys.js b/Storj/protocol-v2/example/4b-add-remove-keys.js similarity index 100% rename from Storj/core/example/4b-add-remove-keys.js rename to Storj/protocol-v2/example/4b-add-remove-keys.js diff --git a/Storj/core/example/5a-list-buckets.js b/Storj/protocol-v2/example/5a-list-buckets.js similarity index 100% rename from Storj/core/example/5a-list-buckets.js rename to Storj/protocol-v2/example/5a-list-buckets.js diff --git a/Storj/core/example/5b-add-remove-bucket.js b/Storj/protocol-v2/example/5b-add-remove-bucket.js similarity index 100% rename from Storj/core/example/5b-add-remove-bucket.js rename to Storj/protocol-v2/example/5b-add-remove-bucket.js diff --git a/Storj/core/example/6a-upload-file.js b/Storj/protocol-v2/example/6a-upload-file.js similarity index 100% rename from Storj/core/example/6a-upload-file.js rename to Storj/protocol-v2/example/6a-upload-file.js diff --git a/Storj/core/example/6b-download-file.js b/Storj/protocol-v2/example/6b-download-file.js similarity index 100% rename from Storj/core/example/6b-download-file.js rename to Storj/protocol-v2/example/6b-download-file.js diff --git a/Storj/core/example/6c-list-bucket-files.js b/Storj/protocol-v2/example/6c-list-bucket-files.js similarity index 100% rename from Storj/core/example/6c-list-bucket-files.js rename to Storj/protocol-v2/example/6c-list-bucket-files.js diff --git a/Storj/core/example/6d-delete-file-from-bucket.js b/Storj/protocol-v2/example/6d-delete-file-from-bucket.js similarity index 100% rename from Storj/core/example/6d-delete-file-from-bucket.js rename to Storj/protocol-v2/example/6d-delete-file-from-bucket.js diff --git a/Storj/core/index.js b/Storj/protocol-v2/index.js similarity index 100% rename from Storj/core/index.js rename to Storj/protocol-v2/index.js diff --git a/Storj/core/lib/audit-tools/audit-stream.js b/Storj/protocol-v2/lib/audit-tools/audit-stream.js similarity index 100% rename from Storj/core/lib/audit-tools/audit-stream.js rename to Storj/protocol-v2/lib/audit-tools/audit-stream.js diff --git a/Storj/core/lib/audit-tools/proof-stream.js b/Storj/protocol-v2/lib/audit-tools/proof-stream.js similarity index 100% rename from Storj/core/lib/audit-tools/proof-stream.js rename to Storj/protocol-v2/lib/audit-tools/proof-stream.js diff --git a/Storj/core/lib/audit-tools/verification.js b/Storj/protocol-v2/lib/audit-tools/verification.js similarity index 100% rename from Storj/core/lib/audit-tools/verification.js rename to Storj/protocol-v2/lib/audit-tools/verification.js diff --git a/Storj/core/lib/bridge-client/blacklist.js b/Storj/protocol-v2/lib/bridge-client/blacklist.js similarity index 100% rename from Storj/core/lib/bridge-client/blacklist.js rename to Storj/protocol-v2/lib/bridge-client/blacklist.js diff --git a/Storj/core/lib/bridge-client/exchange-report.js b/Storj/protocol-v2/lib/bridge-client/exchange-report.js similarity index 100% rename from Storj/core/lib/bridge-client/exchange-report.js rename to Storj/protocol-v2/lib/bridge-client/exchange-report.js diff --git a/Storj/core/lib/bridge-client/index.js b/Storj/protocol-v2/lib/bridge-client/index.js similarity index 100% rename from Storj/core/lib/bridge-client/index.js rename to Storj/protocol-v2/lib/bridge-client/index.js diff --git a/Storj/core/lib/bridge-client/upload-state.js b/Storj/protocol-v2/lib/bridge-client/upload-state.js similarity index 100% rename from Storj/core/lib/bridge-client/upload-state.js rename to Storj/protocol-v2/lib/bridge-client/upload-state.js diff --git a/Storj/core/lib/constants.js b/Storj/protocol-v2/lib/constants.js similarity index 100% rename from Storj/core/lib/constants.js rename to Storj/protocol-v2/lib/constants.js diff --git a/Storj/core/lib/contract/index.js b/Storj/protocol-v2/lib/contract/index.js similarity index 100% rename from Storj/core/lib/contract/index.js rename to Storj/protocol-v2/lib/contract/index.js diff --git a/Storj/core/lib/contract/offer-manager.js b/Storj/protocol-v2/lib/contract/offer-manager.js similarity index 100% rename from Storj/core/lib/contract/offer-manager.js rename to Storj/protocol-v2/lib/contract/offer-manager.js diff --git a/Storj/core/lib/contract/offer-stream.js b/Storj/protocol-v2/lib/contract/offer-stream.js similarity index 100% rename from Storj/core/lib/contract/offer-stream.js rename to Storj/protocol-v2/lib/contract/offer-stream.js diff --git a/Storj/core/lib/contract/schema.json b/Storj/protocol-v2/lib/contract/schema.json similarity index 100% rename from Storj/core/lib/contract/schema.json rename to Storj/protocol-v2/lib/contract/schema.json diff --git a/Storj/core/lib/crypto-tools/cipher-key-iv.js b/Storj/protocol-v2/lib/crypto-tools/cipher-key-iv.js similarity index 100% rename from Storj/core/lib/crypto-tools/cipher-key-iv.js rename to Storj/protocol-v2/lib/crypto-tools/cipher-key-iv.js diff --git a/Storj/core/lib/crypto-tools/decrypt-stream.js b/Storj/protocol-v2/lib/crypto-tools/decrypt-stream.js similarity index 100% rename from Storj/core/lib/crypto-tools/decrypt-stream.js rename to Storj/protocol-v2/lib/crypto-tools/decrypt-stream.js diff --git a/Storj/core/lib/crypto-tools/deterministic-key-iv.js b/Storj/protocol-v2/lib/crypto-tools/deterministic-key-iv.js similarity index 100% rename from Storj/core/lib/crypto-tools/deterministic-key-iv.js rename to Storj/protocol-v2/lib/crypto-tools/deterministic-key-iv.js diff --git a/Storj/core/lib/crypto-tools/encrypt-stream.js b/Storj/protocol-v2/lib/crypto-tools/encrypt-stream.js similarity index 100% rename from Storj/core/lib/crypto-tools/encrypt-stream.js rename to Storj/protocol-v2/lib/crypto-tools/encrypt-stream.js diff --git a/Storj/core/lib/crypto-tools/keypair.js b/Storj/protocol-v2/lib/crypto-tools/keypair.js similarity index 100% rename from Storj/core/lib/crypto-tools/keypair.js rename to Storj/protocol-v2/lib/crypto-tools/keypair.js diff --git a/Storj/core/lib/crypto-tools/keyring.js b/Storj/protocol-v2/lib/crypto-tools/keyring.js similarity index 100% rename from Storj/core/lib/crypto-tools/keyring.js rename to Storj/protocol-v2/lib/crypto-tools/keyring.js diff --git a/Storj/core/lib/deps.js b/Storj/protocol-v2/lib/deps.js similarity index 100% rename from Storj/core/lib/deps.js rename to Storj/protocol-v2/lib/deps.js diff --git a/Storj/core/lib/file-handling/file-demuxer.js b/Storj/protocol-v2/lib/file-handling/file-demuxer.js similarity index 100% rename from Storj/core/lib/file-handling/file-demuxer.js rename to Storj/protocol-v2/lib/file-handling/file-demuxer.js diff --git a/Storj/core/lib/file-handling/file-muxer.js b/Storj/protocol-v2/lib/file-handling/file-muxer.js similarity index 100% rename from Storj/core/lib/file-handling/file-muxer.js rename to Storj/protocol-v2/lib/file-handling/file-muxer.js diff --git a/Storj/core/lib/network/contact.js b/Storj/protocol-v2/lib/network/contact.js similarity index 100% rename from Storj/core/lib/network/contact.js rename to Storj/protocol-v2/lib/network/contact.js diff --git a/Storj/core/lib/network/farmer.js b/Storj/protocol-v2/lib/network/farmer.js similarity index 100% rename from Storj/core/lib/network/farmer.js rename to Storj/protocol-v2/lib/network/farmer.js diff --git a/Storj/core/lib/network/index.js b/Storj/protocol-v2/lib/network/index.js similarity index 100% rename from Storj/core/lib/network/index.js rename to Storj/protocol-v2/lib/network/index.js diff --git a/Storj/core/lib/network/monitor.js b/Storj/protocol-v2/lib/network/monitor.js similarity index 100% rename from Storj/core/lib/network/monitor.js rename to Storj/protocol-v2/lib/network/monitor.js diff --git a/Storj/core/lib/network/protocol.js b/Storj/protocol-v2/lib/network/protocol.js similarity index 100% rename from Storj/core/lib/network/protocol.js rename to Storj/protocol-v2/lib/network/protocol.js diff --git a/Storj/core/lib/network/renter.js b/Storj/protocol-v2/lib/network/renter.js similarity index 100% rename from Storj/core/lib/network/renter.js rename to Storj/protocol-v2/lib/network/renter.js diff --git a/Storj/core/lib/network/shard-server.js b/Storj/protocol-v2/lib/network/shard-server.js similarity index 100% rename from Storj/core/lib/network/shard-server.js rename to Storj/protocol-v2/lib/network/shard-server.js diff --git a/Storj/core/lib/network/transport.js b/Storj/protocol-v2/lib/network/transport.js similarity index 100% rename from Storj/core/lib/network/transport.js rename to Storj/protocol-v2/lib/network/transport.js diff --git a/Storj/core/lib/patches.js b/Storj/protocol-v2/lib/patches.js similarity index 100% rename from Storj/core/lib/patches.js rename to Storj/protocol-v2/lib/patches.js diff --git a/Storj/core/lib/sips/0003/index.js b/Storj/protocol-v2/lib/sips/0003/index.js similarity index 100% rename from Storj/core/lib/sips/0003/index.js rename to Storj/protocol-v2/lib/sips/0003/index.js diff --git a/Storj/core/lib/sips/0003/trigger-manager.js b/Storj/protocol-v2/lib/sips/0003/trigger-manager.js similarity index 100% rename from Storj/core/lib/sips/0003/trigger-manager.js rename to Storj/protocol-v2/lib/sips/0003/trigger-manager.js diff --git a/Storj/core/lib/sips/index.js b/Storj/protocol-v2/lib/sips/index.js similarity index 100% rename from Storj/core/lib/sips/index.js rename to Storj/protocol-v2/lib/sips/index.js diff --git a/Storj/core/lib/storage/adapter.js b/Storj/protocol-v2/lib/storage/adapter.js similarity index 100% rename from Storj/core/lib/storage/adapter.js rename to Storj/protocol-v2/lib/storage/adapter.js diff --git a/Storj/core/lib/storage/adapters/embedded.js b/Storj/protocol-v2/lib/storage/adapters/embedded.js similarity index 100% rename from Storj/core/lib/storage/adapters/embedded.js rename to Storj/protocol-v2/lib/storage/adapters/embedded.js diff --git a/Storj/core/lib/storage/adapters/ram.js b/Storj/protocol-v2/lib/storage/adapters/ram.js similarity index 100% rename from Storj/core/lib/storage/adapters/ram.js rename to Storj/protocol-v2/lib/storage/adapters/ram.js diff --git a/Storj/core/lib/storage/item.js b/Storj/protocol-v2/lib/storage/item.js similarity index 100% rename from Storj/core/lib/storage/item.js rename to Storj/protocol-v2/lib/storage/item.js diff --git a/Storj/core/lib/storage/manager.js b/Storj/protocol-v2/lib/storage/manager.js similarity index 100% rename from Storj/core/lib/storage/manager.js rename to Storj/protocol-v2/lib/storage/manager.js diff --git a/Storj/core/lib/storage/migration.js b/Storj/protocol-v2/lib/storage/migration.js similarity index 100% rename from Storj/core/lib/storage/migration.js rename to Storj/protocol-v2/lib/storage/migration.js diff --git a/Storj/core/lib/utils.js b/Storj/protocol-v2/lib/utils.js similarity index 100% rename from Storj/core/lib/utils.js rename to Storj/protocol-v2/lib/utils.js diff --git a/Storj/core/lib/version.js b/Storj/protocol-v2/lib/version.js similarity index 100% rename from Storj/core/lib/version.js rename to Storj/protocol-v2/lib/version.js diff --git a/Storj/core/package-lock.json b/Storj/protocol-v2/package-lock.json similarity index 100% rename from Storj/core/package-lock.json rename to Storj/protocol-v2/package-lock.json diff --git a/Storj/core/package.json b/Storj/protocol-v2/package.json similarity index 100% rename from Storj/core/package.json rename to Storj/protocol-v2/package.json diff --git a/Storj/core/test/.eslintrc b/Storj/protocol-v2/test/.eslintrc similarity index 100% rename from Storj/core/test/.eslintrc rename to Storj/protocol-v2/test/.eslintrc diff --git a/Storj/core/test/audit-tools/audit-stream.unit.js b/Storj/protocol-v2/test/audit-tools/audit-stream.unit.js similarity index 100% rename from Storj/core/test/audit-tools/audit-stream.unit.js rename to Storj/protocol-v2/test/audit-tools/audit-stream.unit.js diff --git a/Storj/core/test/audit-tools/proof-stream.unit.js b/Storj/protocol-v2/test/audit-tools/proof-stream.unit.js similarity index 100% rename from Storj/core/test/audit-tools/proof-stream.unit.js rename to Storj/protocol-v2/test/audit-tools/proof-stream.unit.js diff --git a/Storj/core/test/audit-tools/verification.unit.js b/Storj/protocol-v2/test/audit-tools/verification.unit.js similarity index 100% rename from Storj/core/test/audit-tools/verification.unit.js rename to Storj/protocol-v2/test/audit-tools/verification.unit.js diff --git a/Storj/core/test/bridge-client/blacklist.unit.js b/Storj/protocol-v2/test/bridge-client/blacklist.unit.js similarity index 100% rename from Storj/core/test/bridge-client/blacklist.unit.js rename to Storj/protocol-v2/test/bridge-client/blacklist.unit.js diff --git a/Storj/core/test/bridge-client/exchange-report.unit.js b/Storj/protocol-v2/test/bridge-client/exchange-report.unit.js similarity index 100% rename from Storj/core/test/bridge-client/exchange-report.unit.js rename to Storj/protocol-v2/test/bridge-client/exchange-report.unit.js diff --git a/Storj/core/test/bridge-client/index.unit.js b/Storj/protocol-v2/test/bridge-client/index.unit.js similarity index 100% rename from Storj/core/test/bridge-client/index.unit.js rename to Storj/protocol-v2/test/bridge-client/index.unit.js diff --git a/Storj/core/test/bridge-client/upload-state.unit.js b/Storj/protocol-v2/test/bridge-client/upload-state.unit.js similarity index 100% rename from Storj/core/test/bridge-client/upload-state.unit.js rename to Storj/protocol-v2/test/bridge-client/upload-state.unit.js diff --git a/Storj/core/test/contract/index.unit.js b/Storj/protocol-v2/test/contract/index.unit.js similarity index 100% rename from Storj/core/test/contract/index.unit.js rename to Storj/protocol-v2/test/contract/index.unit.js diff --git a/Storj/core/test/contract/offer-manager.unit.js b/Storj/protocol-v2/test/contract/offer-manager.unit.js similarity index 100% rename from Storj/core/test/contract/offer-manager.unit.js rename to Storj/protocol-v2/test/contract/offer-manager.unit.js diff --git a/Storj/core/test/contract/offer-stream.unit.js b/Storj/protocol-v2/test/contract/offer-stream.unit.js similarity index 100% rename from Storj/core/test/contract/offer-stream.unit.js rename to Storj/protocol-v2/test/contract/offer-stream.unit.js diff --git a/Storj/core/test/crypto-tools/cipher-key-iv.unit.js b/Storj/protocol-v2/test/crypto-tools/cipher-key-iv.unit.js similarity index 100% rename from Storj/core/test/crypto-tools/cipher-key-iv.unit.js rename to Storj/protocol-v2/test/crypto-tools/cipher-key-iv.unit.js diff --git a/Storj/core/test/crypto-tools/deterministic-key-iv.unit.js b/Storj/protocol-v2/test/crypto-tools/deterministic-key-iv.unit.js similarity index 100% rename from Storj/core/test/crypto-tools/deterministic-key-iv.unit.js rename to Storj/protocol-v2/test/crypto-tools/deterministic-key-iv.unit.js diff --git a/Storj/core/test/crypto-tools/encrypt-stream+decrypt-stream.unit.js b/Storj/protocol-v2/test/crypto-tools/encrypt-stream+decrypt-stream.unit.js similarity index 100% rename from Storj/core/test/crypto-tools/encrypt-stream+decrypt-stream.unit.js rename to Storj/protocol-v2/test/crypto-tools/encrypt-stream+decrypt-stream.unit.js diff --git a/Storj/core/test/crypto-tools/keypair.unit.js b/Storj/protocol-v2/test/crypto-tools/keypair.unit.js similarity index 100% rename from Storj/core/test/crypto-tools/keypair.unit.js rename to Storj/protocol-v2/test/crypto-tools/keypair.unit.js diff --git a/Storj/core/test/crypto-tools/keyring.unit.js b/Storj/protocol-v2/test/crypto-tools/keyring.unit.js similarity index 100% rename from Storj/core/test/crypto-tools/keyring.unit.js rename to Storj/protocol-v2/test/crypto-tools/keyring.unit.js diff --git a/Storj/core/test/file-handling/file-demuxer.unit.js b/Storj/protocol-v2/test/file-handling/file-demuxer.unit.js similarity index 100% rename from Storj/core/test/file-handling/file-demuxer.unit.js rename to Storj/protocol-v2/test/file-handling/file-demuxer.unit.js diff --git a/Storj/core/test/file-handling/file-muxer.unit.js b/Storj/protocol-v2/test/file-handling/file-muxer.unit.js similarity index 100% rename from Storj/core/test/file-handling/file-muxer.unit.js rename to Storj/protocol-v2/test/file-handling/file-muxer.unit.js diff --git a/Storj/core/test/network/contact.unit.js b/Storj/protocol-v2/test/network/contact.unit.js similarity index 100% rename from Storj/core/test/network/contact.unit.js rename to Storj/protocol-v2/test/network/contact.unit.js diff --git a/Storj/core/test/network/farmer.unit.js b/Storj/protocol-v2/test/network/farmer.unit.js similarity index 100% rename from Storj/core/test/network/farmer.unit.js rename to Storj/protocol-v2/test/network/farmer.unit.js diff --git a/Storj/core/test/network/index.unit.js b/Storj/protocol-v2/test/network/index.unit.js similarity index 100% rename from Storj/core/test/network/index.unit.js rename to Storj/protocol-v2/test/network/index.unit.js diff --git a/Storj/core/test/network/monitor.unit.js b/Storj/protocol-v2/test/network/monitor.unit.js similarity index 100% rename from Storj/core/test/network/monitor.unit.js rename to Storj/protocol-v2/test/network/monitor.unit.js diff --git a/Storj/core/test/network/protocol.unit.js b/Storj/protocol-v2/test/network/protocol.unit.js similarity index 100% rename from Storj/core/test/network/protocol.unit.js rename to Storj/protocol-v2/test/network/protocol.unit.js diff --git a/Storj/core/test/network/renter.unit.js b/Storj/protocol-v2/test/network/renter.unit.js similarity index 100% rename from Storj/core/test/network/renter.unit.js rename to Storj/protocol-v2/test/network/renter.unit.js diff --git a/Storj/core/test/network/shard-server.unit.js b/Storj/protocol-v2/test/network/shard-server.unit.js similarity index 100% rename from Storj/core/test/network/shard-server.unit.js rename to Storj/protocol-v2/test/network/shard-server.unit.js diff --git a/Storj/core/test/network/transport.unit.js b/Storj/protocol-v2/test/network/transport.unit.js similarity index 100% rename from Storj/core/test/network/transport.unit.js rename to Storj/protocol-v2/test/network/transport.unit.js diff --git a/Storj/core/test/sips/0003/trigger-manager.unit.js b/Storj/protocol-v2/test/sips/0003/trigger-manager.unit.js similarity index 100% rename from Storj/core/test/sips/0003/trigger-manager.unit.js rename to Storj/protocol-v2/test/sips/0003/trigger-manager.unit.js diff --git a/Storj/core/test/storage/adapter.unit.js b/Storj/protocol-v2/test/storage/adapter.unit.js similarity index 100% rename from Storj/core/test/storage/adapter.unit.js rename to Storj/protocol-v2/test/storage/adapter.unit.js diff --git a/Storj/core/test/storage/adapters/embedded.unit.js b/Storj/protocol-v2/test/storage/adapters/embedded.unit.js similarity index 100% rename from Storj/core/test/storage/adapters/embedded.unit.js rename to Storj/protocol-v2/test/storage/adapters/embedded.unit.js diff --git a/Storj/core/test/storage/adapters/ram.unit.js b/Storj/protocol-v2/test/storage/adapters/ram.unit.js similarity index 100% rename from Storj/core/test/storage/adapters/ram.unit.js rename to Storj/protocol-v2/test/storage/adapters/ram.unit.js diff --git a/Storj/core/test/storage/item.unit.js b/Storj/protocol-v2/test/storage/item.unit.js similarity index 100% rename from Storj/core/test/storage/item.unit.js rename to Storj/protocol-v2/test/storage/item.unit.js diff --git a/Storj/core/test/storage/manager.unit.js b/Storj/protocol-v2/test/storage/manager.unit.js similarity index 100% rename from Storj/core/test/storage/manager.unit.js rename to Storj/protocol-v2/test/storage/manager.unit.js diff --git a/Storj/core/test/storage/migration.unit.js b/Storj/protocol-v2/test/storage/migration.unit.js similarity index 100% rename from Storj/core/test/storage/migration.unit.js rename to Storj/protocol-v2/test/storage/migration.unit.js diff --git a/Storj/core/test/utils.unit.js b/Storj/protocol-v2/test/utils.unit.js similarity index 100% rename from Storj/core/test/utils.unit.js rename to Storj/protocol-v2/test/utils.unit.js diff --git a/Storj/core/test/version.unit.js b/Storj/protocol-v2/test/version.unit.js similarity index 100% rename from Storj/core/test/version.unit.js rename to Storj/protocol-v2/test/version.unit.js

)CdQ3F!eKyF|9D2V!F-rhUpJ8J+l7g0OBBVM#THTI&O8)>EGR%u6Gd9D9pm5!S}%&6DxW}^f|7=Y zPoO3(pTZY#?(7(|!5}5Nn!D%DotZmlW)?smSMcEE<^aT$6gw#LlwubPI9BYTffL0! zyu-EPCnz{Y#ZR&1d{F!hr_NW!&#~mXis$jseXDo@U)-kR7sMBeUt-T&RQw9By@BF9 z3f?cpmw4m-R{RHncaC**(V--ipJ<~6LkW2fi6RVfh%vcYt9@z>&M0LBSf-Q|Et8wU zCt43_*JB)mHR71wb`K@~5Cizwp{`A2uuJ^_Bcl3k{7ree$8&@l?;^2nagS+NqCDBfkB?pJws=PbK~+A7|2 z{gCDJKI-i%m4LD$n{WIwWR|c+NRy`C1#)1sSBI7FiH6z-QkhY&Q_|%I3exQ zQ`X1M?cZH4^M&BSyr;2z$+^SZUMA*0001Z+HKHROw(}?!13=vX`$@Br+fGR zZ%e`5O6%Txi$Yrz0gF{}p>fY>OnlS0Uevf}oDXW;D{d2gcE<2)oFcV80@g$H)63L{HN*d{8kVzKVW(;E)$9N_%kx5Ku3R9WJbY?JW^G#k0Wdx>E$NBBVtKRLiL?sA*s%w`TdsNz1=+~FRNdB8&+@iBD0 zXFTC4C-8-Cwv(4U=LLQ~^Oa4^rG|OTr5?ItoaPMYxxh`%a*kVU z;HYGAjq6;IY{`*awo0DlOMw(hkrYdb(O28l;MYvSx*ChcQW4f^QL5UdE3HbqvbxB$pfSg`>Cj#;?~00;nMAg}==M6d%RaIhCe zARtS)01i=0um)3FSgr#ump{<1pq_<0a34Kp8x=7I1^|9 diff --git a/Storj/core/docs/fonts/OpenSans-Regular-webfont.eot b/Storj/core/docs/fonts/OpenSans-Regular-webfont.eot deleted file mode 100644 index 6bbc3cf58cb011a6b4bf3cb1612ce212608f7274..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19836 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Storj/core/docs/fonts/OpenSans-Regular-webfont.woff b/Storj/core/docs/fonts/OpenSans-Regular-webfont.woff deleted file mode 100644 index e231183dce4c7b452afc9e7799586fd285e146f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22660 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 ML;wL%uV=LY00kR;TmS$7 diff --git a/Storj/core/docs/index.html b/Storj/core/docs/index.html deleted file mode 100644 index 7281073..0000000 --- a/Storj/core/docs/index.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - JSDoc: Home - - - - - - - - - - -