diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index abf138d264..602d5b588d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,6 +14,7 @@ defaults: env: RUSTFLAGS: --deny warnings + LANGUAGES: zh ja jobs: docs: @@ -21,10 +22,22 @@ jobs: steps: - uses: actions/checkout@v2 + + - name: Install Rust Toolchain Components + uses: actions-rs/toolchain@v1 + with: + override: true + toolchain: stable + + - uses: Swatinem/rust-cache@v2 + - uses: peaceiris/actions-mdbook@v1 with: mdbook-version: latest + - name: Install mdbook-i18n-helpers + run: cargo install mdbook-i18n-helpers + - name: Install mdbook-linkcheck run: | mkdir -p mdbook-linkcheck @@ -34,7 +47,18 @@ jobs: chmod +x mdbook-linkcheck pwd >> $GITHUB_PATH - - run: mdbook build docs + - name: Build docs + run: mdbook build docs -d build + + - name: Build all translations for docs + run: | + for lang in ${{ env.LANGUAGES }}; do + echo "::group::Building $lang translation" + MDBOOK_BOOK__LANGUAGE=$lang \ + mdbook build docs -d build/$lang + mv docs/build/$lang/html docs/build/html/$lang + echo "::endgroup::" + done - name: Deploy Pages uses: peaceiris/actions-gh-pages@v3 @@ -43,6 +67,7 @@ jobs: github_token: ${{secrets.GITHUB_TOKEN}} publish_branch: gh-pages publish_dir: docs/build/html + lint: runs-on: ubuntu-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 2379827477..cdcf3b5df3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,47 @@ Changelog ========= +[0.9.0](https://github.com/ordinals/ord/releases/tag/0.9.0) - 2023-09-11 +------------------------------------------------------------------------ + +### Added + +- Allow reinscribing with wallet (#2432) +- Provide more detailed translation instructions (#2443) +- Add Japanese version of handbook (#2426) +- Add provenance to docs summary (#2427) +- Inscribe with parent (#2388) +- Add provenance spec (#2278) +- Implement provenance in index (#2353) +- Add application/protobuf media type (#2389) +- Install mdbook-i18n-helpers in Github Workflows (#2408) +- Add `decode` command (#2401) +- Add Chinese version of the handbook (#2406) +- Add language picker for docs (#2403) +- Add reindexing docs (#2393) +- Vaccuum log with every new deploy (#2390) + +### Changed + +- Fold BlockIndex into database (#2436) +- Prevent search when query field is empty (#2425) +- Make any zero-valued input inscription unbound (#2397) +- Tweak translations intructions (#2413) +- Remove unused itertools dependency (#2416) +- Update dependencies (#2414) +- Update clap (#2415) +- Use tapscript extraction from rust-bitcoin (#2404) +- Allocate blocks vector ahead of time (#2409) +- Deduplicate sat range summation logic (#2402) +- Inscriptions with unrecognized even fields are unbound and cursed (#2359) +- Remove unused content_response match statement (#2384) + +### Fixed + +- Fix type (#2444) +- Fix Chinese translation typos and format errors (#2419) +- Fix UTXO selection in mock Bitcoin Core instance(#2417) + [0.8.3](https://github.com/ordinals/ord/releases/tag/0.8.3) - 2023-08-28 ------------------------------------------------------------------------ diff --git a/Cargo.lock b/Cargo.lock index f235c1474e..b6a0e08f3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" dependencies = [ "memchr", ] @@ -56,11 +56,59 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "anyhow" -version = "1.0.72" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" dependencies = [ "backtrace", ] @@ -84,7 +132,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.23", + "time 0.3.28", ] [[package]] @@ -123,9 +171,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.3.15" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" +checksum = "d495b6dc0184693324491a5ac05f559acc97bf937ab31d7a1c33dd0016be6d2b" dependencies = [ "brotli", "flate2", @@ -154,7 +202,7 @@ dependencies = [ "async-lock", "async-task", "concurrent-queue", - "fastrand", + "fastrand 1.9.0", "futures-lite", "slab", ] @@ -218,15 +266,15 @@ dependencies = [ "polling", "rustix 0.37.23", "slab", - "socket2", + "socket2 0.4.9", "waker-fn", ] [[package]] name = "async-lock" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ "event-listener", ] @@ -295,20 +343,20 @@ checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" [[package]] name = "async-trait" -version = "0.1.72" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.29", ] [[package]] name = "atom_syndication" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca96cb38e3d8236f1573a84bbc55e130bd1ae07df770e36d0cf221ea7a50e36c" +checksum = "571832dcff775e26562e8e6930cd483de5587301d40d3a3b85d532b6383e15a7" dependencies = [ "chrono", "derive_builder", @@ -323,17 +371,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -342,9 +379,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.19" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a1de45611fdb535bfde7b7de4fd54f4fd2b17b1737c0a59b69bf9b92074b8c" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", @@ -412,9 +449,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -433,9 +470,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" [[package]] name = "bech32" @@ -526,9 +563,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "block-buffer" @@ -549,23 +586,23 @@ dependencies = [ "async-lock", "async-task", "atomic-waker", - "fastrand", + "fastrand 1.9.0", "futures-lite", "log", ] [[package]] name = "boilerplate" -version = "0.2.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e7294fa817b2deee8867b77bc4d378523240b5dddecdd9f11fd08187503048" +checksum = "1906889b1f805a715eac02b2dea416e25c5cfa00f099530fa9d137a3cff93113" dependencies = [ - "darling", + "darling 0.20.3", "mime", "new_mime_guess", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.29", ] [[package]] @@ -591,9 +628,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" dependencies = [ "memchr", "serde", @@ -619,9 +656,12 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -637,9 +677,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f" dependencies = [ "android-tzdata", "iana-time-zone", @@ -647,47 +687,54 @@ dependencies = [ "num-traits", "time 0.1.45", "wasm-bindgen", - "winapi", + "windows-targets 0.48.5", ] [[package]] name = "clap" -version = "3.2.25" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" dependencies = [ - "atty", - "bitflags 1.3.2", + "clap_builder", "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +dependencies = [ + "anstream", + "anstyle", "clap_lex", - "indexmap 1.9.3", - "once_cell", "strsim", - "termcolor", - "textwrap", ] [[package]] name = "clap_derive" -version = "3.2.25" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.29", ] [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "concurrent-queue" @@ -820,8 +867,18 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core 0.20.3", + "darling_macro 0.20.3", ] [[package]] @@ -838,17 +895,42 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.29", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", "quote", "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core 0.20.3", + "quote", + "syn 2.0.29", +] + [[package]] name = "data-encoding" version = "2.4.0" @@ -869,6 +951,12 @@ dependencies = [ "rusticata-macros", ] +[[package]] +name = "deranged" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" + [[package]] name = "derive_builder" version = "0.12.0" @@ -884,7 +972,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro2", "quote", "syn 1.0.109", @@ -967,14 +1055,14 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.29", ] [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encode_unicode" @@ -984,9 +1072,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if 1.0.0", ] @@ -1012,9 +1100,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" dependencies = [ "errno-dragonfly", "libc", @@ -1052,11 +1140,17 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ "crc32fast", "miniz_oxide", @@ -1146,7 +1240,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", @@ -1163,7 +1257,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.29", ] [[package]] @@ -1249,15 +1343,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "globset" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" dependencies = [ "aho-corasick", "bstr", @@ -1280,9 +1374,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes", "fnv", @@ -1311,12 +1405,11 @@ checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" [[package]] name = "headers" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" +checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.13.1", - "bitflags 1.3.2", + "base64 0.21.3", "bytes", "headers-core", "http", @@ -1340,15 +1433,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.2" @@ -1397,9 +1481,9 @@ dependencies = [ [[package]] name = "http-range-header" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "http-types" @@ -1429,9 +1513,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" @@ -1456,7 +1540,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -1537,9 +1621,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.5" +version = "0.17.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff8cc23a7393a397ed1d7f56e6365cba772aba9f9912ab968b03043c395d057" +checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730" dependencies = [ "console", "instant", @@ -1569,7 +1653,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi", "libc", "windows-sys 0.48.0", ] @@ -1586,20 +1670,11 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.2", - "rustix 0.38.4", + "hermit-abi", + "rustix 0.38.11", "windows-sys 0.48.0", ] -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.9" @@ -1716,9 +1791,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "lock_api" @@ -1732,24 +1807,24 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" dependencies = [ "value-bag", ] [[package]] name = "matchit" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" [[package]] name = "memoffset" @@ -1814,9 +1889,9 @@ dependencies = [ [[package]] name = "mp4" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509348cba250e7b852a875100a2ddce7a36ee3abf881a681c756670c1774264d" +checksum = "c9ef834d5ed55e494a2ae350220314dc4aacd1c43a9498b00e320e0ea352a5c3" dependencies = [ "byteorder", "bytes", @@ -1873,14 +1948,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if 1.0.0", "libc", - "static_assertions", ] [[package]] @@ -1904,9 +1978,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", @@ -1938,9 +2012,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] @@ -1951,7 +2025,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi", "libc", ] @@ -1963,9 +2037,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" dependencies = [ "memchr", ] @@ -1987,11 +2061,11 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "cfg-if 1.0.0", "foreign-types", "libc", @@ -2008,7 +2082,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.29", ] [[package]] @@ -2019,9 +2093,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b" dependencies = [ "cc", "libc", @@ -2037,13 +2111,13 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "ord-litecoin" -version = "0.8.3" +version = "0.9.0" dependencies = [ "anyhow", "async-trait", "axum", "axum-server", - "base64 0.21.2", + "base64 0.21.3", "bech32", "bip39", "bitcoin", @@ -2062,7 +2136,6 @@ dependencies = [ "http", "hyper", "indicatif", - "itertools", "lazy_static", "log", "mime", @@ -2091,12 +2164,6 @@ dependencies = [ "unindent", ] -[[package]] -name = "os_str_bytes" -version = "6.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" - [[package]] name = "parking" version = "2.1.0" @@ -2145,29 +2212,29 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.29", ] [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -2199,9 +2266,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.4.1" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc55135a600d700580e406b4de0d59cb9ad25e344a3a091a97ded2622ec4ec6" +checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" [[package]] name = "ppv-lite86" @@ -2228,30 +2295,6 @@ dependencies = [ "toml", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.66" @@ -2285,9 +2328,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.28.2" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" dependencies = [ "encoding_rs", "memchr", @@ -2295,9 +2338,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -2403,7 +2446,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring", - "time 0.3.23", + "time 0.3.28", "yasna", ] @@ -2448,9 +2491,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.1" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" dependencies = [ "aho-corasick", "memchr", @@ -2460,9 +2503,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" dependencies = [ "aho-corasick", "memchr", @@ -2471,17 +2514,17 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" dependencies = [ - "base64 0.21.2", + "base64 0.21.3", "bytes", "encoding_rs", "futures-core", @@ -2529,9 +2572,9 @@ dependencies = [ [[package]] name = "rss" -version = "2.0.4" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9acf62e0f3f4b52f61d3a12d6279e3f0b90d4811b0ae888eabdf61a2e7c03a95" +checksum = "7e6c0ea0e621c2a3aa34850ebd711526f0ac7385921f57d2430a47cecc7b9cbc" dependencies = [ "atom_syndication", "derive_builder", @@ -2541,9 +2584,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "6.8.1" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a36224c3276f8c4ebc8c20f158eca7ca4359c8db89991c4925132aaaf6702661" +checksum = "b1e7d90385b59f0a6bf3d3b757f3ca4ece2048265d70db20a2016043d4509a40" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -2552,22 +2595,22 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "6.8.1" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac" +checksum = "3c3d8c6fd84090ae348e63a84336b112b5c3918b3bf0493a581f7bd8ee623c29" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.26", + "syn 2.0.29", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "7.8.1" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74" +checksum = "873feff8cb7bf86fdf0a71bb21c95159f4e4a37dd7a4bd1855a940909b583ada" dependencies = [ "sha2", "walkdir", @@ -2613,26 +2656,26 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.4" +version = "0.38.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "errno", "libc", - "linux-raw-sys 0.4.3", + "linux-raw-sys 0.4.5", "windows-sys 0.48.0", ] [[package]] name = "rustls" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ "log", "ring", - "rustls-webpki 0.101.1", + "rustls-webpki 0.101.4", "sct", ] @@ -2673,14 +2716,14 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.2", + "base64 0.21.3", ] [[package]] name = "rustls-webpki" -version = "0.100.1" +version = "0.100.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" dependencies = [ "ring", "untrusted", @@ -2688,9 +2731,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.1" +version = "0.101.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e" +checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" dependencies = [ "ring", "untrusted", @@ -2765,9 +2808,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -2778,9 +2821,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -2794,29 +2837,29 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "serde" -version = "1.0.171" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.29", ] [[package]] name = "serde_json" -version = "1.0.103" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" +checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" dependencies = [ "itoa", "ryu", @@ -2858,9 +2901,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.24" +version = "0.9.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5f51e3fdb5b9cdd1577e1cb7a733474191b1aca6a72c2e50913241632c1180" +checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" dependencies = [ "indexmap 2.0.0", "itoa", @@ -2893,9 +2936,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b824b6e687aff278cdbf3b36f07aa52d4bd4099699324d5da86a2ebce3aa00b3" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" dependencies = [ "libc", "signal-hook-registry", @@ -2921,9 +2964,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -2962,16 +3005,20 @@ dependencies = [ ] [[package]] -name = "spin" -version = "0.5.2" +name = "socket2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] [[package]] -name = "static_assertions" -version = "1.1.0" +name = "spin" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "strsim" @@ -2992,9 +3039,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.26" +version = "2.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" dependencies = [ "proc-macro2", "quote", @@ -3021,9 +3068,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.29.5" +version = "0.29.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b949f01f9c23823744b71e0060472ecbde578ef68cc2a9e46d114efd77c3034" +checksum = "a8d0e9cc2273cc8d31377bdd638d72e3ac3e5607b18621062b169d02787f1bab" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -3036,21 +3083,20 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.9" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8e77cb757a61f51b947ec4a7e3646efd825b73561db1c232a8ccb639e611a0" +checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" [[package]] name = "tempfile" -version = "3.6.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ - "autocfg", "cfg-if 1.0.0", - "fastrand", + "fastrand 2.0.0", "redox_syscall 0.3.5", - "rustix 0.37.23", + "rustix 0.38.11", "windows-sys 0.48.0", ] @@ -3078,30 +3124,24 @@ dependencies = [ "serde_json", ] -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.29", ] [[package]] @@ -3117,10 +3157,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.23" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" dependencies = [ + "deranged", "itoa", "serde", "time-core", @@ -3135,9 +3176,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" dependencies = [ "time-core", ] @@ -3159,18 +3200,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.3", "tokio-macros", "windows-sys 0.48.0", ] @@ -3183,7 +3223,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.29", ] [[package]] @@ -3273,12 +3313,12 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8bd22a874a2d0b70452d5597b12c537331d49060824a95f49f108994f94aa4c" +checksum = "55ae70283aba8d2a8b411c695c437fe25b8b5e44e23e780662002fc72fb47a82" dependencies = [ "async-compression", - "bitflags 2.3.3", + "bitflags 2.4.0", "bytes", "futures-core", "futures-util", @@ -3339,9 +3379,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] @@ -3399,9 +3439,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", @@ -3409,6 +3449,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "value-bag" version = "1.4.1" @@ -3491,7 +3537,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.29", "wasm-bindgen-shared", ] @@ -3525,7 +3571,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.29", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3552,7 +3598,7 @@ version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" dependencies = [ - "rustls-webpki 0.100.1", + "rustls-webpki 0.100.2", ] [[package]] @@ -3592,7 +3638,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -3610,7 +3656,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -3630,17 +3676,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -3651,9 +3697,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -3663,9 +3709,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -3675,9 +3721,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -3687,9 +3733,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -3699,9 +3745,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -3711,9 +3757,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -3723,17 +3769,18 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if 1.0.0", + "windows-sys 0.48.0", ] [[package]] @@ -3751,7 +3798,7 @@ dependencies = [ "oid-registry", "rusticata-macros", "thiserror", - "time 0.3.23", + "time 0.3.28", ] [[package]] @@ -3766,5 +3813,5 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.23", + "time 0.3.28", ] diff --git a/Cargo.toml b/Cargo.toml index 423664a487..030f9a1d34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ord-litecoin" description = "◉ Ordinal wallet and block explorer for litecoin" -version = "0.8.3" +version = "0.9.0" license = "CC0-1.0" edition = "2021" autotests = false @@ -22,9 +22,9 @@ base64 = "0.21.0" bech32 = "0.9.1" bip39 = "2.0.0" bitcoin = { version = "0.30.0", features = ["rand"] } -boilerplate = { version = "0.2.3", features = ["axum"] } +boilerplate = { version = "1.0.0", features = ["axum"] } chrono = "0.4.19" -clap = { version = "3.2.18", features = ["derive", "deprecated"] } +clap = { version = "4.4.2", features = ["derive"] } ctrlc = { version = "3.2.1", features = ["termination"] } derive_more = "0.99.17" dirs = "5.0.0" @@ -35,18 +35,17 @@ html-escaper = "0.2.0" http = "0.2.6" hyper = { version = "0.14.24", features = ["http1", "client"] } indicatif = "0.17.1" -itertools = "0.11.0" lazy_static = "1.4.0" log = "0.4.14" mime = "0.3.16" mime_guess = "2.0.4" miniscript = "10.0.0" -mp4 = "0.13.0" +mp4 = "0.14.0" bitcoincore-rpc = "0.17.0" redb = "1.0.5" regex = "1.6.0" rss = "2.0.1" -rust-embed = "6.4.0" +rust-embed = "8.0.0" rustls = "0.21.1" rustls-acme = { version = "0.7.1", features = ["axum"] } serde = { version = "1.0.137", features = ["derive"] } @@ -62,7 +61,7 @@ tower-http = { version = "0.4.0", features = ["compression-br", "compression-gzi [dev-dependencies] executable-path = "1.0.0" pretty_assertions = "1.2.1" -reqwest = { version = "0.11.10", features = ["blocking"] } +reqwest = { version = "0.11.10", features = ["blocking", "json"] } test-bitcoincore-rpc = { path = "test-bitcoincore-rpc" } unindent = "0.2.1" diff --git a/README.md b/README.md index 307bea4647..1fab164857 100644 --- a/README.md +++ b/README.md @@ -249,3 +249,60 @@ Release x.y.z - Update dependencies - Update database schema version ``` + +Translations +------------ + +To translate [the docs](https://docs.ordinals.com) we use this +[mdBook i18n helper](https://github.com/google/mdbook-i18n-helpers). +So read through their [usage guide](https://github.com/google/mdbook-i18n-helpers/blob/main/USAGE.md) +to see the structure that translations should follow. + +There are some other things to watch out for but feel free to just start a +translation and open a PR. Have a look at [this commit](https://github.com/ordinals/ord/commit/329f31bf6dac207dad001507dd6f18c87fdef355) +for an idea of what to do. A maintainer will also help you integrate it into our +build system. + +To align your translated version of the Handbook with reference to commit +[#2427](https://github.com/ordinals/ord/pull/2426), here are some guiding +commands to assist you. It is assumed that your local environment is already +well-configured with [Python](https://www.python.org/), +[Mdbook](https://github.com/rust-lang/mdBook), +[mdBook i18n helper](https://github.com/rust-lang/mdbb) and that you've clone +this repo. + + +1. Run the following command to generate a new `pot` file, which is named as +`messages.pot`: + +``` +MDBOOK_OUTPUT='{"xgettext": {"pot-file": "messages.pot"}}' +mdbook build -d po +``` + +2. Run `msgmerge` where `xx.po` is your localized language version following +the naming standard of [ISO639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes). +This process will update the `po` file with the most recent original version: + +``` +msgmerge --update po/xx.po po/messages.pot +``` + +3. Look for `#, fuzzy`. The `mdBook-i18n-helper` tool utilizes the `"fuzzy"` tag +to highlight sections that have been recently edited. You can proceed to perform +the translation tasks by editing the `"fuzzy"`part. + +4. Execute the `mdbook` command. A demonstration in Chinese (`zh`) is given below: + +``` +mdbook build docs -d build +MDBOOK_BOOK__LANGUAGE=zh mdbook build docs -d build/zh +mv docs/build/zh/html docs/build/html/zh +python3 -m http.server --directory docs/build/html --bind 127.0.0.1 8080 +``` + +5. Upon verifying everything and ensuring all is in order, you can commit the +modifications and progress to open a Pull Request (PR) on Github. +(**Note**: Please ensure **ONLY** the **'xx.po'** file is pushed, other files +such as '.pot' or files ending in '~' are **unnecessary** and should **NOT** be +included in the Pull Request.) diff --git a/deploy/setup b/deploy/setup index 5092768519..c615bb600e 100755 --- a/deploy/setup +++ b/deploy/setup @@ -120,6 +120,8 @@ setfacl -m ord:x $COOKIE_FILE_DIR setfacl -dm ord:r $COOKIE_FILE_DIR setfacl -m ord:r $COOKIE_FILE_DIR/.cookie +journalctl --unit ord --vacuum-time 1s + cp deploy/ord.service /etc/systemd/system/ systemctl daemon-reload systemctl enable ord diff --git a/docs/book.toml b/docs/book.toml index 184e9c6b9b..8b8dc9e8e6 100644 --- a/docs/book.toml +++ b/docs/book.toml @@ -6,11 +6,16 @@ src = "src" [build] build-dir = "build" create-missing = false +extra-watch-dirs = ["po"] [output.html] cname = "docs.ordinals.com" default-theme = "coal" git-repository-url = "https://github.com/ordinals/ord" preferred-dark-theme = "coal" +additional-css = ["language-picker.css"] [output.linkcheck] + +[preprocessor.gettext] +after = ["links"] diff --git a/docs/language-picker.css b/docs/language-picker.css new file mode 100644 index 0000000000..1f7d5377e1 --- /dev/null +++ b/docs/language-picker.css @@ -0,0 +1,8 @@ +#language-list { + left: auto; + right: 10px; +} + +#language-list a { + color: inherit; +} diff --git a/docs/po/ja.po b/docs/po/ja.po new file mode 100644 index 0000000000..c1e1b20baf --- /dev/null +++ b/docs/po/ja.po @@ -0,0 +1,4675 @@ +msgid "" +msgstr "" +"Project-Id-Version: 序数理論マニュアル\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2023-09-06 10:03+0800\n" +"Last-Translator: Dr.JingLee @ordjingle \n" +"Language-Team: Japanese\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: src/SUMMARY.md:2 src/introduction.md:1 +msgid "Introduction" +msgstr "紹介" + +#: src/SUMMARY.md:3 +msgid "Overview" +msgstr "概要" + +#: src/SUMMARY.md:4 src/digital-artifacts.md:1 +msgid "Digital Artifacts" +msgstr "数字文物" + +#: src/SUMMARY.md:5 src/SUMMARY.md:12 src/overview.md:221 src/inscriptions.md:1 +msgid "Inscriptions" +msgstr "銘文" + +#: src/SUMMARY.md:6 src/inscriptions/recursion.md:1 +msgid "Recursion" +msgstr "再帰" + +#: src/SUMMARY.md:7 +msgid "FAQ" +msgstr "一般的問題" + +#: src/SUMMARY.md:8 +msgid "Contributing" +msgstr "貢献" + +#: src/SUMMARY.md:9 src/donate.md:1 +msgid "Donate" +msgstr "寄付" + +#: src/SUMMARY.md:10 +msgid "Guides" +msgstr "ガイド" + +#: src/SUMMARY.md:11 +msgid "Explorer" +msgstr "ブラウザ" + +#: src/SUMMARY.md:13 src/guides/sat-hunting.md:1 +msgid "Sat Hunting" +msgstr "聡狩り" + +#: src/SUMMARY.md:14 src/guides/collecting.md:1 +msgid "Collecting" +msgstr "コレクション" + +#: src/SUMMARY.md:15 src/guides/sat-hunting.md:239 +msgid "Sparrow Wallet" +msgstr "雀のウォレット" + +#: src/SUMMARY.md:16 src/guides/testing.md:1 +msgid "Testing" +msgstr "テスティング" + +#: src/SUMMARY.md:17 src/guides/moderation.md:1 +msgid "Moderation" +msgstr "調節" + +#: src/SUMMARY.md:18 src/guides/reindexing.md:1 +msgid "Reindexing" +msgstr "再インデックス" + +#: src/SUMMARY.md:19 +msgid "Bounties" +msgstr "賞金" + +#: src/SUMMARY.md:20 +msgid "Bounty 0: 100,000 sats Claimed!" +msgstr "ミッション 0: 100,000 sats 完成!" + +#: src/SUMMARY.md:21 +msgid "Bounty 1: 200,000 sats Claimed!" +msgstr "ミッション 1: 200,000 sats 完成!" + +#: src/SUMMARY.md:22 +msgid "Bounty 2: 300,000 sats Claimed!" +msgstr "ミッション 2: 300,000 sats 完成!" + +#: src/SUMMARY.md:23 +msgid "Bounty 3: 400,000 sats" +msgstr "ミッション 3: 400,000 sats" + +#: src/introduction.md:4 +msgid "" +"This handbook is a guide to ordinal theory. Ordinal theory concerns itself " +"with satoshis, giving them individual identities and allowing them to be " +"tracked, transferred, and imbued with meaning." +msgstr "このマニュアルは序数理論の(Ordinals Theory)ガイドです。 序数理論は聡を注目され(Satoshi)、彼らに独立な身分を付与され、追跡され、移行され、意義を付与されます。" + +#: src/introduction.md:8 +msgid "" +"Satoshis, not bitcoin, are the atomic, native currency of the Bitcoin " +"network. One bitcoin can be sub-divided into 100,000,000 satoshis, but no " +"further." +msgstr "" +"聡は(Satoshi),ビットコインではなく、ビットコインのインタネットのネイティブ貨幣と最小の単位です。" +"一つのビットコインは100,000,000聡を細分されますが、これ以上細分できません。" + +#: src/introduction.md:11 +msgid "" +"Ordinal theory does not require a sidechain or token aside from Bitcoin, and " +"can be used without any changes to the Bitcoin network. It works right now." +msgstr "" +"序数理論はビットコインブロックチェーン以外のサイドチェーンまたはトークンが必要ではなく、ビットコインインターネットに何も変更しない場合にも使うことができます。" +"すぐに使うことができます。" + +#: src/introduction.md:14 +msgid "" +"Ordinal theory imbues satoshis with numismatic value, allowing them to be " +"collected and traded as curios." +msgstr "序数理論は聡にコレックション価値に与えられ、骨董品としてコレックションし、取引をすることができます。" + +#: src/introduction.md:17 +msgid "" +"Individual satoshis can be inscribed with arbitrary content, creating unique " +"Bitcoin-native digital artifacts that can be held in Bitcoin wallets and " +"transferred using Bitcoin transactions. Inscriptions are as durable, " +"immutable, secure, and decentralized as Bitcoin itself." +msgstr "" +"一つの聡はどんな内容でも刻むことができます。独特なビットコインネイティブ数字文物(Digital Artifact)を作り上げ、" +"ビットコインウォレットの中に保存して、ビットコインの取引で送信することができます。" +"銘文(Inscription)はビットコインのように一样長持ちして、永久、安全と分散化されます。" + +#: src/introduction.md:22 +msgid "" +"Other, more unusual use-cases are possible: off-chain colored-coins, public " +"key infrastructure with key rotation, a decentralized replacement for the " +"DNS. For now though, such use-cases are speculative, and exist only in the " +"minds of fringe ordinal theorists." +msgstr "" +"他の非正規の応用でも可能となり、チェーンの下の染色コインはシークレットキー交替の公開キーのインフラがあります。" +"DNSの分散化の代替品などです。 " +"今のところこういう応用は推測的で、非主流の序数の理論家の頭だけに存在しています" + +#: src/introduction.md:27 +msgid "For more details on ordinal theory, see the [overview](overview.md)." +msgstr "序数理論のより多くの詳細な情報について, [概述](overview.md)を閲見してください。" + +#: src/introduction.md:29 +msgid "For more details on inscriptions, see [inscriptions](inscriptions.md)." +msgstr "銘文のより多くの詳細な情報について、 [銘文](inscriptions.md)を閲見してください。" + +#: src/introduction.md:31 +msgid "" +"When you're ready to get your hands dirty, a good place to start is with " +"[inscriptions](guides/inscriptions.md), a curious species of digital " +"artifact enabled by ordinal theory." +msgstr "" +"準備ができて、自分でする時に、銘文は良いなスタートです。[銘文](guides/inscriptions.md)" +"序数理論で支持した独特な数字文物です。" + +#: src/introduction.md:35 +msgid "Links" +msgstr "リンク" + +#: src/introduction.md:38 +msgid "[GitHub](https://github.com/ordinals/ord/)" +msgstr "[GitHub倉庫](https://github.com/ordinals/ord/)" + +#: src/introduction.md:39 +msgid "[BIP](https://github.com/ordinals/ord/blob/master/bip.mediawiki)" +msgstr "[BIP](https://github.com/ordinals/ord/blob/master/bip.mediawiki)" + +#: src/introduction.md:40 +msgid "[Discord](https://discord.gg/ordinals)" +msgstr "[Discord](https://discord.gg/ordinals)" + +#: src/introduction.md:41 +msgid "[Open Ordinals Institute Website](https://ordinals.org/)" +msgstr "[Open Ordinals Institute ウェブサイト](https://ordinals.org/)" + +#: src/introduction.md:42 +msgid "[Open Ordinals Institute X](https://x.com/ordinalsorg)" +msgstr "[Open Ordinals Institute Xアカウント](https://x.com/ordinalsorg)" + +#: src/introduction.md:43 +msgid "[Mainnet Block Explorer](https://ordinals.com)" +msgstr "[メインネットブロック](https://ordinals.com)" + +#: src/introduction.md:44 +msgid "[Signet Block Explorer](https://signet.ordinals.com)" +msgstr "[Signetブロックブラウザ](https://signet.ordinals.com)" + +#: src/introduction.md:46 +msgid "Videos" +msgstr "動画" + +#: src/introduction.md:49 +msgid "" +"[Ordinal Theory Explained: Satoshi Serial Numbers and NFTs on Bitcoin]" +"(https://www.youtube.com/watch?v=rSS0O2KQpsI)" +msgstr "" +"[序数理論を解釈して: 聡のシリアル番号とビットコインでのNFT]" +"(https://www.youtube.com/watch?v=rSS0O2KQpsI)" + +#: src/introduction.md:50 +msgid "" +"[Ordinals Workshop with Rodarmor](https://www.youtube.com/watch?" +"v=MC_haVa6N3I)" +msgstr "" +"[CaseyRodarmorの序数理論のワークショップ ](https://www.youtube.com/watch?" +"v=MC_haVa6N3I)" + +#: src/introduction.md:51 +msgid "" +"[Ordinal Art: Mint Your own NFTs on Bitcoin w/ @rodarmor](https://www." +"youtube.com/watch?v=j5V33kV3iqo)" +msgstr "" +"[序数の芸術:ビットコインの上で自分のNFTを鋳造します。 w/ @rodarmor](https://www." +"youtube.com/watch?v=j5V33kV3iqo)" + +#: src/overview.md:1 +msgid "Ordinal Theory Overview" +msgstr "序数理論の概要" + +#: src/overview.md:4 +msgid "" +"Ordinals are a numbering scheme for satoshis that allows tracking and " +"transferring individual sats. These numbers are called [ordinal numbers]" +"(https://ordinals.com). Satoshis are numbered in the order in which they're " +"mined, and transferred from transaction inputs to transaction outputs first-" +"in-first-out. Both the numbering scheme and the transfer scheme rely on " +"_order_, the numbering scheme on the _order_ in which satoshis are mined, " +"and the transfer scheme on the _order_ of transaction inputs and outputs. " +"Thus the name, _ordinals_." +msgstr "" +"序数は一つのビットコインの番号プランであり、一つの聡を追跡し、移転することができます。これらの数字はシリアル番号といいます。(https://ordinals.com)。" +"ビットコインはそれらの発掘した順序により番号を書いて、取引輸入から取引輸出まで移行します(先入れ先出しの原則に従います)。" +"番号プランと転送プランは順序に依存して、番号プランはビットコインが発掘された順序に依存し、転送プランは取引の輸入と輸出に順序に依存します。" +"ここで_序数と呼ばれます(Ordinals_。" + +#: src/overview.md:13 +msgid "" +"Technical details are available in [the BIP](https://github.com/ordinals/ord/" +"blob/master/bip.mediawiki)." +msgstr "" +"技術的な詳細は[the BIP](https://github.com/ordinals/ord/blob/master/bip.mediawiki)で獲得することができます." + +#: src/overview.md:16 +msgid "" +"Ordinal theory does not require a separate token, another blockchain, or any " +"changes to Bitcoin. It works right now." +msgstr "" +"序数理論は独特なトークン、独特なブロックチェーン、またはビットコインにどんな変更でも必要ではなくて、すぐに有効的に運行することができません。" + +#: src/overview.md:19 +msgid "Ordinal numbers have a few different representations:" +msgstr "" +"シリアル番号はいくつか異なる表示方式があります" + +#: src/overview.md:21 +msgid "" +"_Integer notation_: [`2099994106992659`](https://ordinals.com/" +"sat/2099994106992659) The ordinal number, assigned according to the order in " +"which the satoshi was mined." +msgstr "" +"_整数符号_:[`2099994106992659`](https://ordinals.com/sat/2099994106992659) " +"このシリアル番号は発掘された聡の順序に従って分配されます。" + + +#: src/overview.md:26 +msgid "" +"_Decimal notation_: [`3891094.16797`](https://ordinals.com/" +"sat/3891094.16797) The first number is the block height in which the satoshi " +"was mined, the second the offset of the satoshi within the block." +msgstr "" +"_十進法符号n_: [`3891094.16797`](https://ordinals.com/" +"sat/3891094.16797) 最初の数字は聡のブロック高度を発掘され、 " +"二番目の数字はブロック内の聡の定常偏差です。" + +#: src/overview.md:31 +msgid "" +"_Degree notation_: [`3°111094′214″16797‴`](https://ordinals.com/" +"sat/3%C2%B0111094%E2%80%B2214%E2%80%B316797%E2%80%B4). We'll get to that in " +"a moment." +msgstr "" +"_度数符号_: [`3°111094′214″16797‴`](https://ordinals.com/" +"sat/3%C2%B0111094%E2%80%B2214%E2%80%B316797%E2%80%B4). " +"それについてはすぐに説明します。" + +#: src/overview.md:35 +msgid "" +"_Percentile notation_: [`99.99971949060254%`](https://ordinals.com/" +"sat/99.99971949060254%25) . The satoshi's position in Bitcoin's supply, " +"expressed as a percentage." +msgstr "" +"_パーセント_: [`99.99971949060254%`](https://ordinals.com/" +"sat/99.99971949060254%25) . パーセントで聡がビットコイン供給の中の位置を示します" + +#: src/overview.md:39 +msgid "" +"_Name_: [`satoshi`](https://ordinals.com/sat/satoshi). An encoding of the " +"ordinal number using the characters `a` through `z`." +msgstr "" +"_名前_: [`satoshi`](https://ordinals.com/sat/satoshi). " +"一つのアルファベットaからbまでのシリアル番号にコーディングを書く方法です。" + +#: src/overview.md:42 +msgid "" +"Arbitrary assets, such as NFTs, security tokens, accounts, or stablecoins " +"can be attached to satoshis using ordinal numbers as stable identifiers." +msgstr "" +"任意の資産、例えばNFT、セキュリティトークン、アカウントまたは安定した貨幣、 " +"序数を使って、安定した標識符号として、聡に付けます。" + +#: src/overview.md:45 +msgid "" +"Ordinals is an open-source project, developed [on GitHub](https://github.com/" +"ordinals/ord). The project consists of a BIP describing the ordinal scheme, " +"an index that communicates with a Bitcoin Core node to track the location of " +"all satoshis, a wallet that allows making ordinal-aware transactions, a " +"block explorer for interactive exploration of the blockchain, functionality " +"for inscribing satoshis with digital artifacts, and this manual." +msgstr "" +"Ordinalsはオープンソースプロジェクトです、[on GitHub](https://github.com/" +"ordinals/ord)に配置されます. このプロジェクトは序数プランを記述するBIPを含まれます。 " +"ビットコインのコアノードと通信して、すべての聡を追跡した索引です" +"シリアル番号の感知取引を許可するウォレットです。 " +"ブロックチェーンインタラクティブな探索のブロック資源管理プログラム、数字文物で聡の機能及びこのマニュアルを嵌めます。 " + +#: src/overview.md:52 +msgid "Rarity" +msgstr "希少度" + +#: src/overview.md:55 +msgid "" +"Humans are collectors, and since satoshis can now be tracked and " +"transferred, people will naturally want to collect them. Ordinal theorists " +"can decide for themselves which sats are rare and desirable, but there are " +"some hints…" +msgstr "" +"人間はコレクターです。現在、聡は追跡、移行されることができて、人々は聡をコレクションしたいです。 " +"序数理論家は自分でどちらの聡が珍しい聡と合意的な聡であることを決めます。 " +"ヒントがあります…" + +#: src/overview.md:59 +msgid "" +"Bitcoin has periodic events, some frequent, some more uncommon, and these " +"naturally lend themselves to a system of rarity. These periodic events are:" +msgstr "" +"ビットコインは周期的な事件があり、頻繫的なのはあるし、一般的なのはあります。これらの事件は自然にレア度システムが形成されます。" +"この周期的な事件は:" + +#: src/overview.md:62 +msgid "" +"_Blocks_: A new block is mined approximately every 10 minutes, from now " +"until the end of time." +msgstr "" +"_ブロック_: 現在から終わるまで10分ごとに新たなブロックを発掘されます。" + +#: src/overview.md:65 +msgid "" +"_Difficulty adjustments_: Every 2016 blocks, or approximately every two " +"weeks, the Bitcoin network responds to changes in hashrate by adjusting the " +"difficulty target which blocks must meet in order to be accepted." +msgstr "" +"_難易度調整_: 2016個ごとのブロック、または約二週間ごとです " +"ビットコインインターネットはブロックが難易度の目標に満足させることを調整して、ハッシュレートの変化に対応します。 " + + +#: src/overview.md:69 +msgid "" +"_Halvings_: Every 210,000 blocks, or roughly every four years, the amount of " +"new sats created in every block is cut in half." +msgstr "" +"_半減_: 21万のブロックごとに、または約4年ごとに,各ブロックが生じた新たな聡の数が半減になります。 " + +#: src/overview.md:72 +msgid "" +"_Cycles_: Every six halvings, something magical happens: the halving and the " +"difficulty adjustment coincide. This is called a conjunction, and the time " +"period between conjunctions a cycle. A conjunction occurs roughly every 24 " +"years. The first conjunction should happen sometime in 2032." +msgstr "" +"_周期_6回ごとに半減にするたび不思議なことが起こります。半分にすることと難易度の調整は同時に起こります。" +"これは相合と言います。相合の時間周期は一周期です。 " +"ほぼ24年ごとに一回の相合が起こります、最初の相合は2032年のある時に起こるはずです。 " + +#: src/overview.md:77 +msgid "This gives us the following rarity levels:" +msgstr "" +"以下の希少度のレベルを与えられました:" + +#: src/overview.md:79 +msgid "`common`: Any sat that is not the first sat of its block" +msgstr "`普通`: 全てのそのブロック最初の聡ではないの聡" + +#: src/overview.md:80 +msgid "`uncommon`: The first sat of each block" +msgstr "`普通ではない`: 各ブロックの最初の聡" + +#: src/overview.md:81 +msgid "`rare`: The first sat of each difficulty adjustment period" +msgstr "`珍しく`: 各難易度の調整周期の最初の聡" + +#: src/overview.md:82 +msgid "`epic`: The first sat of each halving epoch" +msgstr "`史詩`: 各半減周期の最初の聡" + +#: src/overview.md:83 +msgid "`legendary`: The first sat of each cycle" +msgstr "`伝奇`: 各循環周期の最初の聡" + +#: src/overview.md:84 +msgid "`mythic`: The first sat of the genesis block" +msgstr "`神話`: 創世ブロックの最初の聡" + +#: src/overview.md:86 +msgid "" +"Which brings us to degree notation, which unambiguously represents an " +"ordinal number in a way that makes the rarity of a satoshi easy to see at a " +"glance:" +msgstr "" +"これは私たちに度数表記法をもたらしました。それは聡の希少性を一目で見ることができる方法で序数を明確に表しています " + +#: src/overview.md:89 +msgid "" +"```\n" +"A°B′C″D‴\n" +"│ │ │ ╰─ Index of sat in the block\n" +"│ │ ╰─── Index of block in difficulty adjustment period\n" +"│ ╰───── Index of block in halving epoch\n" +"╰─────── Cycle, numbered starting from 0\n" +"```" +msgstr "" +"```\n" +"A°B′C″D‴\n" +"│ │ │ ╰─ 聡の索引位置\n" +"│ │ ╰─── 難易度調整期のブロックの位置\n" +"│ ╰───── 半減周期ブロックの索引位置\n" +"╰─────── 循環周期、0の数字からスタートします。\n" +"```" + +#: src/overview.md:97 +msgid "" +"Ordinal theorists often use the terms \"hour\", \"minute\", \"second\", and " +"\"third\" for _A_, _B_, _C_, and _D_, respectively." +msgstr "" +"序理論家通常使用 \"時間\",\"分\"、\"秒\"、そして\"3\" などの対応を専用の言叶は、a、b、_c、と_d_。 " + +#: src/overview.md:100 +msgid "Now for some examples. This satoshi is common:" +msgstr "いくつか例をお見せしましょうこれは普通の聡です" + +#: src/overview.md:102 +msgid "" +"```\n" +"1°1′1″1‴\n" +"│ │ │ ╰─ Not first sat in block\n" +"│ │ ╰─── Not first block in difficulty adjustment period\n" +"│ ╰───── Not first block in halving epoch\n" +"╰─────── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°1′1″1‴\n" +"│ │ │ ╰─ ブロック最初の聡ではない\n" +"│ │ ╰─── 難易度調整周期の最初の聡ではない\n" +"│ ╰───── 半減周期の最初の聡ではない\n" +"╰─────── 二番目の循環周期\n" +"```" + +#: src/overview.md:111 +msgid "This satoshi is uncommon:" +msgstr "これは一般的な聡ではない" + +#: src/overview.md:113 +msgid "" +"```\n" +"1°1′1″0‴\n" +"│ │ │ ╰─ First sat in block\n" +"│ │ ╰─── Not first block in difficulty adjustment period\n" +"│ ╰───── Not first block in halving epoch\n" +"╰─────── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°1′1″0‴\n" +"│ │ │ ╰─ ブロック最初の聡\n" +"│ │ ╰─── 難易度調整周期の最初の聡ではない\n" +"│ ╰───── 半減周期の最初の聡ではない\n" +"╰─────── 二番目の循環周期\n" +"```" + +#: src/overview.md:121 +msgid "This satoshi is rare:" +msgstr "珍しい聡です。" + +#: src/overview.md:123 +msgid "" +"```\n" +"1°1′0″0‴\n" +"│ │ │ ╰─ First sat in block\n" +"│ │ ╰─── First block in difficulty adjustment period\n" +"│ ╰───── Not the first block in halving epoch\n" +"╰─────── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°1′0″0‴\n" +"│ │ │ ╰─ ブロック最初の聡\n" +"│ │ ╰─── 難易度調整周期の最初の聡ではない\n" +"│ ╰───── 半減周期の最初の聡ではない\n" +"╰─────── 二番目の循環周期\n" +"```" + +#: src/overview.md:131 +msgid "This satoshi is epic:" +msgstr "史詩レベルの聡です" + +#: src/overview.md:133 +msgid "" +"```\n" +"1°0′1″0‴\n" +"│ │ │ ╰─ First sat in block\n" +"│ │ ╰─── Not first block in difficulty adjustment period\n" +"│ ╰───── First block in halving epoch\n" +"╰─────── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°0′1″0‴\n" +"│ │ │ ╰─ ブロック最初の聡\n" +"│ │ ╰─── 難易度調整周期の最初の聡ではない\n" +"│ ╰───── 半減周期の最初の聡ではない\n" +"╰─────── 二番目の循環周期\n" +"```" + +#: src/overview.md:141 +msgid "This satoshi is legendary:" +msgstr "伝奇レベルの聡です。" + +#: src/overview.md:143 +msgid "" +"```\n" +"1°0′0″0‴\n" +"│ │ │ ╰─ First sat in block\n" +"│ │ ╰─── First block in difficulty adjustment period\n" +"│ ╰───── First block in halving epoch\n" +"╰─────── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°0′0″0‴\n" +"│ │ │ ╰─ ブロック最初の聡\n" +"│ │ ╰─── 難易度調整周期の最初の聡ではない\n" +"│ ╰───── 半減周期の最初の聡ではない\n" +"╰─────── 二番目の循環周期\n" +"```" + +#: src/overview.md:151 +msgid "And this satoshi is mythic:" +msgstr "神話レベルの聡です:" + +#: src/overview.md:153 +msgid "" +"```\n" +"0°0′0″0‴\n" +"│ │ │ ╰─ First sat in block\n" +"│ │ ╰─── First block in difficulty adjustment period\n" +"│ ╰───── First block in halving epoch\n" +"╰─────── First cycle\n" +"```" +msgstr "" +"```\n" +"0°0′0″0‴\n" +"│ │ │ ╰─ ブロック最初の聡\n" +"│ │ ╰─── 難易度調整周期の最初の聡ではない\n" +"│ ╰───── 半減周期の最初の聡ではない\n" +"╰─────── 二番目の循環周期\n" +"```" + +#: src/overview.md:161 +msgid "" +"If the block offset is zero, it may be omitted. This is the uncommon satoshi " +"from above:" +msgstr "" +"ブロック オフセットがゼロの場合は省略できます。こちらは上から見た珍しいサトシです。" +#: src/overview.md:164 +msgid "" +"```\n" +"1°1′1″\n" +"│ │ ╰─ Not first block in difficulty adjustment period\n" +"│ ╰─── Not first block in halving epoch\n" +"╰───── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°1′1″\n" +"│ │ ╰─── 難易度調整周期の最初の聡ではない\n" +"│ ╰───── 半減周期の最初の聡ではない\n" +"╰─────── 二番目の循環周期\n" +"```" + +#: src/overview.md:171 +msgid "Rare Satoshi Supply" +msgstr "珍しい聡の総供給量" + +#: src/overview.md:174 +msgid "Total Supply" +msgstr "総供給量" + +#: src/overview.md:176 +msgid "`common`: 2.1 quadrillion" +msgstr "`普通`: 2千100万亿" + +#: src/overview.md:177 +msgid "`uncommon`: 6,929,999" +msgstr "`普通ではない`: 6,929,999" + +#: src/overview.md:178 +msgid "`rare`: 3437" +msgstr "`珍しく`: 3437" + +#: src/overview.md:179 +msgid "`epic`: 32" +msgstr "`史詩`: 32" + +#: src/overview.md:180 +msgid "`legendary`: 5" +msgstr "`伝奇`: 5" + +#: src/overview.md:181 src/overview.md:190 +msgid "`mythic`: 1" +msgstr "`神話`: 1" + +#: src/overview.md:183 +msgid "Current Supply" +msgstr "現有の供給量" + +#: src/overview.md:185 +msgid "`common`: 1.9 quadrillion" +msgstr "`普通`: 1千900万亿" + +#: src/overview.md:186 +msgid "`uncommon`: 745,855" +msgstr "`普通ではない`: 745,855" + +#: src/overview.md:187 +msgid "`rare`: 369" +msgstr "`珍しく`: 369" + +#: src/overview.md:188 +msgid "`epic`: 3" +msgstr "`史詩`: 3" + +#: src/overview.md:189 +msgid "`legendary`: 0" +msgstr "`伝奇`: 0" + +#: src/overview.md:192 +msgid "" +"At the moment, even uncommon satoshis are quite rare. As of this writing, " +"745,855 uncommon satoshis have been mined - one per 25.6 bitcoin in " +"circulation." +msgstr "" +"今は普通ではないの聡にもとても珍しいです。 この文を書くまで, " +"もう745,855の普通ではないの聡を発掘され、およそ25.6の流通ビットコインのうちに一つがあります。 " + +#: src/overview.md:196 +msgid "Names" +msgstr "名前" + +#: src/overview.md:199 +msgid "" +"Each satoshi has a name, consisting of the letters _A_ through _Z_, that get " +"shorter the further into the future the satoshi was mined. They could start " +"short and get longer, but then all the good, short names would be trapped in " +"the unspendable genesis block." +msgstr "" +"それぞれの聡は名前があり、アルファベットAからZまで構成されます " +"随着聪被开采的时间越长聡の発掘された時間が長いほど、名前が短いです。 短い名前から始めて、" +"ますます長くなると、それでは、すべての良い、短い名前は使用できない創世ブロックに閉じ込められます。 " + +#: src/overview.md:204 +msgid "" +"As an example, 1905530482684727°'s name is \"iaiufjszmoba\". The name of the " +"last satoshi to be mined is \"a\". Every combination of 10 characters or " +"less is out there, or will be out there, someday." +msgstr "" +msgid "" +"例えば、1905530482684727°'の名前は\"iaiufjszmoba\".最後に発掘された聡の名前は\"a\"になります。10文字" +"以下の文字の組み合わせが存在するか、いつか存在します。" + +#: src/overview.md:208 +msgid "Exotics" +msgstr "きけいです。" + +#: src/overview.md:211 +msgid "" +"Satoshis may be prized for reasons other than their name or rarity. This " +"might be due to a quality of the number itself, like having an integer " +"square or cube root. Or it might be due to a connection to a historical " +"event, such as satoshis from block 477,120, the block in which SegWit " +"activated, or 2099999997689999°, the last satoshi that will ever be mined." +msgstr "" +"彼らの名前や希少性以外にも、聡は他の理由で重視されているかもしれない。" +"これは、整数の平方根や立方根を持つような数値自体の性質によるものかもしれません。" +"またはそれは、ブロック477,120(SegWitによって活性化されたブロック)からのような歴史的なイベントに関連しています" +"は2099999997689999°で、これが最後に掘り出された聡です。" + +#: src/overview.md:217 +msgid "" +"Such satoshis are termed \"exotic\". Which satoshis are exotic and what " +"makes them so is subjective. Ordinal theorists are encouraged to seek out " +"exotics based on criteria of their own devising." +msgstr "" +"このビットコインは「奇妙な」と呼ばれています。どの聡が「変わった」のですか?何がそんなに重要視されているのか?」" +"順序理論家は、彼ら自身が設計した基準に基づいて「奇妙な」コングを探すことを奨励されています。" + +#: src/overview.md:224 +msgid "" +"Satoshis can be inscribed with arbitrary content, creating Bitcoin-native " +"digital artifacts. Inscribing is done by sending the satoshi to be inscribed " +"in a transaction that reveals the inscription content on-chain. This content " +"is then inextricably linked to that satoshi, turning it into an immutable " +"digital artifact that can be tracked, transferred, hoarded, bought, sold, " +"lost, and rediscovered." +msgstr "" +"コングは、ビットコインネイティブのデジタルアーティファクト(デジタルアート)を作成するために、任意のコンテンツを刻印することができます。" +"「刻印は、刻印する内容を取引に送ることで行われます。この取引はチェーンに銘文の内容を表示します。」" +"は銘文の内容が聡と不可分なつながりを持っているため、から変えられないデジタル人工製品を創造した。" +"このデジタル遺物は、追跡、移転、保管、購入、販売、紛失、再発見することができます。" + + + +#: src/overview.md:231 +msgid "Archaeology" +msgstr "考古" + +#: src/overview.md:234 +msgid "" +"A lively community of archaeologists devoted to cataloging and collecting " +"early NFTs has sprung up. [Here's a great summary of historical NFTs by " +"Chainleft.](https://mirror.xyz/chainleft.eth/MzPWRsesC9mQflxlLo-" +"N29oF4iwCgX3lacrvaG9Kjko)" +msgstr "" +"初期のNFTのカタログ作成と収集に取り組む活発な考古学者コミュニティが雨後の筍" +"のように出現しました" +"[Chainleftによる歴史NFTの素晴らしいまとめ](https://mirror.xyz/chainleft.eth/MzPWRsesC9mQflxlLo-N29oF4iwCgX3lacrvaG9Kjko)" + +#: src/overview.md:238 +msgid "" +"A commonly accepted cut-off for early NFTs is March 19th, 2018, the date the " +"first ERC-721 contract, [SU SQUARES](https://tenthousandsu.com/), was " +"deployed on Ethereum." +msgstr "" +"一般的に受け入れられている古いNFTの締め切りは2018年3月19日、つまり" +"最初のERC-721契約、[SU SQUARES](https://tenthousandsu.com/),がイーサリアムに配備された時間です。" + +#: src/overview.md:242 +msgid "" +"Whether or not ordinals are of interest to NFT archaeologists is an open " +"question! In one sense, ordinals were created in early 2022, when the " +"Ordinals specification was finalized. In this sense, they are not of " +"historical interest." +msgstr "" +"NFT考古学者が序数に興味を持っているかどうかは未解決の問題です!" +"ある意味で、序数は2022年初頭に作成され、当時序数規範がに制定されています。" + +#: src/overview.md:247 +msgid "" +"In another sense though, ordinals were in fact created by Satoshi Nakamoto " +"in 2009 when he mined the Bitcoin genesis block. In this sense, ordinals, " +"and especially early ordinals, are certainly of historical interest." +msgstr "" +"そういう意味では歴史的な意味がありません" +"しかし、別の意味では、序数は実際には中本聡が2009年にビットコイン創世ブロックを採掘した時に作られました。" +"この意味で、序数、特に初期の序数は、もちろん歴史的な意味を持っています。" + +#: src/overview.md:251 +msgid "" +"Many ordinal theorists favor the latter view. This is not least because the " +"ordinals were independently discovered on at least two separate occasions, " +"long before the era of modern NFTs began." +msgstr "" +"多くの順序理論家は後者の見方に賛成しています。これは単に序数が少なくとも2つの異なる場面で独立して発見されたからではありません。" +"は現代のNFT時代よりはるかに早く始まった。" + +#: src/overview.md:255 +msgid "" +"On August 21st, 2012, Charlie Lee [posted a proposal to add proof-of-stake " +"to Bitcoin to the Bitcoin Talk forum](https://bitcointalk.org/index.php?" +"topic=102355.0). This wasn't an asset scheme, but did use the ordinal " +"algorithm, and was implemented but never deployed." +msgstr "" +"2012年8月21日、Charlie LeeでCharlie Lee[Bitcoin Talkフォーラムに投稿する」" +"ビットコイン権益証明Pro of-of-stake追加の提案](https://bitcointalk.org/index.php?" +"topic=102355.0).これは資産シナリオではありませんが、序数アルゴリズムが使用されており、実装されていますが、導入されたことはありません。" + +#: src/overview.md:261 +msgid "" +"On October 8th, 2012, jl2012 [posted a scheme to the same forum](https://" +"bitcointalk.org/index.php?topic=117224.0) which uses decimal notation and " +"has all the important properties of ordinals. The scheme was discussed but " +"never implemented." +msgstr "" +"2012年10月8日、jl 2012は[同じフォーラムで案を発表しました](https://" +"bitcointalk.org/index.php?topic=117224.0)このスキームは、10進表記法を使用し、" +"序数を持つすべての重要な属性。その計画は議論されたが、決して実施されませんでした" + +#: src/overview.md:266 +msgid "" +"These independent inventions of ordinals indicate in some way that ordinals " +"were discovered, or rediscovered, and not invented. The ordinals are an " +"inevitability of the mathematics of Bitcoin, stemming not from their modern " +"documentation, but from their ancient genesis. They are the culmination of a " +"sequence of events set in motion with the mining of the first block, so many " +"years ago." +msgstr "" +"これらの序数の独立した発明は、序数が発見されたことをある程度示しています。" +"または再発見されたもので、発明されたものではありません。順序数はビットコイン数学の必然性であります" +"はそれらの現代の文書からではなく、それらの古い起源から来ています。" +"彼らは何年も前に最初のブロックの採掘とともに始まった一連の出来事のクライマックスです" + +#: src/digital-artifacts.md:4 +msgid "" +"Imagine a physical artifact. A rare coin, say, held safe for untold years in " +"the dark, secret clutch of a Viking hoard, now dug from the earth by your " +"grasping hands. It…" +msgstr "" +"実体のある人工物を想像してください。例えば、珍しいコインの場合、" +"バイキングの宝庫の闇の中で何年も秘密に保管されています" +"今、あなたの手で地下から掘り出されました。それ…" + +#: src/digital-artifacts.md:8 +msgid "" +"…has an owner. You. As long as you keep it safe, nobody can take it from you." +msgstr "" +"……一人の主人がいます。それはあなたです。あなたが大切に保管していれば、誰もあなたからそれを奪うことはできません。" + +#: src/digital-artifacts.md:10 +msgid "…is complete. It has no missing parts." +msgstr "…完全です。漏れている部分はありません。" + +#: src/digital-artifacts.md:12 +msgid "" +"…can only be changed by you. If you were a trader, and you made your way to " +"18th century China, none but you could stamp it with your chop-mark." +msgstr "" +"…あなたしか変えることができません。もしあなたがビジネスマンで、あなたが来たなら" +"の18世紀の中国では、あなた以外に印鑑を押す人はいません。" + +#: src/digital-artifacts.md:15 +msgid "" +"…can only be disposed of by you. The sale, trade, or gift is yours to make, " +"to whomever you wish." +msgstr "" +"……あなたしか処分するすることができません。販売、取引、または贈り物はあなたの決定であり、誰にあげたいかは誰にでもあげます。 " + +#: src/digital-artifacts.md:18 +msgid "" +"What are digital artifacts? Simply put, they are the digital equivalent of " +"physical artifacts." +msgstr "" +"デジタル文化財(デジタル工作物、デジタル人工物)とは?" +"は簡単に言えば、物理的人工物のデジタル等価物であります。" + +#: src/digital-artifacts.md:21 +msgid "" +"For a digital thing to be a digital artifact, it must be like that coin of " +"yours:" +msgstr "デジタル化されたものをデジタルアーティファクトにするには、あなたのコインのようでなければなりません。" + +#: src/digital-artifacts.md:24 +msgid "" +"Digital artifacts can have owners. A number is not a digital artifact, " +"because nobody can own it." +msgstr "" +"デジタル文化財には所有者がいることができるので、デジタル文化財とは異なります。誰も数字を持つことができないからです。" + +#: src/digital-artifacts.md:27 +msgid "" +"Digital artifacts are complete. An NFT that points to off-chain content on " +"IPFS or Arweave is incomplete, and thus not a digital artifact." +msgstr "" +"デジタル文化財は完全であり、IP FSまたはArweave上のチェーンの下のコンテンツを指すNFTは不完全であるため、デジタル文化財ではありません。" + +#: src/digital-artifacts.md:30 +msgid "" +"Digital artifacts are permissionless. An NFT which cannot be sold without " +"paying a royalty is not permissionless, and thus not a digital artifact." +msgstr "" +"デジタル文化財は許可が必要なく、印税を支払わなければ販売できないNFTは許可が必要ないわけではないので、デジタル文化財ではありません。" + +#: src/digital-artifacts.md:33 +msgid "" +"Digital artifacts are uncensorable. Perhaps you can change a database entry " +"on a centralized ledger today, but maybe not tomorrow, and thus one cannot " +"be a digital artifact." +msgstr "" +"デジタル文化財は審査不可能です。今日は集中元帳のデータベースエントリを変更できるかもしれませんが、明日はできないかもしれません。" +"そのため、デジタル文化財ではありません。" + +#: src/digital-artifacts.md:37 +msgid "" +"Digital artifacts are immutable. An NFT with an upgrade key is not a digital " +"artifact." +msgstr "" +"デジタルコンテンツは改ざんできません。アップグレードキーを持つNFTはデジタルコンテンツではありません。" + +#: src/digital-artifacts.md:40 +msgid "" +"The definition of a digital artifact is intended to reflect what NFTs " +"_should_ be, sometimes are, and what inscriptions _always_ are, by their " +"very nature." +msgstr "" +"デジタル文化財の定義は、その特定の性質からNFTを反映することを目的としています" +"_べき_は何か、時には何か、そして銘文_終始_は何ですか " + +#: src/inscriptions.md:4 +msgid "" +"Inscriptions inscribe sats with arbitrary content, creating bitcoin-native " +"digital artifacts, more commonly known as NFTs. Inscriptions do not require " +"a sidechain or separate token." +msgstr "" +"銘文には任意の内容が刻まれ、ビットコインネイティブのデジタル人工製品が作られました。通常NFTと呼ばれています。" +"の銘文には側鎖や個別のトークンは必要ありません。 " + +#: src/inscriptions.md:8 +msgid "" +"These inscribed sats can then be transferred using bitcoin transactions, " +"sent to bitcoin addresses, and held in bitcoin UTXOs. These transactions, " +"addresses, and UTXOs are normal bitcoin transactions, addresses, and UTXOS " +"in all respects, with the exception that in order to send individual sats, " +"transactions must control the order and value of inputs and outputs " +"according to ordinal theory." +msgstr "" +"これらの刻まれたコングは、ビットコイン取引転送を使用してビットコインアドレスに送信され、ビットコインUTXOに保存されます。" +"これらの取引、アドレス、UTXOはすべての点で通常のビットコイン取引、アドレス、UTXOです。" +"は単一の聡を送るために加えて、取引は序数理論に基づいて入力と出力の順序と値を制御しなければなりません" + +#: src/inscriptions.md:15 +msgid "" +"The inscription content model is that of the web. An inscription consists of " +"a content type, also known as a MIME type, and the content itself, which is " +"a byte string. This allows inscription content to be returned from a web " +"server, and for creating HTML inscriptions that use and remix the content of " +"other inscriptions." +msgstr "" +"銘文の内容はワールドワイドウェブ基準に基づいている。銘文はコンテンツタイプ(MI MEタイプとも呼ばれる)とコンテンツ自体(バイト列)で構成されています。" +"これにより、Webサーバーから銘文コンテンツを返すことができ、HTML銘文を作成して使用し、他の銘文コンテンツを再混合するために使用されます。" + +#: src/inscriptions.md:21 +msgid "" +"Inscription content is entirely on-chain, stored in taproot script-path " +"spend scripts. Taproot scripts have very few restrictions on their content, " +"and additionally receive the witness discount, making inscription content " +"storage relatively economical." +msgstr "" +"銘文の内容は完全にチェーン上にあり、保存されているtaproot script-path spendスクリプト内。" +"のTaprootスクリプトはその内容に対する制限が少なく、証人割引を追加で受けることで、銘文内容の保存が比較的経済的になります。" + +#: src/inscriptions.md:26 +msgid "" +"Since taproot script spends can only be made from existing taproot outputs, " +"inscriptions are made using a two-phase commit/reveal procedure. First, in " +"the commit transaction, a taproot output committing to a script containing " +"the inscription content is created. Second, in the reveal transaction, the " +"output created by the commit transaction is spent, revealing the inscription " +"content on-chain." +msgstr "" +"taproot script-path spendスクリプトは既存のtaproot出力からしか生成できないため、" +"そのため、は2段階のcommit/revealプロセスを使用して刻印されます。まず、commitでは、" +"銘文の内容を含むスクリプトに提出するtaproot出力を作成します。次に、reveal取引では、" +"commit取引による出力を使用して、チェーン上の銘文の内容を表示します。" + +#: src/inscriptions.md:33 +msgid "" +"Inscription content is serialized using data pushes within unexecuted " +"conditionals, called \"envelopes\". Envelopes consist of an `OP_FALSE OP_IF " +"… OP_ENDIF` wrapping any number of data pushes. Because envelopes are " +"effectively no-ops, they do not change the semantics of the script in which " +"they are included, and can be combined with any other locking script." +msgstr "" +"銘文の内容は、実行されていない条件のデータプッシュを使用してシリアル化され \"エンベロープ\"と呼ばれます。" +"封筒はOP_FALSE OP_IF…OP_ENDIF任意の数のデータプッシュを構成し、ラップします。" +"エンベロープは実際には空の操作なので、それらを含むスクリプトのセマンティクスは変更されません。" +"となり、他のロックスクリプトと組み合わせて使用できます。" + +#: src/inscriptions.md:39 +msgid "" +"A text inscription containing the string \"Hello, world!\" is serialized as " +"follows:" +msgstr "" +"文字列「Hello,world!」を含むのテキスト銘文を以下のようにシリアル化されています:" + + +#: src/inscriptions.md:42 +msgid "" +"```\n" +"OP_FALSE\n" +"OP_IF\n" +" OP_PUSH \"ord\"\n" +" OP_PUSH 1\n" +" OP_PUSH \"text/plain;charset=utf-8\"\n" +" OP_PUSH 0\n" +" OP_PUSH \"Hello, world!\"\n" +"OP_ENDIF\n" +"```" +msgstr "" + +#: src/inscriptions.md:53 +msgid "" +"First the string `ord` is pushed, to disambiguate inscriptions from other " +"uses of envelopes." +msgstr "" +"まず文字列'ord'がプッシュされ、銘文と封筒の他の用途との曖昧さを解消します。" + +#: src/inscriptions.md:56 +msgid "" +"`OP_PUSH 1` indicates that the next push contains the content type, and " +"`OP_PUSH 0` indicates that subsequent data pushes contain the content " +"itself. Multiple data pushes must be used for large inscriptions, as one of " +"taproot's few restrictions is that individual data pushes may not be larger " +"than 520 bytes." +msgstr "" +"`OP_PUSH 1'は、次のプッシュにコンテンツタイプが含まれていることを示します。" +"'OP_PUSH 0'は、後続のデータプッシュがコンテンツ自体を含むことを示す。" +"の大規模な銘文は複数回のデータプッシュを使用しなければならない。taprootの少数の制限の一つは、単一のデータプッシュが520バイトを超えないことであります。" + + +#: src/inscriptions.md:61 +msgid "" +"The inscription content is contained within the input of a reveal " +"transaction, and the inscription is made on the first sat of its input. This " +"sat can then be tracked using the familiar rules of ordinal theory, allowing " +"it to be transferred, bought, sold, lost to fees, and recovered." +msgstr "" +"銘文の内容はreveal取引の入力に含まれ、銘文はその最初の出力の最初の聡(Satoshi)に刻まれている。" +"私たちはよく知っている序数理論のルールを使ってこの聡satを追跡することができます。移転、購入、販売、紛失、回復を許可します。" + +#: src/inscriptions.md:66 +msgid "Content" +msgstr "内容" + +#: src/inscriptions.md:69 +msgid "" +"The data model of inscriptions is that of a HTTP response, allowing " +"inscription content to be served by a web server and viewed in a web browser." +msgstr "" +"銘文のデータモデルはHTTP応答のデータモデルであり、銘文がウェブサーバによってサービスされ、ウェブブラウザで閲覧することを可能にします。" + +#: src/inscriptions.md:72 +msgid "Fields" +msgstr "フィールド" + +#: src/inscriptions.md:75 +msgid "" +"Inscriptions may include fields before an optional body. Each field consists " +"of two data pushes, a tag and a value." +msgstr "" +"銘文には、オプションの本文の前にフィールドを含めることができます。各フィールドには" +"の2つのデータプッシュ、1つのラベルと1つの値。" + +#: src/inscriptions.md:78 +msgid "" +"Currently, the only defined field is `content-type`, with a tag of `1`, " +"whose value is the MIME type of the body." +msgstr "" +"現在、定義されている唯一のフィールドは『content-type』です。タグは「1」、" +"その値は本文のMI MEタイプです。" + +#: src/inscriptions.md:81 +msgid "" +"The beginning of the body and end of fields is indicated with an empty data " +"push." +msgstr "" +"本文の先頭とフィールドの末尾には \"空のデータ\"でプッシュが表示されます。" + +#: src/inscriptions.md:84 +msgid "" +"Unrecognized tags are interpreted differently depending on whether they are " +"even or odd, following the \"it's okay to be odd\" rule used by the " +"Lightning Network." +msgstr "" +"認識できないラベルの解釈は、偶数か奇数かによって異なり、稲妻ネットワーク\"は奇数\"にすることができるというルールに従います。" + +#: src/inscriptions.md:88 +msgid "" +"Even tags are used for fields which may affect creation, initial assignment, " +"or transfer of an inscription. Thus, inscriptions with unrecognized even " +"fields must be displayed as \"unbound\", that is, without a location." +msgstr "" +"ラベルさえも、作成、初期割り当て、または銘文の転送に影響を及ぼす可能性のあるフィールドのために使用されます。だから、識別できない銘文でも、" +"フィールドも\"未バインド\"として表示されなければなりません。つまり、場所がありません。" + + +#: src/inscriptions.md:92 +msgid "" +"Odd tags are used for fields which do not affect creation, initial " +"assignment, or transfer, such as additional metadata, and thus are safe to " +"ignore." +msgstr "" +"奇数タグは、追加のメタデータなど、作成、初期フィールド、割り当て、または転送に影響を与えないために使用され、したがって、無視することが安全であることを選択します。" + +#: src/inscriptions.md:95 +msgid "Inscription IDs" +msgstr "銘文の身分ID" + +#: src/inscriptions.md:98 +msgid "" +"The inscriptions are contained within the inputs of a reveal transaction. In " +"order to uniquely identify them they are assigned an ID of the form:" +msgstr "" +"銘文は取引を明らかにする入力に含まれている。彼らを一意に識別するために、彼らには以下の形式のIDが割り当てられています:" + +#: src/inscriptions.md:101 +msgid "`521f8eccffa4c41a3a7728dd012ea5a4a02feed81f41159231251ecf1e5c79dai0`" +msgstr "" + +#: src/inscriptions.md:103 +msgid "" +"The part in front of the `i` is the transaction ID (`txid`) of the reveal " +"transaction. The number after the `i` defines the index (starting at 0) of " +"new inscriptions being inscribed in the reveal transaction." +msgstr "" +" ’i’の先頭部分は、トランザクションID(’txid’)である。`i`の後の数字はを定義します。" +"新しい銘文は、取引で常に銘記されたインデックスの位置(0から開始)" + +#: src/inscriptions.md:107 +msgid "" +"Inscriptions can either be located in different inputs, within the same " +"input or a combination of both. In any case the ordering is clear, since a " +"parser would go through the inputs consecutively and look for all " +"inscription `envelopes`." +msgstr "" +"銘文は、入力の中の異なる入力の中にあってもよく、同じ入力であってもよく、あるいは両者の組み合わせであってもよい。" +"いずれにしても、パーサーは入力を連続的にチェックし、すべての銘文『封筒を検索するため、順序は明確です" + +#: src/inscriptions.md:111 +msgid "Input" +msgstr "" + +#: src/inscriptions.md:111 +msgid "Inscription Count" +msgstr "" + +#: src/inscriptions.md:111 +msgid "Indices" +msgstr "" + +#: src/inscriptions.md:113 src/inscriptions.md:116 +msgid "0" +msgstr "" + +#: src/inscriptions.md:113 src/inscriptions.md:115 +msgid "2" +msgstr "" + +#: src/inscriptions.md:113 +msgid "i0, i1" +msgstr "" + +#: src/inscriptions.md:114 src/inscriptions.md:117 +msgid "1" +msgstr "" + +#: src/inscriptions.md:114 +msgid "i2" +msgstr "" + +#: src/inscriptions.md:115 src/inscriptions.md:116 +msgid "3" +msgstr "" + +#: src/inscriptions.md:115 +msgid "i3, i4, i5" +msgstr "" + +#: src/inscriptions.md:117 +msgid "4" +msgstr "" + +#: src/inscriptions.md:117 +msgid "i6" +msgstr "" + +#: src/inscriptions.md:119 +msgid "Sandboxing" +msgstr "サンドボックス化" + +#: src/inscriptions.md:122 +msgid "" +"HTML and SVG inscriptions are sandboxed in order to prevent references to " +"off-chain content, thus keeping inscriptions immutable and self-contained." +msgstr "" +"HTML と SVG 銘文はサンドボックス化され、チェーンの下の内容を引用しないようにして、銘文の不変性と独立性を保ちます。" + +#: src/inscriptions.md:125 +msgid "" +"This is accomplished by loading HTML and SVG inscriptions inside `iframes` " +"with the `sandbox` attribute, as well as serving inscription content with " +"`Content-Security-Policy` headers." +msgstr "" +"これは、HTMLとSVGの銘文を `iframes` にロードし、銘文コンテンツを提供することによって行われる'sandbox'属性です。" +"Content-Security-Policy”ヘッダ。" + +#: src/inscriptions/recursion.md:4 +msgid "" +"An important exception to [sandboxing](../inscriptions.md#sandboxing) is " +"recursion: access to `ord`'s `/content` endpoint is permitted, allowing " +"inscriptions to access the content of other inscriptions by requesting `/" +"content/`." +msgstr "" +"[サンドボックス化](../inscriptions.md#sandboxing)の重要な例外は再帰です:" +"`ord`の /content`エンドポイントへのアクセスが許可され、碑文が`/content/`" +"をリクエストすることで他の碑文のコンテンツにアクセスできるようになります。" + +#: src/inscriptions/recursion.md:8 +msgid "This has a number of interesting use-cases:" +msgstr "ここは面白い用例がとても多いです:" + +#: src/inscriptions/recursion.md:10 +msgid "Remixing the content of existing inscriptions." +msgstr "既存の銘文の内容を再混合します。" + +#: src/inscriptions/recursion.md:12 +msgid "" +"Publishing snippets of code, images, audio, or stylesheets as shared public " +"resources." +msgstr "コード、イメージ、オーディオ、またはスタイルシートフラグメントを共通の共有アセットとしてパブリッシュします。" + +#: src/inscriptions/recursion.md:15 +msgid "" +"Generative art collections where an algorithm is inscribed as JavaScript, " +"and instantiated from multiple inscriptions with unique seeds." +msgstr "アルゴリズムがJava Scriptを使用して刻印され、ユニークなシードを持つ複数の銘文からインスタンス化されたアートコレクションを生成します。" + +#: src/inscriptions/recursion.md:18 +msgid "" +"Generative profile picture collections where accessories and attributes are " +"inscribed as individual images, or in a shared texture atlas, and then " +"combined, collage-style, in unique combinations in multiple inscriptions." +msgstr "" +"アクセサリーやプロパティを含むプロファイル画像セットを生成し、個別の画像として書き込むか、共有テクスチャマップセットに書き込み、" +"の組み合わせ、コラージュスタイル、複数の銘文の中で独特の組み合わせで。" + +#: src/inscriptions/recursion.md:22 +msgid "A few other endpoints that inscriptions may access are the following:" +msgstr "銘文がアクセスできる他のいくつかのエンドポイントは以下の通りです:" + +#: src/inscriptions/recursion.md:24 +msgid "`/blockheight`: latest block height." +msgstr "`/blockheight`:最新のブロック高度。" + +#: src/inscriptions/recursion.md:25 +msgid "`/blockhash`: latest block hash." +msgstr "`/blockhash`:最新のブロックハッシュ。" + +#: src/inscriptions/recursion.md:26 +msgid "`/blockhash/`: block hash at given block height." +msgstr "`/blockhash/`:指定されたブロック高さのブロックハッシュ。" + +#: src/inscriptions/recursion.md:27 +msgid "`/blocktime`: UNIX time stamp of latest block." +msgstr "`/blocktime`:最新のブロックのUNIXタイムスタンプ。" + +#: src/faq.md:1 +msgid "Ordinal Theory FAQ" +msgstr "序数理論のよくある質問" + +#: src/faq.md:4 +msgid "What is ordinal theory?" +msgstr "序数理論はなんですか" + +#: src/faq.md:7 +msgid "" +"Ordinal theory is a protocol for assigning serial numbers to satoshis, the " +"smallest subdivision of a bitcoin, and tracking those satoshis as they are " +"spent by transactions." +msgstr "" +"序数理論は、聡(satoshi、以下は「聡」と書きます。ビットコインの最小単位)シリアル番号を割り当てるプロトコル、" +"と取引中にこれらの聡を追跡します。" + +#: src/faq.md:11 +msgid "" +"These serial numbers are large numbers, like this 804766073970493. Every " +"satoshi, which is ¹⁄₁₀₀₀₀₀₀₀₀ of a bitcoin, has an ordinal number." +msgstr "" +"これらの番号はすべて大きな数字で、例えば、804766073970493.すべての聡satoshi、" +"もビットコインの¹⁄₁₀₀₀₀₀₀₀₀はすべて序数番号を持っています" + +#: src/faq.md:14 +msgid "" +"Does ordinal theory require a side chain, a separate token, or changes to " +"Bitcoin?" +msgstr "" +"序数理論はサイドチェーン、個別のトークン、またはビットコインに変更を加える必要がありますか?" + +#: src/faq.md:17 +msgid "" +"Nope! Ordinal theory works right now, without a side chain, and the only " +"token needed is bitcoin itself." +msgstr "" +"全然いりません!序数理論は現在有効に利用可能で、サイドチェーンがなく、唯一必要なトークンはビットコイン自体であります。" + +#: src/faq.md:20 +msgid "What is ordinal theory good for?" +msgstr "" +"序数理論はどんな用途がありますか?" + +#: src/faq.md:23 +msgid "" +"Collecting, trading, and scheming. Ordinal theory assigns identities to " +"individual satoshis, allowing them to be individually tracked and traded, as " +"curios and for numismatic value." +msgstr "" +"収集、取引、企画。序数理論は身分を個々の聡に割り当て、骨董品や貨幣価値として個別に追跡され取引されることを可能にします。" + +#: src/faq.md:27 +msgid "" +"Ordinal theory also enables inscriptions, a protocol for attaching arbitrary " +"content to individual satoshis, turning them into bitcoin-native digital " +"artifacts." +msgstr "" +"序数理論はまた、任意の内容を単一のコングに付加し、ビットコインのネイティブデジタルアーティファクトにするプロトコルである銘文を与えます。" + +#: src/faq.md:31 +msgid "How does ordinal theory work?" +msgstr "" +"序数理論はどのように機能しますか?" + +#: src/faq.md:34 +msgid "" +"Ordinal numbers are assigned to satoshis in the order in which they are " +"mined. The first satoshi in the first block has ordinal number 0, the second " +"has ordinal number 1, and the last satoshi of the first block has ordinal " +"number 4,999,999,999." +msgstr "" +"序数は採掘の順序に従って聡に割り当てられた。最初のブロックの最初のリスニングの序数は0で、2番目のリスニングの序数は1です。" +"最初のブロックの最後のセグメントの序数は4,999,999,999です。" + +#: src/faq.md:39 +msgid "" +"Satoshis live in outputs, but transactions destroy outputs and create new " +"ones, so ordinal theory uses an algorithm to determine how satoshis hop from " +"the inputs of a transaction to its outputs." +msgstr "" +"コングは出力に存在しますが、トランザクションは出力を破壊し、新しい出力を作成します。" +"したがって、序数理論では、取引の入力から出力にどのようにジャンプするかを決定するアルゴリズ" +"ムを使用します。" + +#: src/faq.md:43 +msgid "Fortunately, that algorithm is very simple." +msgstr "" +"幸いなことに、このアルゴリズムはとても簡単です。" + +#: src/faq.md:45 +msgid "" +"Satoshis transfer in first-in-first-out order. Think of the inputs to a " +"transaction as being a list of satoshis, and the outputs as a list of slots, " +"waiting to receive a satoshi. To assign input satoshis to slots, go through " +"each satoshi in the inputs in order, and assign each to the first available " +"slot in the outputs." +msgstr "" +"聡は先入れ先出しの順に振り込みを行う。トランザクションの入力をスマートリストとして、出力をスロットスロットリストとして、" +"聡の受信を待つ。入力セグメントをスロットに割り当てるには、入力セグメントの各セグメントを順番にチェックします。" +"と表示され、出力の最初の使用可能なスロットに各スマートが割り当てられます。。" + +#: src/faq.md:51 +msgid "" +"Let's imagine a transaction with three inputs and two outputs. The inputs " +"are on the left of the arrow and the outputs are on the right, all labeled " +"with their values:" +msgstr "" +"3つの入力と2つの出力を持つ取引を想像してみましょう。入力は矢印の左側にあり、出力は右側にあり、値のラベルが付いています:" + +#: src/faq.md:55 +msgid "" +"```\n" +"[2] [1] [3] → [4] [2]\n" +"```" +msgstr "" + +#: src/faq.md:57 +msgid "" +"Now let's label the same transaction with the ordinal numbers of the " +"satoshis that each input contains, and question marks for each output slot. " +"Ordinal numbers are large, so let's use letters to represent them:" +msgstr "" +"今は、各入力に含まれる小数点以下の番号で同じトランザクションをマークし、各出力スロットに疑問符をマークします。" +"序数は大きいので、それらをアルファベットで表します:" + +#: src/faq.md:61 +msgid "" +"```\n" +"[a b] [c] [d e f] → [? ? ? ?] [? ?]\n" +"```" +msgstr "" + +#: src/faq.md:63 +msgid "" +"To figure out which satoshi goes to which output, go through the input " +"satoshis in order and assign each to a question mark:" +msgstr "" +"どの出力からどの出力への出力かを確認するには、入力の出力を順番にチェックし、各出力に疑問符を割り当てます:" + +#: src/faq.md:66 +msgid "" +"```\n" +"[a b] [c] [d e f] → [a b c d] [e f]\n" +"```" +msgstr "" + +#: src/faq.md:68 +msgid "" +"What about fees, you might ask? Good question! Let's imagine the same " +"transaction, this time with a two satoshi fee. Transactions with fees send " +"more satoshis in the inputs than are received by the outputs, so to make our " +"transaction into one that pays fees, we'll remove the second output:" +msgstr "" +"取引費用を聞くかもしれませんか?いい質問だ!同じ取引を想像してみましょう。今回は2人の聡の費用です。" +"有料取引は、で送信された音声が出力で受信された音声より多いので、私たちの取引を料金を支払う取引にするために、" +"2番目の出力を削除します:" + +#: src/faq.md:73 +msgid "" +"```\n" +"[2] [1] [3] → [4]\n" +"```" +msgstr "" + +#: src/faq.md:75 +msgid "The satoshis " +msgstr "聡" + +#: src/faq.md:75 +msgid "e" +msgstr "" + +#: src/faq.md:75 +msgid " and " +msgstr " と " + +#: src/faq.md:75 +msgid "f" +msgstr "" + +#: src/faq.md:75 +msgid " now have nowhere to go in the outputs:" +msgstr "今は輸出しているので、どこへも行けません" + +#: src/faq.md:78 +msgid "" +"```\n" +"[a b] [c] [d e f] → [a b c d]\n" +"```" +msgstr "" +"```\n" +"[a b] [c] [d e f] → [a b c d]\n" +"```" + +#: src/faq.md:80 +msgid "" +"So they go to the miner who mined the block as fees. [The BIP](https://" +"github.com/ordinals/ord/blob/master/bip.mediawiki) has the details, but in " +"short, fees paid by transactions are treated as extra inputs to the coinbase " +"transaction, and are ordered how their corresponding transactions are " +"ordered in the block. The coinbase transaction of the block might look like " +"this:" +msgstr "" +"だから彼らは「費用」としてこのブロックを掘っている鉱山労働者のところに行きます。[The BIP]" +"(https://github.com/ordinals/ord/blob/master/bip.mediawiki)にはもっと詳しい説明があります。" +"しかし、簡単に言えば、取引によって支払われる料金は、Coinbase取引への追加入力とみなされ、その対応する取引に応じてブロック内にあります" +"の順にソートされます。ブロックのCoinbaseトランザクションは次のようになる可能性があります:" + +#: src/faq.md:87 +msgid "" +"```\n" +"[SUBSIDY] [e f] → [SUBSIDY e f]\n" +"```" +msgstr "" + +#: src/faq.md:89 +msgid "Where can I find the nitty-gritty details?" +msgstr "これらの詳細な情報はどこで見つけることができますか" + +#: src/faq.md:92 +msgid "[The BIP!](https://github.com/ordinals/ord/blob/master/bip.mediawiki)" +msgstr "" + +#: src/faq.md:94 +msgid "" +"Why are sat inscriptions called \"digital artifacts\" instead of \"NFTs\"?" +msgstr "なぜ聡の銘文は「NFT」ではなく「デジタル文化財」と呼ばれていますか?" + +#: src/faq.md:97 +msgid "" +"An inscription is an NFT, but the term \"digital artifact\" is used instead, " +"because it's simple, suggestive, and familiar." +msgstr "銘文もNFTの一種です。しかし、その代わりに「デジタル文化財」という用語が使われています。それは簡単で、啓発的で、なじみがあるからです" + +#: src/faq.md:100 +msgid "" +"The phrase \"digital artifact\" is highly suggestive, even to someone who " +"has never heard the term before. In comparison, NFT is an acronym, and " +"doesn't provide any indication of what it means if you haven't heard the " +"term before." +msgstr "" +"\"デジタル文化財\"(デジタル工作物、デジタル人工物)これらの言葉は強い暗示性を持っている。" +"「これまでこの言葉を聞いたことがない人にとってもそうだ」" +"に比べて、NFTは頭文字の略語で、以前この用語を聞いたことがなければ、意味を説明できません。" + +#: src/faq.md:104 +msgid "" +"Additionally, \"NFT\" feels like financial terminology, and the both word " +"\"fungible\" and sense of the word \"token\" as used in \"NFT\" is uncommon " +"outside of financial contexts." +msgstr "" +"さらに、\"NFT\"は金融用語のような気がします。\"NFT\"で使われている\"同質化\"という言葉と" +"\"トークン\"という言葉の意味は金融の文脈の外では一般的ではありません。" + +#: src/faq.md:108 +msgid "How do sat inscriptions compare to…" +msgstr "聡は他のルーンと比較します" + +#: src/faq.md:111 +msgid "Ethereum NFTs?" +msgstr "エセリウムNFT" + +#: src/faq.md:113 +msgid "_Inscriptions are always immutable._" +msgstr "_銘文は永遠に変わりません_" + +#: src/faq.md:115 +msgid "" +"There is simply no way to for the creator of an inscription, or the owner of " +"an inscription, to modify it after it has been created." +msgstr "" +"銘文の作成者や所有者は、銘文を作成した後に修正することはできません。" + +#: src/faq.md:118 +msgid "" +"Ethereum NFTs _can_ be immutable, but many are not, and can be changed or " +"deleted by the NFT contract owner." +msgstr "" +"エセリウムNFTs_は変更不可能であることができますが、多くはそうではなく、NFT契約者によって変更" +"または削除することができます。。" + +#: src/faq.md:121 +msgid "" +"In order to make sure that a particular Ethereum NFT is immutable, the " +"contract code must be audited, which requires detailed knowledge of the EVM " +"and Solidity semantics." +msgstr "" +"特定のエセリウムNFTが不変であることを確実にするためには、契約コードを監査しなければなりません。" +"これにはEVMとSolidityセマンティクスの詳細な理解が必要です。" + +#: src/faq.md:125 +msgid "" +"It is very hard for a non-technical user to determine whether or not a given " +"Ethereum NFT is mutable or immutable, and Ethereum NFT platforms make no " +"effort to distinguish whether an NFT is mutable or immutable, and whether " +"the contract source code is available and has been audited." +msgstr "" +"技術ユーザーではない人にとって、あるイーサリアムNFTが可変かどうかを判断することは困難であり、" +"イーサリアムNFTプラットフォームもNFTが可変かどうかを区別する努力をしていません。" +"と、契約ソースコードが利用可能で監査されているかどうかを確認します。" + +#: src/faq.md:130 +msgid "_Inscription content is always on-chain._" +msgstr "_銘文の内容は永遠にコンタクトします_" + +#: src/faq.md:132 +msgid "" +"There is no way for an inscription to refer to off-chain content. This makes " +"inscriptions more durable, because content cannot be lost, and scarcer, " +"because inscription creators must pay fees proportional to the size of the " +"content." +msgstr "" +"銘文はチェーンの下の内容を引用できない。内容が失われないので、銘文はより長持ちします。" +"また、コンテンツのサイズに比例した費用を銘文作成者に支払わなければなりません。" + +#: src/faq.md:136 +msgid "" +"Some Ethereum NFT content is on-chain, but much is off-chain, and is stored " +"on platforms like IPFS or Arweave, or on traditional, fully centralized web " +"servers. Content on IPFS is not guaranteed to continue to be available, and " +"some NFT content stored on IPFS has already been lost. Platforms like " +"Arweave rely on weak economic assumptions, and will likely fail " +"catastrophically when these economic assumptions are no longer met. " +"Centralized web servers may disappear at any time." +msgstr "" +"イーサリアムのNFTコンテンツの中にはチェーン上にあるものもありますが、ほとんどのコンテンツはチェーンの下にあり、IP FSやArweaveなどのプラットフォームに保存されています。" +"または従来の完全に中心化されたネットワークサーバー上で。IP FSのコンテンツは引き続き利用できることを保証していません。IP FSに保存されているNFTコンテンツの一部は失われました。" +"Arweaveのようなプラットフォームは弱い経済的仮定に依存しており、これらの経済的仮定が満たされなくなったとき" +"は壊滅的な失敗を起こす可能性が高い。一元化されたネットワークサーバはいつでも消える可能性があ。" + +#: src/faq.md:144 +msgid "" +"It is very hard for a non-technical user to determine where the content of a " +"given Ethereum NFT is stored." +msgstr "" +"技術ユーザーではない人にとって、イーサリアムNFTのコンテンツがどこに保存されているかを特定することは困難です。" + +#: src/faq.md:147 +msgid "_Inscriptions are much simpler._" +msgstr "_めいぶんはよりかんたんであります_" + +#: src/faq.md:149 +msgid "" +"Ethereum NFTs depend on the Ethereum network and virtual machine, which are " +"highly complex, constantly changing, and which introduce changes via " +"backwards-incompatible hard forks." +msgstr "" +"イーサリアムNFTはイーサリアムネットワークと仮想マシンに依存しており、高度に複雑で変化し続け、下位互換性のないハードフォークによって変化をもたらします。" + +#: src/faq.md:153 +msgid "" +"Inscriptions, on the other hand, depend on the Bitcoin blockchain, which is " +"relatively simple and conservative, and which introduces changes via " +"backwards-compatible soft forks." +msgstr "" +"対照的に、銘文はビットコインブロックチェーンに依存しており、比較的単純で保守的であり、後方互換性のあるソフトフォークによって変化を導入しています。" + +#: src/faq.md:157 +msgid "_Inscriptions are more secure._" +msgstr "_銘文はより安全です_" + +#: src/faq.md:159 +msgid "" +"Inscriptions inherit Bitcoin's transaction model, which allow a user to see " +"exactly which inscriptions are being transferred by a transaction before " +"they sign it. Inscriptions can be offered for sale using partially signed " +"transactions, which don't require allowing a third party, such as an " +"exchange or marketplace, to transfer them on the user's behalf." +msgstr "" +"銘文はビットコインの取引モデルを継承しており、ユーザーは署名する前に取引でどの銘文が転送されたかを正確に見ることができる。" +"銘文は署名取引の一部を使用して販売することができ、取引所や市場などの第三者がユーザーの代わりにそれらを譲渡することを許可する必要はありません。" + +#: src/faq.md:165 +msgid "" +"By comparison, Ethereum NFTs are plagued with end-user security " +"vulnerabilities. It is commonplace to blind-sign transactions, grant third-" +"party apps unlimited permissions over a user's NFTs, and interact with " +"complex and unpredictable smart contracts. This creates a minefield of " +"hazards for Ethereum NFT users which are simply not a concern for ordinal " +"theorists." +msgstr "" +"対照的に、イーサリアムNFTはエンドユーザーのセキュリティホールに悩まされています。ブラインドサイン取引、ユーザーにNFTの第三者アプリケーションを付与" +"の無限の権限と、複雑で予測不可能なスマートコントラクトとのやり取りは当たり前のことです。これはイーサリアムNFTユーザーのために作られた" +"危険地雷原をしていますが、これらは番号理論家にとっては心配する必要はありません。" + +#: src/faq.md:171 +msgid "_Inscriptions are scarcer._" +msgstr "_銘文はより珍しいです_" + +#: src/faq.md:173 +msgid "" +"Inscriptions require bitcoin to mint, transfer, and store. This seems like a " +"downside on the surface, but the raison d'etre of digital artifacts is to be " +"scarce and thus valuable." +msgstr "" +"銘文は鋳造、移転、保存するためにビットコインが必要です。表面的には、これは障害のように見えるが、デジタル文化財の存在の価値目的は希少であります。" + +#: src/faq.md:177 +msgid "" +"Ethereum NFTs, on the other hand, can be minted in virtually unlimited " +"qualities with a single transaction, making them inherently less scarce, and " +"thus, potentially less valuable." +msgstr "" +"一方、イーサリアムNFTは1回の取引でほぼ無限の品質で鋳造することができ、本質的にそれほど希少ではないです。" +"そのため、あまり価値がないかもしれません。" + +#: src/faq.md:181 +msgid "_Inscriptions do not pretend to support on-chain royalties._" +msgstr "_銘文はチェーン上の版税を支持するふりをしません_" + +#: src/faq.md:183 +msgid "" +"On-chain royalties are a good idea in theory but not in practice. Royalty " +"payment cannot be enforced on-chain without complex and invasive " +"restrictions. The Ethereum NFT ecosystem is currently grappling with " +"confusion around royalties, and is collectively coming to grips with the " +"reality that on-chain royalties, which were messaged to artists as an " +"advantage of NFTs, are not possible, while platforms race to the bottom and " +"remove royalty support." +msgstr "" +"「チェーン上の版税」は理論的には良い考えですが、実際にはうまくいきません。複雑で侵入的な制限がなければ" +"チェーン上の版税の支払いを強制することはできません。イーサリアムNFTエコシステムは、版税をめぐる問題を解決するために努力しています。" +"そして、は共に一つの現実に直面しています。つまり、NFTチェーン上の版税という利器を芸術家に伝えることは実際には不可能です。" +"同時に、複数のプラットフォームが版税のサポートを削除するために競争しています" + +#: src/faq.md:190 +msgid "" +"Inscriptions avoid this situation entirely by making no false promises of " +"supporting royalties on-chain, thus avoiding the confusion, chaos, and " +"negativity of the Ethereum NFT situation." +msgstr "" +"銘文はこの状況を完全に迴避し、チェーン上のロイヤリティをサポートすることを虚偽で約束していません。" +"はイーサリアムNFTのような混乱と消極的な状況を避けました。" + +#: src/faq.md:194 +msgid "_Inscriptions unlock new markets._" +msgstr "_銘文は新たな市場を開きました_" + +#: src/faq.md:196 +msgid "" +"Bitcoin's market capitalization and liquidity are greater than Ethereum's by " +"a large margin. Much of this liquidity is not available to Ethereum NFTs, " +"since many Bitcoiners prefer not to interact with the Ethereum ecosystem due " +"to concerns related to simplicity, security, and decentralization." +msgstr "" +"ビットコインの市場価格と流動性はイーサリアムを大きく上回っている。イーサリアムNFTはこのような流動性の大部分を得ることができません。" +"多くのビットコインユーザーは、シンプルさ、安全性、分散化の観点から、イーサリアムのエコシステムと対話することを望んでいないからです。" + +#: src/faq.md:201 +msgid "" +"Such Bitcoiners may be more interested in inscriptions than Ethereum NFTs, " +"unlocking new classes of collector." +msgstr "" +"イーサリアムNFTと比較して、そのようなビットコインの支持者は、新しいカテゴリのコレクターをロッ" +"ク解除するために、碑文に興味を持っている可能性があります。" + +#: src/faq.md:204 +msgid "_Inscriptions have a richer data model._" +msgstr "_铭文有更丰富的数据模型_" + +#: src/faq.md:206 +msgid "" +"Inscriptions consist of a content type, also known as a MIME type, and " +"content, which is an arbitrary byte string. This is the same data model used " +"by the web, and allows inscription content to evolve with the web, and come " +"to support any kind of content supported by web browsers, without requiring " +"changes to the underlying protocol." +msgstr "" +"銘文はコンテンツタイプ(MI MEタイプとも呼ばれる)とコンテンツ)任意のバイト文字列)で構成される。これは、Webで使用されるデータモデルと同じです。" +"銘文コンテンツをウェブの発展に合わせて発展させ、基盤となるプロトコルを変更することなく、ウェブブラウザがサポートするあらゆる種類のコンテンツをサポートすることを可能に" + +#: src/faq.md:212 +msgid "RGB and Taro assets?" +msgstr "RGB 和 Taro 資産?" + +#: src/faq.md:214 +msgid "" +"RGB and Taro are both second-layer asset protocols built on Bitcoin. " +"Compared to inscriptions, they are much more complicated, but much more " +"featureful." +msgstr "" +"RGBとTaroはいずれもビットコインの上に構築された二層資産協定である。銘文に比べて、それらはずっと複雑ですが、より特色があります。" + +#: src/faq.md:217 +msgid "" +"Ordinal theory has been designed from the ground up for digital artifacts, " +"whereas the primary use-case of RGB and Taro are fungible tokens, so the " +"user experience for inscriptions is likely to be simpler and more polished " +"than the user experience for RGB and Taro NFTs." +msgstr "" +"シリアル番号理論はデジタルアーティファクト用に設計されていますが、RGBとTaroの主なユースケースは代替トークンです。" +"そのため、銘文のユーザー体験はRGBやTaro NFTのユーザー体験よりも簡単で完璧かもしれません。" + +#: src/faq.md:222 +msgid "" +"RGB and Taro both store content off-chain, which requires additional " +"infrastructure, and which may be lost. By contrast, inscription content is " +"stored on-chain, and cannot be lost." +msgstr "" +"RGBとTaroはどちらもチェーンの下にコンテンツを保存します。これには追加のインフラが必要で、紛失する可能性があります。" +"に比べて、銘文の内容はチェーンに保存され、失われることはありません。" + +#: src/faq.md:226 +msgid "" +"Ordinal theory, RGB, and Taro are all very early, so this is speculation, " +"but ordinal theory's focus may give it the edge in terms of features for " +"digital artifacts, including a better content model, and features like " +"globally unique symbols." +msgstr "" +"序数理論、RGB、Taroは非常に初期のものなので、これは推測にすぎませんが、序数理論の重点はデジタル芸術品のにあるかもしれません" +"の特性には、より良いコンテンツモデルや、世界で唯一のシンボルのような特性などの利点があります。" + + +#: src/faq.md:231 +msgid "Counterparty assets?" +msgstr "Counterparty资产" + +#: src/faq.md:233 +msgid "" +"Counterparty has its own token, XCP, which is required for some " +"functionality, which makes most bitcoiners regard it as an altcoin, and not " +"an extension or second layer for bitcoin." +msgstr "" +"Counterpartyは独自のトークンXCPを持っています。これはいくつかの機能に必要で、ほとんどのビットコイン保有者はそれをパクリ通貨と見なしています。" +"ビットコインの拡張や第二層ではありません" + +#: src/faq.md:237 +msgid "" +"Ordinal theory has been designed from the ground up for digital artifacts, " +"whereas Counterparty was primarily designed for financial token issuance." +msgstr "" +"序数理論はデジタル文化財のために最初から設計されたのに対し、Counterpartyは主に金融トークン発行のために設計されました。" + +#: src/faq.md:240 +msgid "Inscriptions for…" +msgstr "銘文は..." + +#: src/faq.md:243 +msgid "Artists" +msgstr "芸術家になれます" + +#: src/faq.md:245 +msgid "" +"_Inscriptions are on Bitcoin._ Bitcoin is the digital currency with the " +"highest status and greatest chance of long-term survival. If you want to " +"guarantee that your art survives into the future, there is no better way to " +"publish it than as inscriptions." +msgstr "" +"_ビットコインの銘文_ビットコインは現在最も地位が高く、長期生存の機会が最も大きいデジタル通貨であります。" +"はあなたの芸術作品が未来に伝わることを保証したいなら、銘文より良い発表方法はありません。" + +#: src/faq.md:250 +msgid "" +"_Cheaper on-chain storage._ At $20,000 per BTC and the minimum relay fee of " +"1 satoshi per vbyte, publishing inscription content costs $50 per 1 million " +"bytes." +msgstr "" +"_チェーン上のストレージはより安価です_ビットコインあたり2万ドルとvbyteあたり1聡の最低中継料金で計算します。" +"碑文の内容を公開するためのコストは100万バイトあたり50ドルです。" + +#: src/faq.md:254 +msgid "" +"_Inscriptions are early!_ Inscriptions are still in development, and have " +"not yet launched on mainnet. This gives you an opportunity to be an early " +"adopter, and explore the medium as it evolves." +msgstr "" +"_铭文还处于项目早期_ 铭文仍在开发中,尚未在主网上发布(建议更新)。 " +"这使您有机会成为早期采用者,并随着媒体的发展探索它。" + +#: src/faq.md:258 +msgid "" +"_Inscriptions are simple._ Inscriptions do not require writing or " +"understanding smart contracts." +msgstr "" +"_铭文很简单_ 铭文不需要你编写或理解智能合约。" + +#: src/faq.md:261 +msgid "" +"_Inscriptions unlock new liquidity._ Inscriptions are more accessible and " +"appealing to bitcoin holders, unlocking an entirely new class of collector." +msgstr "" +"_銘文ロック解除新しい流動性_ビットコインの所有者にとって、銘文はより簡単に入手でき、より魅力的で、新しいコレクションをもたらします。" + +#: src/faq.md:264 +msgid "" +"_Inscriptions are designed for digital artifacts._ Inscriptions are designed " +"from the ground up to support NFTs, and feature a better data model, and " +"features like globally unique symbols and enhanced provenance." +msgstr "" +"_銘文はデジタル文化財のために設計されています_新しいデザインの銘文はNFTをサポートし、より良いデータモデルを持っています," +"や、世界的にユニークなシンボルや拡張ソースなどの機能です。" + +#: src/faq.md:268 +msgid "" +"_Inscriptions do not support on-chain royalties._ This is negative, but only " +"depending on how you look at it. On-chain royalties have been a boon for " +"creators, but have also created a huge amount of confusion in the Ethereum " +"NFT ecosystem. The ecosystem now grapples with this issue, and is engaged in " +"a race to the bottom, towards a royalties-optional future. Inscriptions have " +"no support for on-chain royalties, because they are technically infeasible. " +"If you choose to create inscriptions, there are many ways you can work " +"around this limitation: withhold a portion of your inscriptions for future " +"sale, to benefit from future appreciation, or perhaps offer perks for users " +"who respect optional royalties." +msgstr "" +"_銘文はチェーン上のロイヤリティを奨励しない_これは良いニュースではないかもしれませんが、それをどう見るかによっても異なります。チェーン上のロイヤリティは常にクリエイターにとっての福音です" +"しかし、はイーサリアムNFT生態系にも大きな混乱をもたらした。イーサリアムは今この問題を解決しようと努力しています。底をついた競争でもあります。" +"は「オプションのロイヤリティ」の未来を実現する。銘文はチェーン上のロイヤリティをサポートしていません。技術的に不可能だからです。」" +"銘文を作成することを選択した場合、この制限を迴避する方法はたくさんあります。銘文の一部を将来の販売のために残して、将来の上昇から利益を得ます。" +"またはオプションのロイヤリティを尊重するユーザーに追加の手当を提供します。" + +#: src/faq.md:279 +msgid "Collectors" +msgstr "コレクター" + +#: src/faq.md:281 +msgid "" +"_Inscriptions are simple, clear, and have no surprises._ They are always " +"immutable and on-chain, with no special due diligence required." +msgstr "" +"_銘文は簡単です_、はっきりしていて事故はありません*それらは常に不変でチェーン上にあり、特別なデューデリジェンスは必要ありません。" + +#: src/faq.md:284 +msgid "" +"_Inscriptions are on Bitcoin._ You can verify the location and properties of " +"inscriptions easily with Bitcoin full node that you control." +msgstr "" +"_ビットコイン上の銘文_あなたが制御するビットコインのフルノードを使用して、銘文の位置と属性を簡単に検証できます。" + +#: src/faq.md:287 +msgid "Bitcoiners" +msgstr "ビットコインの信仰者" + +#: src/faq.md:289 +msgid "" +"Let me begin this section by saying: the most important thing that the " +"Bitcoin network does is decentralize money. All other use-cases are " +"secondary, including ordinal theory. The developers of ordinal theory " +"understand and acknowledge this, and believe that ordinal theory helps, at " +"least in a small way, Bitcoin's primary mission." +msgstr "" +"冒頭で説明しましょう。ビットコインネットワークが行っている最も重要なことは、通貨の中心化です。" +"の他のすべてのユースケースは、序数理論を含む副次的なものです。序数理論の開発者はこれを理解し、認めています。" +"そして、序数理論はビットコインの主要な課題に少なくともわずかに寄与すると信じています。" + +#: src/faq.md:295 +msgid "" +"Unlike many other things in the altcoin space, digital artifacts have merit. " +"There are, of course, a great deal of NFTs that are ugly, stupid, and " +"fraudulent. However, there are many that are fantastically creative, and " +"creating and collecting art has been a part of the human story since its " +"inception, and predates even trade and money, which are also ancient " +"technologies." +msgstr "" +"他のパクリ通貨分野のものとは異なり、デジタル文化財には利点がある。もちろん、多くのNFTは醜い、愚か、詐欺的です。" +"しかし、素晴らしいアイデアはたくさんあります。芸術を創造し、収蔵することはもともと人間の物語の一部です。" +"は貿易やお金といった同じ古い技術よりも早いです。" + +#: src/faq.md:302 +msgid "" +"Bitcoin provides an amazing platform for creating and collecting digital " +"artifacts in a secure, decentralized way, that protects users and artists in " +"the same way that it provides an amazing platform for sending and receiving " +"value, and for all the same reasons." +msgstr "" +"ビットコインは、安全で分散化された方法でデジタルアーティファクトを作成し、収集するための素晴らしいプラットフォームを提供しています。" +"も同様にユーザーとアーティストを保護し、同時に価値を送受信する優れたプラットフォームを提供しています。" + +#: src/faq.md:307 +msgid "" +"Ordinals and inscriptions increase demand for Bitcoin block space, which " +"increase Bitcoin's security budget, which is vital for safeguarding " +"Bitcoin's transition to a fee-dependent security model, as the block subsidy " +"is halved into insignificance." +msgstr "" +"序数と銘文はビットコインのブロックスペースの必要性を高め、ビットコインのセキュリティ予算を増加させた。" +"はビットコインが費用依存型のセキュリティモデルに移行することを保障するために重要であります。ブロック補助金の半減はわずかになったからであります。" + +#: src/faq.md:312 +msgid "" +"Inscription content is stored on-chain, and thus the demand for block space " +"for use in inscriptions is unlimited. This creates a buyer of last resort " +"for _all_ Bitcoin block space. This will help support a robust fee market, " +"which ensures that Bitcoin remains secure." +msgstr "" +"銘文の内容はチェーンに保存されているので、銘文のためのブロック空間の需要は無限であります。" +"これにより、すべてのビットコインのブロックスペースに最後の買い手が生まれます。" +"これは強力な有料市場をサポートし、ビットコインが常に安全であることを保証するのに役立ちます。" + +#: src/faq.md:317 +msgid "" +"Inscriptions also counter the narrative that Bitcoin cannot be extended or " +"used for new use-cases. If you follow projects like DLCs, Fedimint, " +"Lightning, Taro, and RGB, you know that this narrative is false, but " +"inscriptions provide a counter argument which is easy to understand, and " +"which targets a popular and proven use case, NFTs, which makes it highly " +"legible." +msgstr "" +"銘文はまた、ビットコインは拡張できない、または新しいユースケースに使用できないという説に反論した。DLC、Fedimint、Lightning、に注目すると" +"TaroやRGBなどのプロジェクトをすると、この言い方が間違っていることがわかります。碑文は、理解しやすい反論を提供しています。" +"そして、一般的で実証済みのユースケースについて:NFT,これにより、非常に理解しやすくなります。" + +#: src/faq.md:323 +msgid "" +"If inscriptions prove, as the authors hope, to be highly sought after " +"digital artifacts with a rich history, they will serve as a powerful hook " +"for Bitcoin adoption: come for the fun, rich art, stay for the decentralized " +"digital money." +msgstr "" +"作者が望むように、銘文が豊富な歴史を持つデジタル文化財であることが証明され、高く支持されていれば" +"それらはビットコインに採用される強力な魅力になります:楽しさ、豊かな芸術に惹かれて、" +"脱中心化されたデジタル通貨のためにも残りたいです。" + +#: src/faq.md:327 +msgid "" +"Inscriptions are an extremely benign source of demand for block space. " +"Unlike, for example, stablecoins, which potentially give large stablecoin " +"issuers influence over the future of Bitcoin development, or DeFi, which " +"might centralize mining by introducing opportunities for MEV, digital art " +"and collectables on Bitcoin, are unlikely to produce individual entities " +"with enough power to corrupt Bitcoin. Art is decentralized." +msgstr "" +"銘文はブロック空間需要の極めて健全な源であり、安定通貨とは異なり、大手発行者がビットコインの未来をする可能性があります" +"発展に影響を与えて;DeFiとは異なり、ビットコインにMEV、デジタルアート、コレクションを導入する機会を通じて、マイニングを集中化することができます。" +"芸術は脱中心化されており、いかなる実体も権力を使ってビットコインを破壊することはできません。" + +#: src/faq.md:334 +msgid "" +"Inscription users and service providers are incentivized to run Bitcoin full " +"nodes, to publish and track inscriptions, and thus throw their economic " +"weight behind the honest chain." +msgstr "" +"銘文ユーザーとサービスプロバイダーは、ビットコインのフルノードを実行し、追跡銘文を発行して、彼らの経済的重みを正直なチェーンに向けるように動機付けられています。" + +#: src/faq.md:338 +msgid "" +"Ordinal theory and inscriptions do not meaningfully affect Bitcoin's " +"fungibility. Bitcoin users can ignore both and be unaffected." +msgstr "" +"序数理論と銘文はビットコインの代替可能性に大きな影響を与えない。ビットコインユーザーはこの2つを無視しても影響を受けません。" + +#: src/faq.md:341 +msgid "" +"We hope that ordinal theory strengthens and enriches bitcoin, and gives it " +"another dimension of appeal and functionality, enabling it more effectively " +"serve its primary use case as humanity's decentralized store of value." +msgstr "" +"序数理論がビットコインを強化し、豊かにし、別の次元の魅力と機能を与えることを望んでいます。" +"人間の分散化された価値ストレージとしての主要なユースケースにより効率的にサービスを提供できるようにします。" + +#: src/contributing.md:1 +msgid "Contributing to `ord`" +msgstr "どのように`ord`のために貢献しますか" + +#: src/contributing.md:4 +msgid "Suggested Steps" +msgstr "お勧めの手順" + +#: src/contributing.md:7 +msgid "Find an issue you want to work on." +msgstr "解決したい問題を見つけました。" + +#: src/contributing.md:8 +msgid "" +"Figure out what would be a good first step towards resolving the issue. This " +"could be in the form of code, research, a proposal, or suggesting that it be " +"closed, if it's out of date or not a good idea in the first place." +msgstr "" +"この問題を解決するための良い第一歩とは何かを明らかにします。これはコード、研究、提案の形にすることができます。または" +"は、それが古くなった場合、または最初から良いアイデアではない場合は、それを閉じることをお勧めします。" + +#: src/contributing.md:11 +msgid "" +"Comment on the issue with an outline of your suggested first step, and " +"asking for feedback. Of course, you can dive in and start writing code or " +"tests immediately, but this avoids potentially wasted effort, if the issue " +"is out of date, not clearly specified, blocked on something else, or " +"otherwise not ready to implement." +msgstr "" +"提案した最初のステップの概要を説明し、問題についてコメントし、フィードバックを求めます。もちろん、すぐに投入して始めることもできます" +"コードを書いたり、テストしたりする。しかし、問題がすでに時代遅れ、明確に制定されていなく、他の理由で妨げられていて、または準備ができていない場合" +"はよく実施され、このステップは潜在的なエネルギーの浪費を避けることができます。" + +#: src/contributing.md:16 +msgid "" +"If the issue requires a code change or bugfix, open a draft PR with tests, " +"and ask for feedback. This makes sure that everyone is on the same page " +"about what needs to be done, or what the first step in solving the issue " +"should be. Also, since tests are required, writing the tests first makes it " +"easy to confirm that the change can be tested easily." +msgstr "" +"コードの変更やエラーの修正が必要な場合は、テストPRのドラフトを開き、フィードバックを求めてください。これは保証されます" +"誰もが同期して何をすべきか、あるいはこの問題を解決する最初のステップは何かを知っています。同様に、デバッグ" +"は必須なので、まずテストドラフトを作成し、更新が容易にテストできることを確認します。" + +#: src/contributing.md:21 +msgid "" +"Mash the keyboard randomly until the tests pass, and refactor until the code " +"is ready to submit." +msgstr "" +"テストに合格するまでキーボードをランダムにタップし、コードをコミットする準備ができるまでリファクタリングします。" + +#: src/contributing.md:23 +msgid "Mark the PR as ready to review." +msgstr "" +"PRをレビュー準備完了としてマーク。" + +#: src/contributing.md:24 +msgid "Revise the PR as needed." +msgstr "必要であれば PRを直します 。" + +#: src/contributing.md:25 +msgid "And finally, mergies!" +msgstr "最後のの一歩!" + +#: src/contributing.md:27 +msgid "Start small" +msgstr "塵を重ねば、山となる" + +#: src/contributing.md:30 +msgid "" +"Small changes will allow you to make an impact quickly, and if you take the " +"wrong tack, you won't have wasted much time." +msgstr "小さな変化はあなたに迅速に影響力を与えることができ、間違った戦略をとっても、あまり時間を無駄にしません。" + +#: src/contributing.md:33 +msgid "Ideas for small issues:" +msgstr "いくつかの小さな問題の考え:" + +#: src/contributing.md:34 +msgid "Add a new test or test case that increases test coverage" +msgstr "新しいテストまたはテストケースを追加して、テストのカバー率を高めます。" + +#: src/contributing.md:35 +msgid "Add or improve documentation" +msgstr "ドキュメントの追加または改善" + +#: src/contributing.md:36 +msgid "" +"Find an issue that needs more research, and do that research and summarize " +"it in a comment" +msgstr "より多くの研究が必要な問題を見つけ、研究を行い、コメントにまとめます" + +#: src/contributing.md:38 +msgid "Find an out-of-date issue and comment that it can be closed" +msgstr "古い質問を見つけ、コメントして閉じます。" + +#: src/contributing.md:39 +msgid "" +"Find an issue that shouldn't be done, and provide constructive feedback " +"detailing why you think that is the case" +msgstr "本来すべきではない問題を見つけ、建設的なフィードバックを提供して、このような状況が発生すると考えられる理由を詳しく説明します" + +#: src/contributing.md:42 +msgid "Merge early and often" +msgstr "早く合併し、よく合併します" + +#: src/contributing.md:45 +msgid "" +"Break up large tasks into multiple smaller steps that individually make " +"progress. If there's a bug, you can open a PR that adds a failing ignored " +"test. This can be merged, and the next step can be to fix the bug and " +"unignore the test. Do research or testing, and report on your results. Break " +"a feature into small sub-features, and implement them one at a time." +msgstr "" +"大規模なタスクを複数の小さなステップに分け、これらのステップが個別に取ることができる進展。プログラムエラーがある場合は、" +"PRを開くこともできます。失敗した無視テストを追加します。これはマージすることができ、次のステップでエラーを修正することができます" +"とテストを無視します。あなたの研究またはテスト結果を報告します。大きな機能を小さなサブ機能に分解します。" +"そして、それらを一度に1つずつ段階的に実現します。" + +#: src/contributing.md:51 +msgid "" +"Figuring out how to break down a larger PR into smaller PRs where each can " +"be merged is an art form well-worth practicing. The hard part is that each " +"PR must itself be an improvement." +msgstr "" +"大きなPRを小さなPRに分解する方法を明らかにし、すべてのPRが統合できるのは非常に練習価値があります。" +"これもプログラミングの芸術です。難しい部分は、各PR自体が改善でなければならないことです。" + +#: src/contributing.md:55 +msgid "" +"I strive to follow this advice myself, and am always better off when I do." +msgstr "" +"私は自分でこのアドバイスに従うように努力しています。そして、私がそうすると、私はいつももっと上手にできます。" + +#: src/contributing.md:57 +msgid "" +"Small changes are fast to write, review, and merge, which is much more fun " +"than laboring over a single giant PR that takes forever to write, review, " +"and merge. Small changes don't take much time, so if you need to stop " +"working on a small change, you won't have wasted much time as compared to a " +"larger change that represents many hours of work. Getting a PR in quickly " +"improves the project a little bit immediately, instead of having to wait a " +"long time for larger improvement. Small changes are less likely to " +"accumulate merge conflict. As the Athenians said: _The fast commit what they " +"will, the slow merge what they must._" +msgstr "" +"小さな変更は、迅速に作成、レビュー、マージすることができます。これは、永遠に作成、レビュー、マージする必要がある大規模な" +"PRの仕事はもっと面白いです。小さな変更にはあまり時間がかからないので、小さな変更の処理を中止する必要がある場合は、" +"何時間もの仕事を表す大きな変化に比べて、あまり時間を無駄にしません。迅速なPR獲得はプロジェクトをすぐに改善することができます。" +"はより大きな改善を行うために長い時間を待つ必要はありません。小さな変更ではマージの競合が累積する可能性は低くなります。" +"はアテネ人が言ったように、_速い者はその望みを尽くし、遅い者はその必要を併合します。_" + +#: src/contributing.md:67 +msgid "Get help" +msgstr "助けを求めます。" + +#: src/contributing.md:70 +msgid "" +"If you're stuck for more than 15 minutes, ask for help, like a Rust Discord, " +"Stack Exchange, or in a project issue or discussion." +msgstr "" +"15分以上困っている場合は、例えば、助けを求めてくださいRust Discord、Stack Exchange," +"またはプロジェクトの問題や議論で助けを求めます。" + +#: src/contributing.md:73 +msgid "Practice hypothesis-driven debugging" +msgstr "「仮説駆動型」のデバッグを実践します。" + +#: src/contributing.md:76 +msgid "" +"Formulate a hypothesis as to what is causing the problem. Figure out how to " +"test that hypothesis. Perform that tests. If it works, great, you fixed the " +"issue or now you know how to fix the issue. If not, repeat with a new " +"hypothesis." +msgstr "" +"問題の原因について仮説を立てる。この仮説をどのように検証するかを明らかにする。テストを実行します。効果があれば、それは素晴らしいことです。" +"は問題を解決しました。または、問題を解決する方法を知っています。そうでなければ、新しい仮定を繰り返してください。。" + +#: src/contributing.md:81 +msgid "Pay attention to error messages" +msgstr "エラーメッセージを注目します" + +#: src/contributing.md:84 +msgid "Read all error messages and don't tolerate warnings." +msgstr "すべてのエラーメッセージを読み、警告を容認しないでください。" + +#: src/donate.md:4 +msgid "" +"Ordinals is open-source and community funded. The current lead maintainer of " +"`ord` is [raphjaph](https://github.com/raphjaph/). Raph's work on `ord` is " +"entirely funded by donations. If you can, please consider donating!" +msgstr "" +"Ordinals序数はオープンソースで、コミュニティが資金を提供するプロジェクトです。現在の『ord』のチーフメンテナンス担当者は" +"[raphjaph](https://github.com/raphjaph/)." +"「Raphの『ord』でのメンテナンスはすべて寄付金で行われました。よろしければ、寄付を検討してください!!" + +#: src/donate.md:8 +msgid "" +"The donation address for Bitcoin is " +"[bc1q8kt9pyd6r27k2840l8g5d7zshz3cg9v6rfda0m248lva3ve5072q3sxelt](https://" +"mempool.space/address/" +"bc1q8kt9pyd6r27k2840l8g5d7zshz3cg9v6rfda0m248lva3ve5072q3sxelt). The " +"donation address for inscriptions is " +"[bc1qn3map8m9hmk5jyqdkkwlwvt335g94zvxwd9aql7q3vdkdw9r5eyqvlvec0](https://" +"mempool.space/address/" +"bc1qn3map8m9hmk5jyqdkkwlwvt335g94zvxwd9aql7q3vdkdw9r5eyqvlvec0)." +msgstr "" +"寄与のアドレスは " +"[bc1q8kt9pyd6r27k2840l8g5d7zshz3cg9v6rfda0m248lva3ve5072q3sxelt](https://" +"mempool.space/address/" +"bc1q8kt9pyd6r27k2840l8g5d7zshz3cg9v6rfda0m248lva3ve5072q3sxelt). " +"銘文の寄与のアドレスは " +"[bc1qn3map8m9hmk5jyqdkkwlwvt335g94zvxwd9aql7q3vdkdw9r5eyqvlvec0](https://" +"mempool.space/address/" +"bc1qn3map8m9hmk5jyqdkkwlwvt335g94zvxwd9aql7q3vdkdw9r5eyqvlvec0)." + +#: src/donate.md:11 +msgid "" +"Both addresses are in a 2 of 4 multisig wallet with keys held by [raphjaph]" +"(https://twitter.com/raphjaph), [erin](https://twitter.com/realizingerin), " +"[rodarmor](https://twitter.com/rodarmor), and [ordinally](https://twitter." +"com/veryordinally)." +msgstr "" +"上記の2つの住所は以下の多署名者(2/4)が保有管理しています。[raphjaph]: [raphjaph]" +"(https://twitter.com/raphjaph), [erin](https://twitter.com/realizingerin), " +"[rodarmor](https://twitter.com/rodarmor), and [ordinally](https://twitter." +"com/veryordinally)." + +#: src/donate.md:17 +msgid "" +"Donations received will go towards funding maintenance and development of " +"`ord`, as well as hosting costs for [ordinals.com](https://ordinals.com)." +msgstr "" +"受け取った寄付金は『ord』の維持と更なる開発に資金を提供するために使われます。" +"は同時に[ordinals.com](https://ordinals.com)のホスト費用を支払います。" + +#: src/donate.md:20 +msgid "Thank you for donating!" +msgstr "ご寄与を感謝いたします!" + +#: src/guides.md:1 +msgid "Ordinal Theory Guides" +msgstr "序数理論の指導" + +#: src/guides.md:4 +msgid "" +"See the table of contents for a list of guides, including a guide to the " +"explorer, a guide for sat hunters, and a guide to inscriptions." +msgstr "" +"ガイドの一覧については、カタログを参照してください。これには、ブロックブラウザガイド、スマートフォンガイド、銘文ガイドなどがあります。" + +#: src/guides/explorer.md:1 +msgid "Ordinal Explorer" +msgstr "序数ブラウザ" + +#: src/guides/explorer.md:4 +msgid "" +"The `ord` binary includes a block explorer. We host a instance of the block " +"explorer on mainnet at [ordinals.com](https://ordinals.com), and on signet " +"at [signet.ordinals.com](https://signet.ordinals.com)." +msgstr "" +"`ord` ファイルにはブロックブラウザが含まれています。当社のメインネットワークブロックチェーンは [ordinals.com](https://ordinals.com), " +"signet[signet.ordinals.com](https://signet.ordinals.com)に配置します。" + +#: src/guides/explorer.md:8 +msgid "Running The Explorer" +msgstr "運行ブラウザ" + +#: src/guides/explorer.md:9 +msgid "The server can be run locally with:" +msgstr "サーバはローカルで運行可能:" + +#: src/guides/explorer.md:11 +msgid "`ord server`" +msgstr "" + +#: src/guides/explorer.md:13 +msgid "To specify a port add the `--http-port` flag:" +msgstr "指定されたポートは、'--http-port'タグを使用します。" + +#: src/guides/explorer.md:15 +msgid "`ord server --http-port 8080`" +msgstr "" + +#: src/guides/explorer.md:17 +msgid "To test how your inscriptions will look you can run:" +msgstr "銘文をテストして、運行できます:" + +#: src/guides/explorer.md:19 +msgid "`ord preview ...`" +msgstr "" + +#: src/guides/explorer.md:21 +msgid "Search" +msgstr "検索" + +#: src/guides/explorer.md:24 +msgid "The search box accepts a variety of object representations." +msgstr "検索ボックスではさまざまなオブジェクトを使用できます:" + +#: src/guides/explorer.md:26 +msgid "Blocks" +msgstr "ブロック" + +#: src/guides/explorer.md:28 +msgid "Blocks can be searched by hash, for example, the genesis block:" +msgstr "ブロックはハッシュで見つけることができます。例えば、創世ブロックです:" + +#: src/guides/explorer.md:30 +msgid "" +"[000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f](https://" +"ordinals.com/" +"search/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f)" +msgstr "" + +#: src/guides/explorer.md:32 +msgid "Transactions" +msgstr "取引" + +#: src/guides/explorer.md:34 +msgid "" +"Transactions can be searched by hash, for example, the genesis block " +"coinbase transaction:" +msgstr "創世記ブロックのcoinbaseトランザクションなど、ハッシュによってトランザクションを見つけることができます。:" + +#: src/guides/explorer.md:37 +msgid "" +"[4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b](https://" +"ordinals.com/" +"search/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b)" +msgstr "" + +#: src/guides/explorer.md:39 +msgid "Outputs" +msgstr "輸出" + +#: src/guides/explorer.md:41 +msgid "" +"Transaction outputs can searched by outpoint, for example, the only output " +"of the genesis block coinbase transaction:" +msgstr "" +"アウトポイントを使用して、創世ブロックcoinbaseトランザクションのユニークな出力などのトランザクション出力を検索できます:" + +#: src/guides/explorer.md:44 +msgid "" +"[4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0](https://" +"ordinals.com/" +"search/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0)" +msgstr "" + +#: src/guides/explorer.md:46 +msgid "Sats" +msgstr "聡" + +#: src/guides/explorer.md:48 +msgid "" +"Sats can be searched by integer, their position within the entire bitcoin " +"supply:" +msgstr "" +"聡は整数で検索することができ、ビットコインの供給全体の中のそれらの位置:" + +#: src/guides/explorer.md:51 +msgid "[2099994106992659](https://ordinals.com/search/2099994106992659)" +msgstr "" + +#: src/guides/explorer.md:53 +msgid "By decimal, their block and offset within that block:" +msgstr "10進数では、そのブロックとそのブロック内のオフセット:" + +#: src/guides/explorer.md:55 +msgid "[481824.0](https://ordinals.com/search/481824.0)" +msgstr "" + +#: src/guides/explorer.md:57 +msgid "" +"By degree, their cycle, blocks since the last halving, blocks since the last " +"difficulty adjustment, and offset within their block:" +msgstr "度数、それらの週期、前回の半減以来のブロック、前回の難易度調整以来のブロック、そしてブロック内のオフセット:" + +#: src/guides/explorer.md:60 +msgid "[1°0′0″0‴](https://ordinals.com/search/1°0′0″0‴)" +msgstr "" + +#: src/guides/explorer.md:62 +msgid "" +"By name, their base 26 representation using the letters \"a\" through \"z\":" +msgstr "名前に応じて、文字\"a\"~\"z\"の26文字の組み合わせで表されます:" + +#: src/guides/explorer.md:64 +msgid "[ahistorical](https://ordinals.com/search/ahistorical)" +msgstr "" + +#: src/guides/explorer.md:66 +msgid "" +"Or by percentile, the percentage of bitcoin's supply that has been or will " +"have been issued when they are mined:" +msgstr "または百分率で、採掘時にすでに発行された、または発行される予定のビットコインの供給量のパーセント:" + +#: src/guides/explorer.md:69 +msgid "[100%](https://ordinals.com/search/100%)" +msgstr "" + +#: src/guides/inscriptions.md:1 +msgid "Ordinal Inscription Guide" +msgstr "銘文のガイド" + +#: src/guides/inscriptions.md:4 +msgid "" +"Individual sats can be inscribed with arbitrary content, creating Bitcoin-" +"native digital artifacts that can be held in a Bitcoin wallet and " +"transferred using Bitcoin transactions. Inscriptions are as durable, " +"immutable, secure, and decentralized as Bitcoin itself." +msgstr "" +"単一のコングは、ビットコインウォレットに保存され、ビットコイントランザクションを使用して転送" +"されるビットコインネイティブデジタルアーティファクトを作成するために、任意のコンテンツを刻印することができます。" +"の銘文はビットコイン自体と同じくらい持続的で、不変で、安全で、分散化されています。" + +#: src/guides/inscriptions.md:9 +msgid "" +"Working with inscriptions requires a Bitcoin full node, to give you a view " +"of the current state of the Bitcoin blockchain, and a wallet that can create " +"inscriptions and perform sat control when constructing transactions to send " +"inscriptions to another wallet." +msgstr "" +"銘文を使用するには、ビットコインのブロックチェーンの現在の状態を知ることができるビットコイン" +"の完全なノードが必要です。また、銘文を作成し、取引を構築することができます」" +"他のウォレットに銘文を送信するときにスマートコントロールを実行するウォレット。" + +#: src/guides/inscriptions.md:14 +msgid "" +"Bitcoin Core provides both a Bitcoin full node and wallet. However, the " +"Bitcoin Core wallet cannot create inscriptions and does not perform sat " +"control." +msgstr "" +"Bitcoin Core ビットコインのフルノードとウォレットを提供します。しかし,Bitcoin Coreウォ" +"レットは碑文を作成できず、スマートコントロールを実行しません。" + +#: src/guides/inscriptions.md:17 +msgid "" +"This requires [`ord`](https://github.com/ordinals/ord), the ordinal utility. " +"`ord` doesn't implement its own wallet, so `ord wallet` subcommands interact " +"with Bitcoin Core wallets." +msgstr "" +"これには['ord'](https://github.com/ordinals/ord),序数ユーティリティ。" +"'ord'は自分のウォレットを持っていないので、'ord wallet'サブコマンドはBitcoin Coreウォレットと対話します。" + +#: src/guides/inscriptions.md:21 +msgid "This guide covers:" +msgstr "このガイドの含まれ:" + +#: src/guides/inscriptions.md:23 src/guides/inscriptions.md:39 +msgid "Installing Bitcoin Core" +msgstr " Bitcoin Coreを取り付けます。" + +#: src/guides/inscriptions.md:24 +msgid "Syncing the Bitcoin blockchain" +msgstr "ビットコインのブロックを同期します。" + +#: src/guides/inscriptions.md:25 +msgid "Creating a Bitcoin Core wallet" +msgstr "Bitcoin Core ウォレットを作り上げます。" + +#: src/guides/inscriptions.md:26 +msgid "Using `ord wallet receive` to receive sats" +msgstr " `ord wallet receive`を使って聡を取り受けます。" + +#: src/guides/inscriptions.md:27 +msgid "Creating inscriptions with `ord wallet inscribe`" +msgstr "`ord wallet inscribe`を使って、銘文を作り上げます。" + +#: src/guides/inscriptions.md:28 +msgid "Sending inscriptions with `ord wallet send`" +msgstr "`ord wallet send`を使って`銘文を発送します" + +#: src/guides/inscriptions.md:29 +msgid "Receiving inscriptions with `ord wallet receive`" +msgstr "`ord wallet receive`を使って`銘文を受け取ります。" + +#: src/guides/inscriptions.md:31 +msgid "Getting Help" +msgstr "助けを求めます。" + +#: src/guides/inscriptions.md:34 +msgid "" +"If you get stuck, try asking for help on the [Ordinals Discord Server]" +"(https://discord.com/invite/87cjuz4FYg), or checking GitHub for relevant " +"[issues](https://github.com/ordinals/ord/issues) and [discussions](https://" +"github.com/ordinals/ord/discussions)." +msgstr "" +"困ったことがあったら、[Ordinals Discord Server](https://discord.com/invite/87cjuz4FYg)," +"またはGithubの関連内容をチェックする[質問](https://github.com/ordinals/ord/issues)と" +"[ディスカッション](https://github.com/ordinals/ord/discussions)." + +#: src/guides/inscriptions.md:42 +msgid "" +"Bitcoin Core is available from [bitcoincore.org](https://bitcoincore.org/) " +"on the [download page](https://bitcoincore.org/en/download/)." +msgstr "" +"[bitcoincore.org](https://bitcoincore.org/)で」" +"の[ダウンロードページ](https://bitcoincore.org/en/download/)" + +#: src/guides/inscriptions.md:45 +msgid "Making inscriptions requires Bitcoin Core 24 or newer." +msgstr "銘文を作成するにはBitcoin Core 24以降が必要です。" + +#: src/guides/inscriptions.md:47 +msgid "" +"This guide does not cover installing Bitcoin Core in detail. Once Bitcoin " +"Core is installed, you should be able to run `bitcoind -version` " +"successfully from the command line." +msgstr "" +"このガイドには、Bitcoin Coreの詳細なインストール方法は含まれていません。Bitcoin Coreのインストールに成功した後、" +"コマンドラインで'bitcoind-version'コマンドを使うことができます。" + +#: src/guides/inscriptions.md:51 +msgid "Configuring Bitcoin Core" +msgstr " Bitcoin Coreを配置します。" + +#: src/guides/inscriptions.md:54 +msgid "`ord` requires Bitcoin Core's transaction index." +msgstr "`ord` Bitcoin Core の取引索引が必要です。" + +#: src/guides/inscriptions.md:56 +msgid "" +"To configure your Bitcoin Core node to maintain a transaction index, add the " +"following to your `bitcoin.conf`:" +msgstr "" +"トランザクションインデックスを配置するためにBitcoin Coreフェーズを設定します,'bitcoin.conf'に追加する必要があります::" + +#: src/guides/inscriptions.md:59 src/guides/sat-hunting.md:30 +msgid "" +"```\n" +"txindex=1\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:63 +msgid "Or, run `bitcoind` with `-txindex`:" +msgstr "または, `bitcoind` 和 `-txindex`を運行します:" + +#: src/guides/inscriptions.md:65 src/guides/inscriptions.md:74 +msgid "" +"```\n" +"bitcoind -txindex\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:69 +msgid "Syncing the Bitcoin Blockchain" +msgstr "ビットコインのブロックを同期にします。" + +#: src/guides/inscriptions.md:72 +msgid "To sync the chain, run:" +msgstr "ブロックを同期にして、運行します:" + +#: src/guides/inscriptions.md:78 +msgid "…and leave it running until `getblockcount`:" +msgstr "… `getblockcount運行するまで`:" + +#: src/guides/inscriptions.md:80 +msgid "" +"```\n" +"bitcoin-cli getblockcount\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:84 +msgid "" +"agrees with the block count on a block explorer like [the mempool.space " +"block explorer](https://mempool.space/). `ord` interacts with `bitcoind`, so " +"you should leave `bitcoind` running in the background when you're using " +"`ord`." +msgstr "" +"ブロックチェーンブラウザのように[the mempool.space block explorer](https://mempool.space/)のように" +"ブロックを記述する...`ord`は'bitcoind'と相互作用するので、'ord'を使用するときは'bitcoind'をバックグラウンドで実行する必要があります。" + +#: src/guides/inscriptions.md:88 +msgid "Installing `ord`" +msgstr " `ord取り付けます。`" + +#: src/guides/inscriptions.md:91 +msgid "" +"The `ord` utility is written in Rust and can be built from [source](https://" +"github.com/ordinals/ord). Pre-built binaries are available on the [releases " +"page](https://github.com/ordinals/ord/releases)." +msgstr "" +"`ord` プログラムはRust言語で書かれており、[ソースコード](https://github.com/ordinals/ord)インストール." +"事前に作成されたファイルは、[バージョンリリースページ](https://github.com/ordinals/ord/releases))からダウンロードできます。" + +#: src/guides/inscriptions.md:95 +msgid "You can install the latest pre-built binary from the command line with:" +msgstr "コマンドラインで次のコマンドを使用して、最新のファイルをインストールすることもできます。:" + +#: src/guides/inscriptions.md:97 +msgid "" +"```sh\n" +"curl --proto '=https' --tlsv1.2 -fsLS https://ordinals.com/install.sh | bash " +"-s\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:101 +msgid "Once `ord` is installed, you should be able to run:" +msgstr "'ord'が正常にインストールされた後、あなたは実行することができます :" + +#: src/guides/inscriptions.md:103 +msgid "" +"```\n" +"ord --version\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:107 +msgid "Which prints out `ord`'s version number." +msgstr "これにより、「ord」のバージョン番号が出力されます。" + +#: src/guides/inscriptions.md:109 +msgid "Creating a Bitcoin Core Wallet" +msgstr "『ord』という名前のBitcoin Coreウォレットを作成します。" + +#: src/guides/inscriptions.md:112 +msgid "" +"`ord` uses Bitcoin Core to manage private keys, sign transactions, and " +"broadcast transactions to the Bitcoin network." +msgstr "`ord` Bitcoin Coreを使用して秘密鍵を管理し、トランザクションに署名し、ビットコインネットワークにトランザクションをブロードキャストします。。" + +#: src/guides/inscriptions.md:115 +msgid "To create a Bitcoin Core wallet named `ord` for use with `ord`, run:" +msgstr "『ord』という名前のBitcoin Coreウォレットを作成し、運行します:" + +#: src/guides/inscriptions.md:117 +msgid "" +"```\n" +"ord wallet create\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:121 +msgid "Receiving Sats" +msgstr "聡を取り受けます。" + +#: src/guides/inscriptions.md:124 +msgid "" +"Inscriptions are made on individual sats, using normal Bitcoin transactions " +"that pay fees in sats, so your wallet will need some sats." +msgstr "銘文は、単一のコングに作成され、通常のビットコイン取引のためにコングを使用して料金を支払うので、あなたの財布はいくつかのコング(ビットコイン)を必要とします。" + +#: src/guides/inscriptions.md:127 +msgid "Get a new address from your `ord` wallet by running:" +msgstr "'ord'ウォレットの新しいアドレスを作成して、実行します::" + +#: src/guides/inscriptions.md:129 src/guides/inscriptions.md:201 +#: src/guides/inscriptions.md:229 +msgid "" +"```\n" +"ord wallet receive\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:133 +msgid "And send it some funds." +msgstr "上記の住所に資金を発送します。" + +#: src/guides/inscriptions.md:135 +msgid "You can see pending transactions with:" +msgstr "以下のコマンドで取引状況を見ることができます:" + +#: src/guides/inscriptions.md:137 src/guides/inscriptions.md:213 +#: src/guides/inscriptions.md:240 +msgid "" +"```\n" +"ord wallet transactions\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:141 +msgid "" +"Once the transaction confirms, you should be able to see the transactions " +"outputs with `ord wallet outputs`." +msgstr "取引が確認されたら、'ord wallet outputs'を使って取引の輸出を見ることができるはずです;" + +#: src/guides/inscriptions.md:144 +msgid "Creating Inscription Content" +msgstr "銘文の内容を作成します。" + +#: src/guides/inscriptions.md:147 +msgid "" +"Sats can be inscribed with any kind of content, but the `ord` wallet only " +"supports content types that can be displayed by the `ord` block explorer." +msgstr "聡の上ではあらゆる種類のコンテンツを書き込むことができますが、'ord'ウォレットは'ord'ブロックブラウザで表示できる種類のコンテンツしかサポートしていません。" + +#: src/guides/inscriptions.md:150 +msgid "" +"Additionally, inscriptions are included in transactions, so the larger the " +"content, the higher the fee that the inscription transaction must pay." +msgstr "また、銘文は取引に含まれているため、内容が大きいほど銘文取引にかかる費用が高くなります。" + +#: src/guides/inscriptions.md:153 +msgid "" +"Inscription content is included in transaction witnesses, which receive the " +"witness discount. To calculate the approximate fee that an inscribe " +"transaction will pay, divide the content size by four and multiply by the " +"fee rate." +msgstr "" +"銘文の内容は取引証言に含まれ、証言割引を受ける。トランザクションへの書き込みで支払われる費用の概算を計算するには、" +"コンテンツサイズを4で割ってから、レートを掛けてください。" + +#: src/guides/inscriptions.md:157 +msgid "" +"Inscription transactions must be less than 400,000 weight units, or they " +"will not be relayed by Bitcoin Core. One byte of inscription content costs " +"one weight unit. Since an inscription transaction includes not just the " +"inscription content, limit inscription content to less than 400,000 weight " +"units. 390,000 weight units should be safe." +msgstr "" +"銘文取引は400,000重量測定単位未満でなければならない。そうでなければ、Bitcoin Coreに中継されない" +"の1バイトの銘文内容には重み測定単位が必要です。銘文取引は銘文の内容だけではないので、" +"銘文の内容は400、000重量計量単位以内に制限されている。390、000の重み測定単位は安全でなければならなりません。" + +#: src/guides/inscriptions.md:163 +msgid "Creating Inscriptions" +msgstr "銘文を作成します。" + +#: src/guides/inscriptions.md:166 +msgid "To create an inscription with the contents of `FILE`, run:" +msgstr "『FILE』の内容で銘文を作成し、実行する必要があります:" + +#: src/guides/inscriptions.md:168 +msgid "" +"```\n" +"ord wallet inscribe --fee-rate FEE_RATE FILE\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:172 +msgid "" +"Ord will output two transactions IDs, one for the commit transaction, and " +"one for the reveal transaction, and the inscription ID. Inscription IDs are " +"of the form `TXIDiN`, where `TXID` is the transaction ID of the reveal " +"transaction, and `N` is the index of the inscription in the reveal " +"transaction." +msgstr "" +"Ordは2つの取引IDが出力されます。1つはcommit取引、もう1つはreveal取引、そして銘文IDです。" +"銘文IDのフォーマットは、'TXIDiN'であり、'TXID'は、取引を開示する取引IDであり、'N'は、取引" +"における銘文を開示するインデックスであ。" + +#: src/guides/inscriptions.md:177 +msgid "" +"The commit transaction commits to a tapscript containing the content of the " +"inscription, and the reveal transaction spends from that tapscript, " +"revealing the content on chain and inscribing it on the first sat of the " +"input that contains the corresponding tapscript." +msgstr "" +"CommitCommitトランザクションは銘文の内容を含むtapscriptに提出され、revealトランザクションはそのtapscriptから費やされます。" +"チェーン上のコンテンツを表示し、revealトランザクションの最初の出力の最初のsatにそれらをマークします。" + +#: src/guides/inscriptions.md:182 +msgid "" +"Wait for the reveal transaction to be mined. You can check the status of the " +"commit and reveal transactions using [the mempool.space block explorer]" +"(https://mempool.space/)." +msgstr "" +"reveal取引が記録されるのを待っている間、あなたは使用することができます[the mempool.space block explorer]" +"(https://mempool.space/)は取引の状態をチェックします。" + +#: src/guides/inscriptions.md:186 +msgid "" +"Once the reveal transaction has been mined, the inscription ID should be " +"printed when you run:" +msgstr "" +"reveal取引が記帳を完了したら、以下のコマンドを使用して銘文IDを照会できます" + + +#: src/guides/inscriptions.md:189 src/guides/inscriptions.md:220 +#: src/guides/inscriptions.md:246 +msgid "" +"```\n" +"ord wallet inscriptions\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:193 +msgid "" +"And when you visit [the ordinals explorer](https://ordinals.com/) at " +"`ordinals.com/inscription/INSCRIPTION_ID`." +msgstr "" +"[the ordinals explorer](https://ordinals.com/)で以下の形式で銘文にアクセスできます`." + +#: src/guides/inscriptions.md:196 +msgid "Sending Inscriptions" +msgstr "銘文を発送します" + +#: src/guides/inscriptions.md:199 +msgid "Ask the recipient to generate a new address by running:" +msgstr "銘文受信者は次のコマンドを使って住所を生成する" + +#: src/guides/inscriptions.md:205 +msgid "Send the inscription by running:" +msgstr "コマンドを使用して銘文を発送します:" + +#: src/guides/inscriptions.md:207 +msgid "" +"```\n" +"ord wallet send --fee-rate
\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:211 src/guides/inscriptions.md:239 +msgid "See the pending transaction with:" +msgstr "できなかった取引状況を検査します:" + +#: src/guides/inscriptions.md:217 +msgid "" +"Once the send transaction confirms, the recipient can confirm receipt by " +"running:" +msgstr "取引が確認されると、受信者は次のコマンドを使用して受信した銘文を見ることができます" + +#: src/guides/inscriptions.md:224 +msgid "Receiving Inscriptions" +msgstr "銘文を受け取ります" + +#: src/guides/inscriptions.md:227 +msgid "Generate a new receive address using:" +msgstr "次のコマンドを使用して新しい受信アドレスを生成する" + +#: src/guides/inscriptions.md:233 +msgid "The sender can transfer the inscription to your address using:" +msgstr "送信者はコマンドを使用してあなたの住所に銘文を送信します" + +#: src/guides/inscriptions.md:235 +msgid "" +"```\n" +"ord wallet send ADDRESS INSCRIPTION_ID\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:244 +msgid "" +"Once the send transaction confirms, you can can confirm receipt by running:" +msgstr "取引が確認されると、受信者は次のコマンドを使用して受信した銘文を見ることができます" + +#: src/guides/sat-hunting.md:4 +msgid "" +"_This guide is out of date. Since it was written, the `ord` binary was " +"changed to only build the full satoshi index when the `--index-sats` flag is " +"supplied. Additionally, `ord` now has a built-in wallet that wraps a Bitcoin " +"Core wallet. See `ord wallet --help`._" +msgstr "" +"_このガイドは時代遅れです。書かれて以来、'ord'インストールファイルが変更されました。" +"「--index-sats」フラグが指定されている場合にのみ、完全なスマートインデックスが作成されます。" +"さらに「ord」には現在、ビットコインのコアウォレットを含むウォレットが内蔵されていて、ord wallet --help`を参照してください。_" + +#: src/guides/sat-hunting.md:9 +msgid "" +"Ordinal hunting is difficult but rewarding. The feeling of owning a wallet " +"full of UTXOs, redolent with the scent of rare and exotic sats, is beyond " +"compare." +msgstr "" + +#: src/guides/sat-hunting.md:12 +msgid "" +"Ordinals are numbers for satoshis. Every satoshi has an ordinal number and " +"every ordinal number has a satoshi." +msgstr "" + +#: src/guides/sat-hunting.md:15 +msgid "Preparation" +msgstr "" + +#: src/guides/sat-hunting.md:18 +msgid "There are a few things you'll need before you start." +msgstr "" + +#: src/guides/sat-hunting.md:20 +msgid "" +"First, you'll need a synced Bitcoin Core node with a transaction index. To " +"turn on transaction indexing, pass `-txindex` on the command-line:" +msgstr "" + +#: src/guides/sat-hunting.md:23 +msgid "" +"```sh\n" +"bitcoind -txindex\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:27 +msgid "" +"Or put the following in your [Bitcoin configuration file](https://github.com/" +"bitcoin/bitcoin/blob/master/doc/bitcoin-conf.md#configuration-file-path):" +msgstr "" + +#: src/guides/sat-hunting.md:34 +msgid "" +"Launch it and wait for it to catch up to the chain tip, at which point the " +"following command should print out the current block height:" +msgstr "" + +#: src/guides/sat-hunting.md:37 +msgid "" +"```sh\n" +"bitcoin-cli getblockcount\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:41 +msgid "Second, you'll need a synced `ord` index." +msgstr "" + +#: src/guides/sat-hunting.md:43 +msgid "Get a copy of `ord` from [the repo](https://github.com/ordinals/ord/)." +msgstr "" + +#: src/guides/sat-hunting.md:45 +msgid "" +"Run `RUST_LOG=info ord index`. It should connect to your bitcoin core node " +"and start indexing." +msgstr "" + +#: src/guides/sat-hunting.md:48 +msgid "Wait for it to finish indexing." +msgstr "" + +#: src/guides/sat-hunting.md:50 +msgid "Third, you'll need a wallet with UTXOs that you want to search." +msgstr "" + +#: src/guides/sat-hunting.md:52 +msgid "Searching for Rare Ordinals" +msgstr "" + +#: src/guides/sat-hunting.md:55 +msgid "Searching for Rare Ordinals in a Bitcoin Core Wallet" +msgstr "" + +#: src/guides/sat-hunting.md:57 +msgid "" +"The `ord wallet` command is just a wrapper around Bitcoin Core's RPC API, so " +"searching for rare ordinals in a Bitcoin Core wallet is Easy. Assuming your " +"wallet is named `foo`:" +msgstr "" + +#: src/guides/sat-hunting.md:61 +msgid "Load your wallet:" +msgstr "" + +#: src/guides/sat-hunting.md:63 +msgid "" +"```sh\n" +"bitcoin-cli loadwallet foo\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:67 +msgid "Display any rare ordinals wallet `foo`'s UTXOs:" +msgstr "" + +#: src/guides/sat-hunting.md:69 src/guides/sat-hunting.md:132 +#: src/guides/sat-hunting.md:233 +msgid "" +"```sh\n" +"ord wallet sats\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:73 +msgid "Searching for Rare Ordinals in a Non-Bitcoin Core Wallet" +msgstr "" + +#: src/guides/sat-hunting.md:75 +msgid "" +"The `ord wallet` command is just a wrapper around Bitcoin Core's RPC API, so " +"to search for rare ordinals in a non-Bitcoin Core wallet, you'll need to " +"import your wallet's descriptors into Bitcoin Core." +msgstr "" + +#: src/guides/sat-hunting.md:79 +msgid "" +"[Descriptors](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors." +"md) describe the ways that wallets generate private keys and public keys." +msgstr "" + +#: src/guides/sat-hunting.md:82 +msgid "" +"You should only import descriptors into Bitcoin Core for your wallet's " +"public keys, not its private keys." +msgstr "" + +#: src/guides/sat-hunting.md:85 +msgid "" +"If your wallet's public key descriptor is compromised, an attacker will be " +"able to see your wallet's addresses, but your funds will be safe." +msgstr "" + +#: src/guides/sat-hunting.md:88 +msgid "" +"If your wallet's private key descriptor is compromised, an attacker can " +"drain your wallet of funds." +msgstr "" + +#: src/guides/sat-hunting.md:91 +msgid "" +"Get the wallet descriptor from the wallet whose UTXOs you want to search for " +"rare ordinals. It will look something like this:" +msgstr "" + +#: src/guides/sat-hunting.md:94 +msgid "" +"```\n" +"wpkh([bf1dd55e/84'/0'/0']xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)#csvefu29\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:98 +msgid "Create a watch-only wallet named `foo-watch-only`:" +msgstr "" + +#: src/guides/sat-hunting.md:100 +msgid "" +"```sh\n" +"bitcoin-cli createwallet foo-watch-only true true\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:104 +msgid "Feel free to give it a better name than `foo-watch-only`!" +msgstr "" + +#: src/guides/sat-hunting.md:106 +msgid "Load the `foo-watch-only` wallet:" +msgstr "" + +#: src/guides/sat-hunting.md:108 src/guides/sat-hunting.md:199 +msgid "" +"```sh\n" +"bitcoin-cli loadwallet foo-watch-only\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:112 +msgid "Import your wallet descriptors into `foo-watch-only`:" +msgstr "" + +#: src/guides/sat-hunting.md:114 +msgid "" +"```sh\n" +"bitcoin-cli importdescriptors \\\n" +" '[{ \"desc\": " +"\"wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)#tpnxnxax\", \"timestamp\":0 }]'\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:119 +msgid "" +"If you know the Unix timestamp when your wallet first started receive " +"transactions, you may use it for the value of `\"timestamp\"` instead of " +"`0`. This will reduce the time it takes for Bitcoin Core to search for your " +"wallet's UTXOs." +msgstr "" + +#: src/guides/sat-hunting.md:124 src/guides/sat-hunting.md:225 +msgid "Check that everything worked:" +msgstr "" + +#: src/guides/sat-hunting.md:126 src/guides/sat-hunting.md:227 +msgid "" +"```sh\n" +"bitcoin-cli getwalletinfo\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:130 src/guides/sat-hunting.md:231 +msgid "Display your wallet's rare ordinals:" +msgstr "" + +#: src/guides/sat-hunting.md:136 +msgid "" +"Searching for Rare Ordinals in a Wallet that Exports Multi-path Descriptors" +msgstr "" + +#: src/guides/sat-hunting.md:138 +msgid "" +"Some descriptors describe multiple paths in one descriptor using angle " +"brackets, e.g., `<0;1>`. Multi-path descriptors are not yet supported by " +"Bitcoin Core, so you'll first need to convert them into multiple " +"descriptors, and then import those multiple descriptors into Bitcoin Core." +msgstr "" + +#: src/guides/sat-hunting.md:143 +msgid "" +"First get the multi-path descriptor from your wallet. It will look something " +"like this:" +msgstr "" + +#: src/guides/sat-hunting.md:146 +msgid "" +"```\n" +"wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/" +"<0;1>/*)#fw76ulgt\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:150 +msgid "Create a descriptor for the receive address path:" +msgstr "" + +#: src/guides/sat-hunting.md:152 +msgid "" +"```\n" +"wpkh([bf1dd55e/84'/0'/0']xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:156 +msgid "And the change address path:" +msgstr "" + +#: src/guides/sat-hunting.md:158 +msgid "" +"```\n" +"wpkh([bf1dd55e/84'/0'/0']xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/1/" +"*)\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:162 +msgid "" +"Get and note the checksum for the receive address descriptor, in this case " +"`tpnxnxax`:" +msgstr "" + +#: src/guides/sat-hunting.md:165 +msgid "" +"```sh\n" +"bitcoin-cli getdescriptorinfo \\\n" +" 'wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)'\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:170 +msgid "" +"```json\n" +"{\n" +" \"descriptor\": " +"\"wpkh([bf1dd55e/84'/0'/0']xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)#csvefu29\",\n" +" \"checksum\": \"tpnxnxax\",\n" +" \"isrange\": true,\n" +" \"issolvable\": true,\n" +" \"hasprivatekeys\": false\n" +"}\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:180 +msgid "And for the change address descriptor, in this case `64k8wnd7`:" +msgstr "" + +#: src/guides/sat-hunting.md:182 +msgid "" +"```sh\n" +"bitcoin-cli getdescriptorinfo \\\n" +" 'wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/1/" +"*)'\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:187 +msgid "" +"```json\n" +"{\n" +" \"descriptor\": " +"\"wpkh([bf1dd55e/84'/0'/0']xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/1/" +"*)#fyfc5f6a\",\n" +" \"checksum\": \"64k8wnd7\",\n" +" \"isrange\": true,\n" +" \"issolvable\": true,\n" +" \"hasprivatekeys\": false\n" +"}\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:197 +msgid "Load the wallet you want to import the descriptors into:" +msgstr "" + +#: src/guides/sat-hunting.md:203 +msgid "" +"Now import the descriptors, with the correct checksums, into Bitcoin Core." +msgstr "" + +#: src/guides/sat-hunting.md:205 +msgid "" +"```sh\n" +"bitcoin-cli \\\n" +" importdescriptors \\\n" +" '[\n" +" {\n" +" \"desc\": " +"\"wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)#tpnxnxax\"\n" +" \"timestamp\":0\n" +" },\n" +" {\n" +" \"desc\": " +"\"wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/1/" +"*)#64k8wnd7\",\n" +" \"timestamp\":0\n" +" }\n" +" ]'\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:220 +msgid "" +"If you know the Unix timestamp when your wallet first started receive " +"transactions, you may use it for the value of the `\"timestamp\"` fields " +"instead of `0`. This will reduce the time it takes for Bitcoin Core to " +"search for your wallet's UTXOs." +msgstr "" + +#: src/guides/sat-hunting.md:237 +msgid "Exporting Descriptors" +msgstr "" + +#: src/guides/sat-hunting.md:241 +msgid "" +"Navigate to the `Settings` tab, then to `Script Policy`, and press the edit " +"button to display the descriptor." +msgstr "" + +#: src/guides/sat-hunting.md:244 +msgid "Transferring Ordinals" +msgstr "" + +#: src/guides/sat-hunting.md:246 +msgid "" +"The `ord` wallet supports transferring specific satoshis. You can also use " +"`bitcoin-cli` commands `createrawtransaction`, " +"`signrawtransactionwithwallet`, and `sendrawtransaction`, how to do so is " +"complex and outside the scope of this guide." +msgstr "" + +#: src/guides/collecting.md:4 +msgid "" +"Currently, [ord](https://github.com/ordinals/ord/) is the only wallet " +"supporting sat-control and sat-selection, which are required to safely store " +"and send rare sats and inscriptions, hereafter ordinals." +msgstr "" +"現在、[ord](https://github.com/ordinals/ord/)はsat-controlとsat-selectionをサポートする唯一のものです" +"の財布、これは希少なsatsと銘文(以下、序数と略称する)を安全に保存して送るために必要です。" + +#: src/guides/collecting.md:8 +msgid "" +"The recommended way to send, receive, and store ordinals is with `ord`, but " +"if you are careful, it is possible to safely store, and in some cases send, " +"ordinals with other wallets." +msgstr "" +"送信、受信、シーケンス番号の格納方法としては、'ord'を用いることが推奨される。しかし、注意すれば安全に保管できます。" +"場合によっては、別のウォレットを使用してシリアル番号を送信します。" + +#: src/guides/collecting.md:12 +msgid "" +"As a general note, receiving ordinals in an unsupported wallet is not " +"dangerous. Ordinals can be sent to any bitcoin address, and are safe as long " +"as the UTXO that contains them is not spent. However, if that wallet is then " +"used to send bitcoin, it may select the UTXO containing the ordinal as an " +"input, and send the inscription or spend it to fees." +msgstr "" +"一般的な説明として、サポートされていないウォレットでシーケンス番号を受信することは危険ではありません。シリアル番号は任意のビットコインアドレスに送信できます。" +"はそれらを含むUTXOが使われていない限り、安全です。しかし、ウォレットがその後ビットコインを送信するために使用された場合、" +"はシリアル番号を含むUTXOを入力として選択し、銘文を送ったり、費用に使用したりすることがあります。。" + +#: src/guides/collecting.md:18 +msgid "" +"A [guide](./collecting/sparrow-wallet.md) to creating an `ord`\\-compatible " +"wallet with [Sparrow Wallet](https://sparrowwallet.com/), is available in " +"this handbook." +msgstr "" +"このマニュアルでは、[Sparrow Wallet](https://sparrowwallet.com/)作成" +"'ord'と互換性のある財布の[ガイド](./collecting/sparrow-wallet.md).。" + +#: src/guides/collecting.md:21 +msgid "" +"Please note that if you follow this guide, you should not use the wallet you " +"create to send BTC, unless you perform manual coin-selection to avoid " +"sending ordinals." +msgstr "" +"このガイドに従う場合は、シリアル番号の送信を避けるために手動コイン選択を実行しない限り、作成したウォレットを使用してBTCを送信しないでください。。" + +#: src/guides/collecting/sparrow-wallet.md:1 +msgid "Collecting Inscriptions and Ordinals with Sparrow Wallet" +msgstr "スズメのSparrow財布を使って銘文をコレクションします。" + +#: src/guides/collecting/sparrow-wallet.md:4 +msgid "" +"Users who cannot or have not yet set up the [ord](https://github.com/" +"ordinals/ord) wallet can receive inscriptions and ordinals with alternative " +"bitcoin wallets, as long as they are _very_ careful about how they spend " +"from that wallet." +msgstr "" +"それらの生きていられないまだ設定されていない[ord](https://github.com/ordinals/ord)" +"ウォレットのユーザーは、ウォレットを使用する際に細心の注意を払っていれば、他のビットコインウォレットを使用して銘文と序数を受け取ることができます。。" + +#: src/guides/collecting/sparrow-wallet.md:6 +msgid "" +"This guide gives some basic steps on how to create a wallet with [Sparrow " +"Wallet](https://sparrowwallet.com/) which is compatible with `ord` and can " +"be later imported into `ord`" +msgstr "このガイドでは、[Sparrow Wallet](https://sparrowwallet.com/)" +"の使用方法を説明します。'ord'と互換性のあるウォレットを作成し、後で'ord'にインポートできます。`" + +#: src/guides/collecting/sparrow-wallet.md:8 +msgid "⚠️⚠️ Warning!! ⚠️⚠️" +msgstr "⚠️⚠️ 警告!! ⚠️⚠️" + +#: src/guides/collecting/sparrow-wallet.md:9 +msgid "" +"As a general rule if you take this approach, you should use this wallet with " +"the Sparrow software as a receive-only wallet." +msgstr "" +"一般的に、この方法を選ぶなら、この財布をお金を受け取る財布として、Sparrowソフトウェアを使うべきです" + +#: src/guides/collecting/sparrow-wallet.md:11 +msgid "" +"Do not spend any satoshis from this wallet unless you are sure you know what " +"you are doing. You could very easily inadvertently lose access to your " +"ordinals and inscriptions if you don't heed this warning." +msgstr "" +"自分が何をしているか分からない限り、この財布からビットコインを使わないでください。この警告に注意しなければ、" +"うっかり序数や銘文へのアクセスを失いやすいかもしれません" + +#: src/guides/collecting/sparrow-wallet.md:13 +msgid "Wallet Setup & Receiving" +msgstr "ウォレットの設置と取り受け" + +#: src/guides/collecting/sparrow-wallet.md:15 +msgid "" +"Download the Sparrow Wallet from the [releases page](https://sparrowwallet." +"com/download/) for your particular operating system." +msgstr "" +"オペレーティングシステムに応じて[リリースページ]から(https://sparrowwallet.com/download/)ダウンロードSparrowウォレット。" + +#: src/guides/collecting/sparrow-wallet.md:17 +msgid "Select `File -> New Wallet` and create a new wallet called `ord`." +msgstr "" +"『File->New Wallet』を選択し、『ord』という名前の新しいウォレットを作成します。" + +#: src/guides/collecting/sparrow-wallet.md:19 +msgid "![](images/wallet_setup_01.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:21 +msgid "" +"Change the `Script Type` to `Taproot (P2TR)` and select the `New or Imported " +"Software Wallet` option." +msgstr "" +"'Script Type'を'Taproot(P 2 TR)'に変更します。そして、New or Imported Software Wallet'オプションを選択します。" + +#: src/guides/collecting/sparrow-wallet.md:23 +msgid "![](images/wallet_setup_02.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:25 +msgid "" +"Select `Use 12 Words` and then click `Generate New`. Leave the passphrase " +"blank." +msgstr "" +"『Use 12 Words』を選択し、『Generate New』をクリックします。パスフレーズは空白のままにします。。" + +#: src/guides/collecting/sparrow-wallet.md:27 +msgid "![](images/wallet_setup_03.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:29 +msgid "" +"A new 12 word BIP39 seed phrase will be generated for you. Write this down " +"somewhere safe as this is your backup to get access to your wallet. NEVER " +"share or show this seed phrase to anyone else." +msgstr "" +"あなたのために新しい12語BIP 39シードフレーズが生成されます。このフレーズを安全な場所に書いてください。" +"これはウォレットへのアクセス権を取得するためのバックアップです。このシードフレーズを他の人と共有したり表示したりしないでください" + +#: src/guides/collecting/sparrow-wallet.md:31 +msgid "Once you have written down the seed phrase click `Confirm Backup`." +msgstr "シードフレーズを書いたら、`Confirm Backup`をクリックしてください' `Confirm Backup`." + +#: src/guides/collecting/sparrow-wallet.md:33 +msgid "![](images/wallet_setup_04.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:35 +msgid "" +"Re-enter the seed phrase which you wrote down, and then click `Create " +"Keystore`." +msgstr "" +"メモしたシードフレーズを再入力して、'Create Key storeをクリックしてください。`." + +#: src/guides/collecting/sparrow-wallet.md:37 +msgid "![](images/wallet_setup_05.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:39 +msgid "Click `Import Keystore`." +msgstr " `Import Keystoreをクリックします`." + + +#: src/guides/collecting/sparrow-wallet.md:41 +msgid "![](images/wallet_setup_06.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:43 +msgid "Click `Apply`. Add a password for the wallet if you want to." +msgstr "『Apply』をクリックします。もしあなたが望むなら、財布にパスワードを追加してもいいです。。" + +#: src/guides/collecting/sparrow-wallet.md:45 +msgid "![](images/wallet_setup_07.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:47 +msgid "" +"You now have a wallet which is compatible with `ord`, and can be imported " +"into `ord` using the BIP39 Seed Phrase. To receive ordinals or inscriptions, " +"click on the `Receive` tab and copy a new address." +msgstr "" +"今、BIP 39シードフレーズを使って'ord'にインポートできる'ord'互換のウォレットを持っています。序数や銘文を受け取るには、" +"'Receive'タブをクリックし、新しいアドレスをコピーします" + +#: src/guides/collecting/sparrow-wallet.md:49 +msgid "" +"Each time you want to receive you should use a brand-new address, and not re-" +"use existing addresses." +msgstr "受信するたびに、既存のアドレスを再利用するのではなく、新しいアドレスを使用する必要があります。" + +#: src/guides/collecting/sparrow-wallet.md:51 +msgid "" +"Note that bitcoin is different to some other blockchain wallets, in that " +"this wallet can generate an unlimited number of new addresses. You can " +"generate a new address by clicking on the `Get Next Address` button. You can " +"see all of your addresses in the `Addresses` tab of the app." +msgstr "" +"ビットコインは他のいくつかのブロックチェーンウォレットとは異なり、無限の数の新しいアドレスを生成できることに注意してください。" +"は次の住所を取得ボタンをクリックすることで新しい住所を生成できます。あなたはアプリケーションの'Addresses'タブですべてのアドレスを見ることができます" + +#: src/guides/collecting/sparrow-wallet.md:53 +msgid "" +"You can add a label to each address, so you can keep track of what it was " +"used for." +msgstr "各アドレスにタグを付けることができますので、目的を追跡することができます。" + +#: src/guides/collecting/sparrow-wallet.md:55 +msgid "![](images/wallet_setup_08.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:57 +msgid "Validating / Viewing Received Inscriptions" +msgstr "査証/受け取った銘文を見ます" + +#: src/guides/collecting/sparrow-wallet.md:59 +msgid "" +"Once you have received an inscription you will see a new transaction in the " +"`Transactions` tab of Sparrow, as well as a new UTXO in the `UTXOs` tab." +msgstr "" +"銘文を受け取ったら、Sparrowの『Transactions』タブに新しい取引が表示されます。" +"'UTXOs'タブに新しいUTXOが表示されます。" + +#: src/guides/collecting/sparrow-wallet.md:61 +msgid "" +"Initially this transaction may have an \"Unconfirmed\" status, and you will " +"need to wait for it to be mined into a bitcoin block before it is fully " +"received." +msgstr "" +"最初は、この取引には\"未確認\"の状態があるかもしれません。実際に受け取ったのはビットコインブロックに採掘されるのを待つ必要があります。" + +#: src/guides/collecting/sparrow-wallet.md:63 +msgid "![](images/validating_viewing_01.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:65 +msgid "" +"To track the status of your transaction you can right-click on it, select " +"`Copy Transaction ID` and then paste that transaction id into [mempool.space]" +"(https://mempool.space)." +msgstr "" +"取引状況を追跡するには、右クリックして'Copy Transaction ID'を選択することができます," +"そして、この取引idを[mempool.space](https://mempool.space)に貼り付けます。" + +#: src/guides/collecting/sparrow-wallet.md:67 +msgid "![](images/validating_viewing_02.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:69 +msgid "" +"Once the transaction has confirmed, you can validate and view your " +"inscription by heading over to the `UTXOs` tab, finding the UTXO you want to " +"check, right-clicking on the `Output` and selecting `Copy Transaction " +"Output`. This transaction output id can then be pasted into the [ordinals." +"com](https://ordinals.com) search." +msgstr "" +"取引が確認されたら、`UTXOs`タブに行くことによって、チェックしたい`UTXO`を見つけることができます,右クリック`Output`" +"'Copy Transaction Out put'を選択して、あなたの銘文を確認し、確認します。そして、この取引はidを輸出します" +"は[ordinals.com](https://ordinals.com)検索)に貼り付けることができます。。" + +#: src/guides/collecting/sparrow-wallet.md:72 +msgid "Freezing UTXO's" +msgstr " UTXOを凍結します" + +#: src/guides/collecting/sparrow-wallet.md:73 +msgid "" +"As explained above, each of your inscriptions is stored in an Unspent " +"Transaction Output (UTXO). You want to be very careful not to accidentally " +"spend your inscriptions, and one way to make it harder for this to happen is " +"to freeze the UTXO." +msgstr "" +"上記のように、あなたのすべての銘文は未費用の取引出力(UTXO)に保存されています。あなたの銘文を誤って使わないように細心の注意を払う必要があります」" +"がUTXOを凍結することは、このような状況を発生させる難易度を高める一つの方法であります。" + +#: src/guides/collecting/sparrow-wallet.md:75 +msgid "" +"To do this, go to the `UTXOs` tab, find the UTXO you want to freeze, right-" +"click on the `Output` and select `Freeze UTXO`." +msgstr "" +"これを行うには、UTXOsタブに行き、フリーズしたい'UTXOs'を見つけ、'Out put'をクリックして'Freeze UTXO'`を選択します。" + +#: src/guides/collecting/sparrow-wallet.md:77 +msgid "" +"This UTXO (Inscription) is now un-spendable within the Sparrow Wallet until " +"you unfreeze it." +msgstr "" +"このUTXO(銘文)は現在Sparrowウォレットでは、解凍するまで消費できません。。" + +#: src/guides/collecting/sparrow-wallet.md:79 +msgid "Importing into `ord` wallet" +msgstr " `ord` ウォレットを導入します。" + +#: src/guides/collecting/sparrow-wallet.md:81 +msgid "" +"For details on setting up Bitcoin Core and the `ord` wallet check out the " +"[Inscriptions Guide](../inscriptions.md)" +msgstr "" +"ビットコインコアと'ord'ウォレットの設定の詳細については、[銘文ガイド](../inscriptions.md)をご覧ください。" + +#: src/guides/collecting/sparrow-wallet.md:83 +msgid "" +"When setting up `ord`, instead of running `ord wallet create` to create a " +"brand-new wallet, you can import your existing wallet using `ord wallet " +"restore \"BIP39 SEED PHRASE\"` using the seed phrase you generated with " +"Sparrow Wallet." +msgstr "" +"'ord'を設定するときは、'ord wallet restore\"BIP 39 SE ED PHRASE\"'コマンドと" +"Sparrow Walletで生成されたシードフレーズを使用して、'ord wallet create'を実行する代わりに、既存のウォレットをインポートします。" +"は新しい財布を作ります。" + +#: src/guides/collecting/sparrow-wallet.md:85 +msgid "" +"There is currently a [bug](https://github.com/ordinals/ord/issues/1589) " +"which causes an imported wallet to not be automatically rescanned against " +"the blockchain. To work around this you will need to manually trigger a " +"rescan using the bitcoin core cli: `bitcoin-cli -rpcwallet=ord " +"rescanblockchain 767430`" +msgstr "" +"現在、[プログラムエラー]が存在します(https://github.com/ordinals/ord/issues/1589)インポートの原因" +"のウォレットはブロックチェーンを自動的に再スキャンできません。この問題を解決するには、手動で再スキャンをトリガーする必要があります。" +"Bitcoinコアコマンドラインインターフェイスを使います:" + +#: src/guides/collecting/sparrow-wallet.md:88 +msgid "" +"You can then check your wallet's inscriptions using `ord wallet inscriptions`" +msgstr "そして、'ord wallet inscriptions'を使用して、財布の碑文を確認することができます。." + +#: src/guides/collecting/sparrow-wallet.md:90 +msgid "" +"Note that if you have previously created a wallet with `ord`, then you will " +"already have a wallet with the default name, and will need to give your " +"imported wallet a different name. You can use the `--wallet` parameter in " +"all `ord` commands to reference a different wallet, eg:" +msgstr "" +"前にウォレットを'ord'で作成したことがある場合は、デフォルトの名前のウォレットを既に持っていることに注意してください。" +"はあなたが導入した財布に違う名前を付ける必要があります。すべての'ord'コマンドで'--wallet'引数を使用できます" +"異なる財布を引用するために、例えば:" + +#: src/guides/collecting/sparrow-wallet.md:92 +msgid "`ord --wallet ord_from_sparrow wallet restore \"BIP39 SEED PHRASE\"`" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:94 +msgid "`ord --wallet ord_from_sparrow wallet inscriptions`" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:96 +msgid "`bitcoin-cli -rpcwallet=ord_from_sparrow rescanblockchain 767430`" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:98 +msgid "Sending inscriptions with Sparrow Wallet" +msgstr "雀の財布を使って銘文を発送します。" + +#: src/guides/collecting/sparrow-wallet.md:100 +msgid "⚠️⚠️ Warning ⚠️⚠️" +msgstr "⚠️⚠️ 警告 ⚠️⚠️" + +#: src/guides/collecting/sparrow-wallet.md:101 +msgid "" +"While it is highly recommended that you set up a bitcoin core node and run " +"the `ord` software, there are certain limited ways you can send inscriptions " +"out of Sparrow Wallet in a safe way. Please note that this is not " +"recommended, and you should only do this if you fully understand what you " +"are doing." +msgstr "" +"ビットコインコアノードを設定し、'ord'ソフトウェアを実行することを強くお勧めしますが、いくつかの安全な方法で" +"Sparrowウォレットに銘文をお送りします。これはお勧めではないことに注意してください。あなたが何をしているのか完全に理解している場合にのみ、そうすることができます。" + +#: src/guides/collecting/sparrow-wallet.md:103 +msgid "" +"Using the `ord` software will remove much of the complexity we are " +"describing here, as it is able to automatically and safely handle sending " +"inscriptions in an easy way." +msgstr "" +"『ord』ソフトウェアを使用すると、ここで説明した複雑さが大幅に簡素化されます。それは、簡単な方法で自動的かつ安全に碑文の送信を処理できるからです。。"" + +#: src/guides/collecting/sparrow-wallet.md:105 +msgid "⚠️⚠️ Additional Warning ⚠️⚠️" +msgstr "⚠️⚠️ 特別警告 ⚠️⚠️" + +#: src/guides/collecting/sparrow-wallet.md:106 +msgid "" +"Don't use your sparrow inscriptions wallet to do general sends of non-" +"inscription bitcoin. You can setup a separate wallet in sparrow if you need " +"to do normal bitcoin transactions, and keep your inscriptions wallet " +"separate." +msgstr "" +"sparrowスズメの銘文財布を使って非銘文ビットコインを送らないでください。通常のビットコイン取引が必要な場合は、" +"はスズメの中に別の財布を設置して、銘文財布を独立させることができます。" + +#: src/guides/collecting/sparrow-wallet.md:108 +msgid "Bitcoin's UTXO model" +msgstr "ビットコインのUTXO模型" + +#: src/guides/collecting/sparrow-wallet.md:109 +msgid "" +"Before sending any transaction it's important that you have a good mental " +"model for bitcoin's Unspent Transaction Output (UTXO) system. The way " +"Bitcoin works is fundamentally different to many other blockchains such as " +"Ethereum. In Ethereum generally you have a single address in which you store " +"ETH, and you cannot differentiate between any of the ETH - it is just all a " +"single value of the total amount in that address. Bitcoin works very " +"differently in that we generate a new address in the wallet for each " +"receive, and every time you receive sats to an address in your wallet you " +"are creating a new UTXO. Each UTXO can be seen and managed individually. You " +"can select specific UTXO's which you want to spend, and you can choose not " +"to spend certain UTXO's." +msgstr "" +"取引を送信する前に、ビットコインの未消費取引出力(UTXO)システムをよく理解しなければなりません。" +"ビットコインの仕組みはイーサリアムなど他の多くのブロックチェーンと根本的に異なっている。イーサリアムでは、通常、ETHを保存する単一のアドレスを持っています。" +"これらのETHのいずれかを区別することはできません。それらはその住所の合計金額の単一の値にすぎません。" +"ビットコインの仕組みは全く異なります。私たちは受信ごとに新しいアドレスを生成します。ウォレットのアドレスの1つにsatsを受信するたびに" +"あなたは新しいUTXOを作っています。各UTXOは個別に表示および管理できます。" +"特定のUTXOを使用するか、または特定のUTXOを使用しないかを選択できます。" + +#: src/guides/collecting/sparrow-wallet.md:111 +msgid "" +"Some Bitcoin wallets do not expose this level of detail, and they just show " +"you a single summed up value of all the bitcoin in your wallet. However, " +"when sending inscriptions it is important that you use a wallet like Sparrow " +"which allows for UTXO control." +msgstr "" +"ビットコインウォレットの中には、このレベルの詳細情報を表示しないものもあります。ウォレット内のすべてのビットコインの単一の合計値しか表示しません。" +"しかし、銘文を送るときは、スズメのようなUTXO制御を許す財布を使うことが非常に重要であります。" + +#: src/guides/collecting/sparrow-wallet.md:113 +msgid "Inspecting your inscription before sending" +msgstr "在发送之前检查你的铭文" + +#: src/guides/collecting/sparrow-wallet.md:114 +msgid "" +"Like we have previously described inscriptions are inscribed onto sats, and " +"sats are stored within UTXOs. UTXO's are a collection of satoshis with some " +"particular value of the number of satoshis (the output value). Usually (but " +"not always) the inscription will be inscribed on the first satoshi in the " +"UTXO." +msgstr "" +"的第一个satoshi上前にも述べたように、銘文はは聡に刻まれ、satsはUTXOに格納されています。" +"UTXOは、ある特定の数のsatoshi(出力値)を持つsatoshiの集合です。銘文はUTXOの最初の聡に刻まれることが多いが、いつもそうではないけど」。" + +#: src/guides/collecting/sparrow-wallet.md:116 +msgid "" +"When inspecting your inscription before sending the main thing you will want " +"to check is which satoshi in the UTXO your inscription is inscribed on." +msgstr "" +"発送前にあなたの銘文をチェックするとき、主にチェックしなければならないのはあなたの銘文がUTXOのどのsatoshiに刻まれているかです。" + +#: src/guides/collecting/sparrow-wallet.md:118 +msgid "" +"To do this, you can follow the [Validating / Viewing Received Inscriptions]" +"(./sparrow-wallet.md#validating--viewing-received-inscriptions) described " +"above to find the inscription page for your inscription on ordinals.com" +msgstr "" +"そのためには、上記のように[受け取った銘文を検証/見る]することができます(./sparrow-wallet.md#validating--viewing-received-inscriptions)" +"ordinals.comのあなたの銘文の銘文ページを見つけるために来ます。" + +#: src/guides/collecting/sparrow-wallet.md:120 +msgid "" +"There you will find some metadata about your inscription which looks like " +"the following:" +msgstr "そこで、あなたの銘文に関するメタデータを見つけます。以下のようになります:" + +#: src/guides/collecting/sparrow-wallet.md:122 +msgid "![](images/sending_01.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:124 +msgid "There is a few of important things to check here:" +msgstr "以下は、チェックすべき重要事項です:" + +#: src/guides/collecting/sparrow-wallet.md:125 +msgid "" +"The `output` identifier matches the identifier of the UTXO you are going to " +"send" +msgstr "`output` 識別子が送信しようとしているUTXOの識別子と一致します" + +#: src/guides/collecting/sparrow-wallet.md:126 +msgid "" +"The `offset` of the inscription is `0` (this means that the inscription is " +"located on the first sat in the UTXO)" +msgstr "銘文の'off set'は'0'であり、(これは銘文がUTXOの最初のsatにあることを意味する)" + +#: src/guides/collecting/sparrow-wallet.md:127 +msgid "" +"the `output_value` has enough sats to cover the transaction fee (postage) " +"for sending the transaction. The exact amount you will need depends on the " +"fee rate you will select for the transaction" +msgstr "" +"`output_value` 取引を送るための取引料金(郵便料金)を支払うのに十分なsatsがあります。必要な正確な金額は" +"あなたが取引に選択したレート" + +#: src/guides/collecting/sparrow-wallet.md:129 +msgid "" +"If all of the above are true for your inscription, it should be safe for you " +"to send it using the method below." +msgstr "" +"上記の内容がすべてあなたの碑文に正しい場合、あなたは安全に以下の方法でそれを送ることができるはずです。" + +#: src/guides/collecting/sparrow-wallet.md:131 +msgid "" +"⚠️⚠️ Be very careful sending your inscription particularly if the `offset` " +"value is not `0`. It is not recommended to use this method if that is the " +"case, as doing so you could accidentally send your inscription to a bitcoin " +"miner unless you know what you are doing." +msgstr "" +"⚠️⚠️ 銘文を送るときは、特に'off set'値が'0'でない場合は細心の注意を払ってください。この場合は、" +"この方法をお勧めしません。そうしないと、自分が何をしているのか分からない限り、あなたの銘文をビットコイン鉱山労働者に送ることになるかもしれません。" + +#: src/guides/collecting/sparrow-wallet.md:133 +msgid "Sending your inscription" +msgstr "あなたの銘文を発送します。" + +#: src/guides/collecting/sparrow-wallet.md:134 +msgid "" +"To send an inscription navigate to the `UTXOs` tab, and find the UTXO which " +"you previously validated contains your inscription." +msgstr "" +"要銘文を送信するには、'UTXOs'タブに移動し、以前にあなたの彫刻が含まれていることを確認したUTXOを見つけてください。" + +#: src/guides/collecting/sparrow-wallet.md:136 +msgid "" +"If you previously froze the UXTO you will need to right-click on it and " +"unfreeze it." +msgstr "" +"以前にUXTOを凍結した場合、右クリックして解凍する必要があります。" + +#: src/guides/collecting/sparrow-wallet.md:138 +msgid "" +"Select the UTXO you want to send, and ensure that is the _only_ UTXO is " +"selected. You should see `UTXOs 1/1` in the interface. Once you are sure " +"this is the case you can hit `Send Selected`." +msgstr "" +"送信するUTXOを選択します。これが唯一選択されたUTXOであることを確認します。インターフェイスでは、'UTXOs 1/1'が表示されるはずです。" +"これを確認した後、'Send Selected'をクリックすることができます。" + +#: src/guides/collecting/sparrow-wallet.md:140 +msgid "![](images/sending_02.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:142 +msgid "" +"You will then be presented with the transaction construction interface. " +"There is a few things you need to check here to make sure that this is a " +"safe send:" +msgstr "" +"次に、トランザクション構築インターフェイスが表示されます。ここでは、これが安全な送信であることを確認するためにいくつかのことを確認する必要があります:" + +#: src/guides/collecting/sparrow-wallet.md:144 +msgid "" +"The transaction should have only 1 input, and this should be the UTXO with " +"the label you want to send" +msgstr "" +"取引には1つの入力しかないはずです。これはラベル付きのUTXOを送りたいはずです" + +#: src/guides/collecting/sparrow-wallet.md:145 +msgid "" +"The transaction should have only 1 output, which is the address/label where " +"you want to send the inscription" +msgstr "" +"取引には1つの出力しかないはずです。これは銘文を送りたい住所/ラベルです" + +#: src/guides/collecting/sparrow-wallet.md:147 +msgid "" +"If your transaction looks any different, for example you have multiple " +"inputs, or multiple outputs then this may not be a safe transfer of your " +"inscription, and you should abandon sending until you understand more, or " +"can import into the `ord` wallet." +msgstr "" +"取引がこれとは異なるように見える場合、例えば複数の入力や複数の出力がある場合、これは安全な碑文の転送方法ではないかもしれません。" +"あなたがよりよく知っているか、'ord'ウォレットにインポートすることができるまで、送信を断念する必要があります。" + +#: src/guides/collecting/sparrow-wallet.md:149 +msgid "" +"You should set an appropriate transaction fee, Sparrow will usually " +"recommend a reasonable one, but you can also check [mempool.space](https://" +"mempool.space) to see what the recommended fee rate is for sending a " +"transaction." +msgstr "" +"適切な取引手数料を設定する必要があります。Sparrowは通常、合理的な料金をお勧めします。" +"しかし、[mempool.space]を見て、(https://mempool.space)送信トランザクションの推奨レートを見ます。" + +#: src/guides/collecting/sparrow-wallet.md:151 +msgid "" +"You should add a label for the recipient address, a label like `alice " +"address for inscription #123` would be ideal." +msgstr "" +"受信者の住所にラベルを追加する必要があります。『alice address for inscription#123』は理想的です。" + +#: src/guides/collecting/sparrow-wallet.md:153 +msgid "" +"Once you have checked the transaction is a safe transaction using the checks " +"above, and you are confident to send it you can click `Create Transaction`." +msgstr "" +"上記のチェックを使用して、取引が安全な取引であることを確認し、それを送信する自信があることを確認したら、『Create Transaction』をクリックしてください。" + +#: src/guides/collecting/sparrow-wallet.md:155 +msgid "![](images/sending_03.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:157 +msgid "" +"Here again you can double check that your transaction looks safe, and once " +"you are confident you can click `Finalize Transaction for Signing`." +msgstr "" +"ここで、あなたの取引が安全かどうかを再確認できます。確認した後、『Finalize Transaction for Signing'をクリックしてください。" + +#: src/guides/collecting/sparrow-wallet.md:159 +msgid "![](images/sending_04.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:161 +msgid "Here you can triple check everything before hitting `Sign`." +msgstr "ここでは、『Sign』をクリックする前にすべてを再確認できます。" + +#: src/guides/collecting/sparrow-wallet.md:163 +msgid "![](images/sending_05.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:165 +msgid "" +"And then actually you get very very last chance to check everything before " +"hitting `Broadcast Transaction`. Once you broadcast the transaction it is " +"sent to the bitcoin network, and starts being propagated into the mempool." +msgstr "" +"そして、実際には『Broadcast Transaction』をクリックする前に、すべてをチェックする最後の機会があります。" +"は取引を放送すると、ビットコインネットワークに送られ、mempoolで広がり始めます。" + +#: src/guides/collecting/sparrow-wallet.md:167 +msgid "![](images/sending_06.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:169 +msgid "" +"If you want to track the status of your transaction you can copy the " +"`Transaction Id (Txid)` and paste that into [mempool.space](https://mempool." +"space)" +msgstr "" +"取引状態を追跡したいなら、『Transaction Id(Txid)をコピーして" +"[mempool.space](https://mempool.space)'に貼り付けます。" + + +#: src/guides/collecting/sparrow-wallet.md:171 +msgid "" +"Once the transaction has confirmed you can check the inscription page on " +"[ordinals.com](https://ordinals.com) to validate that it has moved to the " +"new output location and address." +msgstr "" +"取引が確認されたら、[ordinals.com](https://ordinals.com)" +"の銘文ページで、新しい出力場所と住所に移動したことを確認します。" + +#: src/guides/collecting/sparrow-wallet.md:173 +msgid "Troubleshooting" +msgstr "故障排除" + +#: src/guides/collecting/sparrow-wallet.md:175 +msgid "" +"Sparrow wallet is not showing a transaction/UTXO, but I can see it on " +"mempool.space!" +msgstr "Sparrowウォレットは取引/UTXOを表示していませんが、mempool.spaceでを見ました" + +#: src/guides/collecting/sparrow-wallet.md:177 +msgid "" +"Make sure that your wallet is connected to a bitcoin node. To validate this, " +"head into the `Preferences`\\-> `Server` settings, and click `Edit Existing " +"Connection`." +msgstr "" +"ウォレットがビットコインノードに接続されていることを確認してください。これを確認するには、'Preferences'\\-->'Server'の設定に移動します。" +"そして、'Edit Existing Connection'をクリックしてください。。" + +#: src/guides/collecting/sparrow-wallet.md:179 +msgid "![](images/troubleshooting_01.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:181 +msgid "" +"From there you can select a node and click `Test Connection` to validate " +"that Sparrow is able to connect successfully." +msgstr "そこからノードを選択し、'Test Connection'をクリックしてSparrowが正常に接続できることを確認できます。" + +#: src/guides/collecting/sparrow-wallet.md:183 +msgid "![](images/troubleshooting_02.png)" +msgstr "" + +#: src/guides/testing.md:4 +msgid "" +"Ord can be tested using the following flags to specify the test network. For " +"more information on running Bitcoin Core for testing, see [Bitcoin's " +"developer documentation](https://developer.bitcoin.org/examples/testing." +"html)." +msgstr "" +"次のフラグを使用してテストネットワークを指定すると、フォームをテストできます。テストのためのビットコインコアの実行の詳細については、" +"[ビットコインの開発者ドキュメント]を参照してください。" + +#: src/guides/testing.md:7 +msgid "" +"Most `ord` commands in [inscriptions](inscriptions.md) and [explorer]" +"(explorer.md) can be run with the following network flags:" +msgstr "" +"[銘文](inscriptions.md)および[ブラウザ](explorer.md)内のほとんどの'ord'コマンドは、次のネットワークフラグを使用して実行できます:" + +#: src/guides/testing.md:10 +msgid "Network" +msgstr "" + +#: src/guides/testing.md:10 +msgid "Flag" +msgstr "" + +#: src/guides/testing.md:12 +msgid "Testnet" +msgstr "" + +#: src/guides/testing.md:12 +msgid "`--testnet` or `-t`" +msgstr "" + +#: src/guides/testing.md:13 +msgid "Signet" +msgstr "" + +#: src/guides/testing.md:13 +msgid "`--signet` or `-s`" +msgstr "" + +#: src/guides/testing.md:14 +msgid "Regtest" +msgstr "" + +#: src/guides/testing.md:14 +msgid "`--regtest` or `-r`" +msgstr "" + +#: src/guides/testing.md:16 +msgid "Regtest doesn't require downloading the blockchain or indexing ord." +msgstr "Regtestはブロックチェーンをダウンロードしたり、ordインデックスを作成したりする必要はありません" + +#: src/guides/testing.md:18 src/guides/reindexing.md:15 +msgid "Example" +msgstr "サンプル" + +#: src/guides/testing.md:21 +msgid "Run bitcoind in regtest with:" +msgstr "regtestの中でbitcoindを運行し、使います:" + +#: src/guides/testing.md:22 +msgid "" +"```\n" +"bitcoind -regtest -txindex\n" +"```" +msgstr "" + +#: src/guides/testing.md:25 +msgid "Create a wallet in regtest with:" +msgstr "regtestの中でウォレットを作り上げます。" + +#: src/guides/testing.md:26 +msgid "" +"```\n" +"ord -r wallet create\n" +"```" +msgstr "" + +#: src/guides/testing.md:29 +msgid "Get a regtest receive address with:" +msgstr "regtest受け取りアドレスを作成します" + +#: src/guides/testing.md:30 +msgid "" +"```\n" +"ord -r wallet receive\n" +"```" +msgstr "" + +#: src/guides/testing.md:33 +msgid "Mine 101 blocks (to unlock the coinbase) with:" +msgstr "101個のブロックを掘る(ロック解除coinbase)に使います:" + +#: src/guides/testing.md:34 +msgid "" +"```\n" +"bitcoin-cli generatetoaddress 101 \n" +"```" +msgstr "" + +#: src/guides/testing.md:37 +msgid "Inscribe in regtest with:" +msgstr "regtest上で刻みます。" + +#: src/guides/testing.md:38 +msgid "" +"```\n" +"ord -r wallet inscribe --fee-rate 1 \n" +"```" +msgstr "" + +#: src/guides/testing.md:41 +msgid "Mine the inscription with:" +msgstr "銘文を発掘します。" + +#: src/guides/testing.md:42 +msgid "" +"```\n" +"bitcoin-cli generatetoaddress 1 \n" +"```" +msgstr "" + +#: src/guides/testing.md:45 +msgid "View the inscription in the regtest explorer:" +msgstr "regtestブラウザで銘文を見ます。" + +#: src/guides/testing.md:46 +msgid "" +"```\n" +"ord -r server\n" +"```" +msgstr "" + +#: src/guides/testing.md:50 +msgid "Testing Recursion" +msgstr "再帰のテスト" + +#: src/guides/testing.md:53 +msgid "" +"When testing out [recursion](../inscriptions/recursion.md), inscribe the " +"dependencies first (example with [p5.js](https://p5js.org):" +msgstr "" +" [recursion](../inscriptions/recursion.md) のテスト[の場合、最初に依存関係をメモします。" +"( [p5.js](https://p5js.org) を例とします:" + +#: src/guides/testing.md:55 +msgid "" +"```\n" +"ord -r wallet inscribe --fee-rate 1 p5.js\n" +"```" +msgstr "" + +#: src/guides/testing.md:58 +msgid "" +"This should return a `inscription_id` which you can then reference in your " +"recursive inscription." +msgstr "" +"これは'inscription_id'を返す必要があります。その後、再帰的な銘文でそれを参照することができます。。" + +#: src/guides/testing.md:61 +msgid "" +"ATTENTION: These ids will be different when inscribing on mainnet or signet, " +"so be sure to change those in your recursive inscription for each chain." +msgstr "" +"これは'inscription_id'を返す必要があります。その後、再帰的な銘文でそれを参照することができます。" + +#: src/guides/testing.md:65 +msgid "Then you can inscribe your recursive inscription with:" +msgstr "次のコマンドを使用して、再帰的な碑文を刻むことができます。:" + +#: src/guides/testing.md:66 +msgid "" +"```\n" +"ord -r wallet inscribe --fee-rate 1 recursive-inscription.html\n" +"```" +msgstr "" + +#: src/guides/testing.md:69 +msgid "Finally you will have to mine some blocks and start the server:" +msgstr "最終的には、サーバーを開始するためにいくつかのブロックを掘ることができます:" + +#: src/guides/testing.md:70 +msgid "" +"```\n" +"bitcoin-cli generatetoaddress 6 \n" +"ord -r server\n" +"```" +msgstr "" + +#: src/guides/moderation.md:4 +msgid "" +"`ord` includes a block explorer, which you can run locally with `ord server`." +msgstr "" +"`ord` ブロックブラウザが含まれています,あなたはローカルで'ord server`運行することができます." + +#: src/guides/moderation.md:6 +msgid "" +"The block explorer allows viewing inscriptions. Inscriptions are user-" +"generated content, which may be objectionable or unlawful." +msgstr "" +"ブロックブラウザでは、銘文を見ることができます。銘文はユーザーが生成した内容であるため、不快または違法である可能性があります。" + +#: src/guides/moderation.md:9 +msgid "" +"It is the responsibility of each individual who runs an ordinal block " +"explorer instance to understand their responsibilities with respect to " +"unlawful content, and decide what moderation policy is appropriate for their " +"instance." +msgstr "" +"Wordブロックブラウザのインスタンスを実行するすべてのユーザーは、不正なコンテンツに対する責任を理解し、そのインスタンスに適した監査ポリシーを決定する責任があります。" + +#: src/guides/moderation.md:13 +msgid "" +"In order to prevent particular inscriptions from being displayed on an `ord` " +"instance, they can be included in a YAML config file, which is loaded with " +"the `--config` option." +msgstr "" +"特定の銘文が'ord'インスタンスに表示されないようにするには、YAML設定ファイルに含めることができます。" +'--config'オプションを使用してファイルをロードします。" + +#: src/guides/moderation.md:17 +msgid "" +"To hide inscriptions, first create a config file, with the inscription ID " +"you want to hide:" +msgstr "" +"銘文を隠れると、先ずプロファイルを作成しますその中は隠れる銘文IDが含まれます。" + +#: src/guides/moderation.md:20 +msgid "" +"```yaml\n" +"hidden:\n" +"- 0000000000000000000000000000000000000000000000000000000000000000i0\n" +"```" +msgstr "" + +#: src/guides/moderation.md:25 +msgid "" +"The suggested name for `ord` config files is `ord.yaml`, but any filename " +"can be used." +msgstr "" +"'ord'設定ファイルの推奨名は'ord.yaml'です。ただし、任意のファイル名を使用できます。" + +#: src/guides/moderation.md:28 +msgid "Then pass the file to `--config` when starting the server:" +msgstr "" +"その後、サービスの開始時にファイルを使います--config` :" + +#: src/guides/moderation.md:30 +msgid "`ord --config ord.yaml server`" +msgstr "" + +#: src/guides/moderation.md:32 +msgid "" +"Note that the `--config` option comes after `ord` but before the `server` " +"subcommand." +msgstr "" +"注意してください。 『--config'オプションは'ord'の後で'server'サブコマンドの前にあります。" + +#: src/guides/moderation.md:35 +msgid "`ord` must be restarted in to load changes to the config file." +msgstr "" +"'ord'は、設定ファイルの変更をロードするために再起動する必要があります。" + +#: src/guides/moderation.md:37 +msgid "`ordinals.com`" +msgstr "" + +#: src/guides/moderation.md:40 +msgid "" +"The `ordinals.com` instances use `systemd` to run the `ord server` service, " +"which is called `ord`, with a config file located at `/var/lib/ord/ord.yaml`." +msgstr "" +"ordinals.com'インスタンスは'systemd'を使用して'ord'という名前の'ord server'サービスを実行しています。" +"設定ファイルは『/var/lib/ord/ord.yaml'." + +#: src/guides/moderation.md:43 +msgid "To hide an inscription on `ordinals.com`:" +msgstr " ordinals.com 上で銘文を隠れます:" + +#: src/guides/moderation.md:45 +msgid "SSH into the server" +msgstr "SSHでサーバを登録します。" + +#: src/guides/moderation.md:46 +msgid "Add the inscription ID to `/var/lib/ord/ord.yaml`" +msgstr " `/var/lib/ord/ord.yaml`中で銘文を増やしますID" + +#: src/guides/moderation.md:47 +msgid "Restart the service with `systemctl restart ord`" +msgstr " `systemctl restart ord`で サービスを再起動します。" + +#: src/guides/moderation.md:48 +msgid "Monitor the restart with `journalctl -u ord`" +msgstr " `journalctl -u ord` で再起動します。" + +#: src/guides/moderation.md:50 +msgid "" +"Currently, `ord` is slow to restart, so the site will not come back online " +"immediately." +msgstr "今は、ordの再起動の速度が遅いから、そのため、サイトはすぐにオンラインに戻りません。" + +#: src/guides/reindexing.md:4 +msgid "" +"Sometimes the `ord` database must be reindexed, which means deleting the " +"database and restarting the indexing process with either `ord index run` or " +"`ord server`. Reasons to reindex are:" +msgstr "" +"「ord」データベースを再インデックスする必要がある場合があります。これは、データベースを削除し、「ord index run」または「ord server」を使用することを意味します。" +"を使用してデータベースを再インデックス化します。再インデックスを作成する理由は次のとおりです。:" + +#: src/guides/reindexing.md:8 +msgid "A new major release of ord, which changes the database scheme" +msgstr "ord 发布新的主要版本,更改了数据库架构 新たなメインバージョンをリリースして、データベースのスキーマを変更されました。" + +#: src/guides/reindexing.md:9 +msgid "The database got corrupted somehow" +msgstr "データベースは壊れるかもしれません" + +#: src/guides/reindexing.md:11 +msgid "" +"The database `ord` uses is called [redb](https://github.com/cberner/redb), " +"so we give the index the default file name `index.redb`. By default we store " +"this file in different locations depending on your operating system." +msgstr "" +"`ord`は 使っているデータベースは [redb](https://github.com/cberner/redb)を呼ばれています," +"索引のために‘index.redb’を指定された黙認ファイル名として、黙認する場合は保存します" +"操作システムによって、このファイルは異なる位置にあります" + +#: src/guides/reindexing.md:15 +msgid "Platform" +msgstr "プラットフォーム" + +#: src/guides/reindexing.md:15 +msgid "Value" +msgstr "" + +#: src/guides/reindexing.md:17 +msgid "Linux" +msgstr "" + +#: src/guides/reindexing.md:17 +msgid "`$XDG_DATA_HOME`/ord or `$HOME`/.local/share/ord" +msgstr "" + +#: src/guides/reindexing.md:17 +msgid "/home/alice/.local/share/ord" +msgstr "" + +#: src/guides/reindexing.md:18 +msgid "macOS" +msgstr "" + +#: src/guides/reindexing.md:18 +msgid "`$HOME`/Library/Application Support/ord" +msgstr "" + +#: src/guides/reindexing.md:18 +msgid "/Users/Alice/Library/Application Support/ord" +msgstr "" + +#: src/guides/reindexing.md:19 +msgid "Windows" +msgstr "" + +#: src/guides/reindexing.md:19 +msgid "`{FOLDERID_RoamingAppData}`\\\\ord" +msgstr "" + +#: src/guides/reindexing.md:19 +msgid "C:\\Users\\Alice\\AppData\\Roaming\\ord" +msgstr "" + +#: src/guides/reindexing.md:21 +msgid "" +"So to delete the database and reindex on MacOS you would have to run the " +"following commands in the terminal:" +msgstr "" +"ですので,MacOSの上にデータベースを削除して再索引し、ターミナルでこのコマンドを実行します。" + +#: src/guides/reindexing.md:24 +msgid "" +"```bash\n" +"rm ~/Library/Application Support/ord/index.redb\n" +"ord index run\n" +"```" +msgstr "" + +#: src/guides/reindexing.md:29 +msgid "" +"You can of course also set the location of the data directory yourself with " +"`ord --data-dir index run` or give it a specific filename and path " +"with `ord --index index run`." +msgstr "" +"もちろん自分でデータの目録の位置を設置することができます,`ord --data-dir index run` または" +"指定された特定のファイル名とパスに‘ord --index で索引運行します’。" + +#: src/bounties.md:1 +msgid "Ordinal Bounty Hunting Hints" +msgstr "Ordinals賞金計画の提示" + +#: src/bounties.md:4 +msgid "" +"The `ord` wallet can send and receive specific satoshis. Additionally, " +"ordinal theory is extremely simple. A clever hacker should be able to write " +"code from scratch to manipulate satoshis using ordinal theory in no time." +msgstr "" +"`ord` ウォレットは特定の聡を発送して、受け取れます。その他、序数理論は非常に簡単で、賢いハッカが速く最初から始めることができるはずです" +"コードを書いて、序数理論を使って聡を操作します。" + +#: src/bounties.md:8 +msgid "" +"For more information about ordinal theory, check out the [FAQ](./faq.md) for " +"an overview, the [BIP](https://github.com/ordinals/ord/blob/master/bip." +"mediawiki) for the technical details, and the [ord repo](https://github.com/" +"ordinals/ord) for the `ord` wallet and block explorer." +msgstr "" +"序数理論のより多くの情報に関して,[FAQ](./faq.md) を閲見して概要を獲得します。" +"[BIP](https://github.com/ordinals/ord/blob/master/bip.mediawiki) を閲見して、技術の詳細を獲得します" +"[ord repo](https://github.com/ordinals/ord)を閲見して、`ord`ウォレットとブラウザの情報を獲得します." + +#: src/bounties.md:14 +msgid "" +"Satoshi was the original developer of ordinal theory. However, he knew that " +"others would consider it heretical and dangerous, so he hid his knowledge, " +"and it was lost to the sands of time. This potent theory is only now being " +"rediscovered. You can help by researching rare satoshis." +msgstr "" +"聡は序数理論の原始の開発者であり、しかし、他の人は変なことだと、危険だと思われますが彼は自分の知識を隠れて、" +"時間の砂漠に消えてしまいます。現在、この強い理論は発見されて、珍しい聡を研究することによって私たちを手伝っていただきます。" + +#: src/bounties.md:19 +msgid "Good luck and godspeed!" +msgstr "ご好運、順調に進んでいるように!" + +#: src/bounty/0.md:1 +msgid "Ordinal Bounty 0" +msgstr "賞金任務 0" + +#: src/bounty/0.md:4 src/bounty/1.md:4 src/bounty/2.md:4 src/bounty/3.md:4 +msgid "Criteria" +msgstr "標準" + +#: src/bounty/0.md:7 +msgid "" +"Send a sat whose ordinal number ends with a zero to the submission address:" +msgstr "序数の“0”で終わりの聡を提出アドレスに発送します。" + +#: src/bounty/0.md:9 +msgid "✅: [1857578125803250](https://ordinals.com/ordinal/1857578125803250)" +msgstr "" + +#: src/bounty/0.md:11 +msgid "❌: [1857578125803251](https://ordinals.com/ordinal/1857578125803251)" +msgstr "" + +#: src/bounty/0.md:13 +msgid "The sat must be the first sat of the output you send." +msgstr "聡はあなたが発送した“輸出”の初めての聡でなければなりません。" + +#: src/bounty/0.md:15 src/bounty/1.md:14 src/bounty/2.md:15 src/bounty/3.md:63 +msgid "Reward" +msgstr "奨励" + +#: src/bounty/0.md:18 +msgid "100,000 sats" +msgstr "" + +#: src/bounty/0.md:20 src/bounty/1.md:19 src/bounty/2.md:20 src/bounty/3.md:70 +msgid "Submission Address" +msgstr "アドレスを提出する" + +#: src/bounty/0.md:23 +msgid "" +"[`1PE7u4wbDP2RqfKN6geD1bG57v9Gj9FXm3`](https://mempool.space/" +"address/1PE7u4wbDP2RqfKN6geD1bG57v9Gj9FXm3)" +msgstr "" + +#: src/bounty/0.md:25 src/bounty/1.md:24 src/bounty/2.md:25 src/bounty/3.md:75 +msgid "Status" +msgstr "状態" + +#: src/bounty/0.md:28 +msgid "" +"Claimed by [@count_null](https://twitter.com/rodarmor/" +"status/1560793241473400833)!" +msgstr "" +"[@count_null](https://twitter.com/rodarmor/" +"status/1560793241473400833)! 獲得" + +#: src/bounty/1.md:1 +msgid "Ordinal Bounty 1" +msgstr "賞金任務 1" + +#: src/bounty/1.md:7 +msgid "" +"The transaction that submits a UTXO containing the oldest sat, i.e., that " +"with the lowest number, amongst all submitted UTXOs will be judged the " +"winner." +msgstr "一つの最も古い聡を含まれるUTXOを提出されます。例えば、すべて提出されたUTXOの中に最も小さい数字は優勝者とします" + +#: src/bounty/1.md:10 +msgid "" +"The bounty is open for submissions until block 753984—the first block of " +"difficulty adjustment period 374. Submissions included in block 753984 or " +"later will not be considered." +msgstr "" +"賞金はブロック高度753984 の前に有効であり、ブロック高度753984は初めての難易度の調整期374の後の初めてのブロックです。" +"これらを含まれてまたはブロック高度753984より遅いのは考えされません。" + +#: src/bounty/1.md:17 +msgid "200,000 sats" +msgstr "" + +#: src/bounty/1.md:22 +msgid "" +"[`145Z7PFHyVrwiMWwEcUmDgFbmUbQSU9aap`](https://mempool.space/" +"address/145Z7PFHyVrwiMWwEcUmDgFbmUbQSU9aap)" +msgstr "" + +#: src/bounty/1.md:27 +msgid "" +"Claimed by [@ordinalsindex](https://twitter.com/rodarmor/" +"status/1569883266508853251)!" +msgstr "" +" [@ordinalsindex](https://twitter.com/rodarmor/" +"status/1569883266508853251)は獲得!" + +#: src/bounty/2.md:1 +msgid "Ordinal Bounty 2" +msgstr "賞金任務 2" + +#: src/bounty/2.md:7 +msgid "Send an " +msgstr "一つ発送します" + +#: src/bounty/2.md:7 +msgid "uncommon" +msgstr "普通ではないの" + +#: src/bounty/2.md:7 +msgid " sat to the submission address:" +msgstr "聡は下のアドレスに" + +#: src/bounty/2.md:9 +msgid "✅: [347100000000000](https://ordinals.com/sat/347100000000000)" +msgstr "" + +#: src/bounty/2.md:11 +msgid "❌: [6685000001337](https://ordinals.com/sat/6685000001337)" +msgstr "" + +#: src/bounty/2.md:13 +msgid "" +"Confirm that the submission address has not received transactions before " +"submitting your entry. Only the first successful submission will be rewarded." +msgstr "" +"提出する前に、上述のアドレスがこの前に他の珍しい聡が受け取らなかったことを確認し、最初に提出されたのは奨励を得られます。" + +#: src/bounty/2.md:18 +msgid "300,000 sats" +msgstr "" + +#: src/bounty/2.md:23 +msgid "" +"[`1Hyr94uypwWq5CQffaXHvwUMEyBPp3TUZH`](https://mempool.space/" +"address/1Hyr94uypwWq5CQffaXHvwUMEyBPp3TUZH)" +msgstr "" + +#: src/bounty/2.md:28 +msgid "" +"Claimed by [@utxoset](https://twitter.com/rodarmor/" +"status/1582424455615172608)!" +msgstr "" +"[@utxoset](https://twitter.com/rodarmor/" +"status/1582424455615172608) は獲得!" + +#: src/bounty/3.md:1 +msgid "Ordinal Bounty 3" +msgstr "賞金任務 3" + +#: src/bounty/3.md:7 +msgid "" +"Ordinal bounty 3 has two parts, both of which are based on _ordinal names_. " +"Ordinal names are a modified base-26 encoding of ordinal numbers. To avoid " +"locking short names inside the unspendable genesis block coinbase reward, " +"ordinal names get _shorter_ as the ordinal number gets _longer_. The name of " +"sat 0, the first sat to be mined is `nvtdijuwxlp` and the name of sat " +"2,099,999,997,689,999, the last sat to be mined, is `a`." +msgstr "" +"任务3は二つの部分があり、序数の名前に基づきます_" +"序数の名前は序数の数字を直したbase-26によって行われたコードです。短い名前を時間をかけはいけない創成プレート奨励の中に絞らないように" +"序数の長くなるほど、序数の名前は短くなります。例えば、初めに採掘された0番の聡の名前は`nvtdijuwxlpで`、" +"最後に採掘された2,099,999,997,689,999番の聡の名前は `a`です。" + +#: src/bounty/3.md:14 +msgid "" +"The bounty is open for submissions until block 840000—the first block after " +"the fourth halvening. Submissions included in block 840000 or later will not " +"be considered." +msgstr "" +"賞金計画はブロック高度の840000の-第四回の半分にしたの初めてのブロックまで開放します。ブロック高度の840000及びそれ以上のブロックは考えられません" + +#: src/bounty/3.md:18 +msgid "" +"Both parts use [frequency.tsv](frequency.tsv), a list of words and the " +"number of times they occur in the [Google Books Ngram dataset](http://" +"storage.googleapis.com/books/ngrams/books/datasetsv2.html). filtered to only " +"include the names of sats which will have been mined by the end of the " +"submission period, that appear at least 5000 times in the corpus." +msgstr "" +"二つの部分のミッションが使われ [frequency.tsv](frequency.tsv), 一つの単語のリスト及び" +" [Google Books Ngram dataset](http://storage.googleapis.com/books/ngrams/books/datasetsv2.html)" +"で現れた回数。濾過した後、提出時間が終わるときに発掘された聡の名前だけを含まれ、これらの名称は少なくともコーパスの中で5000回以上現れます。" + +#: src/bounty/3.md:24 +msgid "" +"`frequency.tsv` is a file of tab-separated values. The first column is the " +"word, and the second is the number of times it appears in the corpus. The " +"entries are sorted from least-frequently occurring to most-frequently " +"occurring." +msgstr "" +"`frequency.tsv` タブ区切り値のファイルは第一列が単語で,第二列がコーパスに現れる回数です" +"これらの条目は出現の最も低い頻度から最も高い頻度まで順番に並べています。" + +#: src/bounty/3.md:29 +msgid "" +"`frequency.tsv` was compiled using [this program](https://github.com/casey/" +"onegrams)." +msgstr "" +"`frequency.tsv` [このプログラム]を使って(https://github.com/casey/onegrams)纂訳されます。." + + +#: src/bounty/3.md:32 +msgid "" +"To search an `ord` wallet for sats with a name in `frequency.tsv`, use the " +"following [`ord`](https://github.com/ordinals/ord) command:" +msgstr "" +"`ord`ウォレットの中で`frequency.tsv`の中に含まれた聡の名前を検索して , したのを使います" +"[`ord`](https://github.com/ordinals/ord)コマンド: " + +#: src/bounty/3.md:35 +msgid "" +"```\n" +"ord wallet sats --tsv frequency.tsv\n" +"```" +msgstr "" + +#: src/bounty/3.md:39 +msgid "" +"This command requires the sat index, so `--index-sats` must be passed to ord " +"when first creating the index." +msgstr "" +"このコマンドは聡の索引必要なので,`--index-sats` は初めに索引を作り上げる時に使います。" + +#: src/bounty/3.md:42 +msgid "Part 0" +msgstr "第0部分" + +#: src/bounty/3.md:44 +msgid "_Rare sats pair best with rare words._" +msgstr "_珍しい聡と珍しい名前のベストマッチ" + +#: src/bounty/3.md:46 +msgid "" +"The transaction that submits the UTXO containing the sat whose name appears " +"with the lowest number of occurrences in `frequency.tsv` shall be the winner " +"of part 0." +msgstr "" +"提出したUTXOの中に聡の名前が含まれ、`frequency.tsv`の中に頻度が最も低い人は第0部分の優勝者であります。。" + +#: src/bounty/3.md:50 +msgid "Part 1" +msgstr "第1部分" + +#: src/bounty/3.md:52 +msgid "_Popularity is the font of value._" +msgstr "_人気は価値の源泉です_" + + +#: src/bounty/3.md:54 +msgid "" +"The transaction that submits the UTXO containing the sat whose name appears " +"with the highest number of occurrences in `frequency.tsv` shall be the " +"winner of part 1." +msgstr "" +"提出したUTXOの中に聡の名前が含まれ、`frequency.tsv`の中に頻度が最も高い人は第一部分の優勝者であります。" + +#: src/bounty/3.md:58 +msgid "Tie Breaking" +msgstr "勝負なしの場合" + +#: src/bounty/3.md:60 +msgid "" +"In the case of a tie, where two submissions occur with the same frequency, " +"the earlier submission shall be the winner." +msgstr "勝負なしの場合は二つの提出が同じ頻度でしたら、もっと早く提出した人は優勝者となります" + +#: src/bounty/3.md:66 +msgid "Part 0: 200,000 sats" +msgstr "" + +#: src/bounty/3.md:67 +msgid "Part 1: 200,000 sats" +msgstr "" + +#: src/bounty/3.md:68 +msgid "Total: 400,000 sats" +msgstr "" + +#: src/bounty/3.md:73 +msgid "" +"[`17m5rvMpi78zG8RUpCRd6NWWMJtWmu65kg`](https://mempool.space/" +"address/17m5rvMpi78zG8RUpCRd6NWWMJtWmu65kg)" +msgstr "" + +#: src/bounty/3.md:78 +msgid "Unclaimed!" +msgstr "依然有効です!" diff --git a/docs/po/zh.po b/docs/po/zh.po new file mode 100644 index 0000000000..a87fe3f30f --- /dev/null +++ b/docs/po/zh.po @@ -0,0 +1,4851 @@ +msgid "" +msgstr "" +"Project-Id-Version: 序数理论手册\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2023-08-30 10:03+0800\n" +"Last-Translator: Dr.JingLee \n" +"Language-Team: Chinese\n" +"Language: zh\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: src/SUMMARY.md:2 src/introduction.md:1 +msgid "Introduction" +msgstr "介绍" + +#: src/SUMMARY.md:3 +msgid "Overview" +msgstr "概述" + +#: src/SUMMARY.md:4 src/digital-artifacts.md:1 +msgid "Digital Artifacts" +msgstr "数字文物" + +#: src/SUMMARY.md:5 src/SUMMARY.md:13 src/overview.md:221 src/inscriptions.md:1 +msgid "Inscriptions" +msgstr "铭文" + +#: src/SUMMARY.md:6 src/inscriptions/provenance.md:1 +msgid "Provenance" +msgstr "溯源" + +#: src/SUMMARY.md:7 src/inscriptions/recursion.md:1 +msgid "Recursion" +msgstr "递归" + +#: src/SUMMARY.md:8 +msgid "FAQ" +msgstr "常见问题" + +#: src/SUMMARY.md:9 +msgid "Contributing" +msgstr "贡献" + +#: src/SUMMARY.md:10 src/donate.md:1 +msgid "Donate" +msgstr "捐赠" + +#: src/SUMMARY.md:11 +msgid "Guides" +msgstr "指引" + +#: src/SUMMARY.md:12 +msgid "Explorer" +msgstr "浏览器" + +#: src/SUMMARY.md:14 src/guides/sat-hunting.md:1 +msgid "Sat Hunting" +msgstr "猎聪" + +#: src/SUMMARY.md:15 src/guides/collecting.md:1 +msgid "Collecting" +msgstr "收藏" + +#: src/SUMMARY.md:16 src/guides/sat-hunting.md:239 +msgid "Sparrow Wallet" +msgstr "麻雀钱包" + +#: src/SUMMARY.md:17 src/guides/testing.md:1 +msgid "Testing" +msgstr "调试" + +#: src/SUMMARY.md:18 src/guides/moderation.md:1 +msgid "Moderation" +msgstr "调节" + +#: src/SUMMARY.md:19 src/guides/reindexing.md:1 +msgid "Reindexing" +msgstr "重新索引" + +#: src/SUMMARY.md:20 +msgid "Bounties" +msgstr "赏金" + +#: src/SUMMARY.md:21 +msgid "Bounty 0: 100,000 sats Claimed!" +msgstr "任务 0: 100,000 sats 完成!" + +#: src/SUMMARY.md:22 +msgid "Bounty 1: 200,000 sats Claimed!" +msgstr "任务 1: 200,000 sats 完成!" + +#: src/SUMMARY.md:23 +msgid "Bounty 2: 300,000 sats Claimed!" +msgstr "任务 2: 300,000 sats 完成!" + +#: src/SUMMARY.md:24 +msgid "Bounty 3: 400,000 sats" +msgstr "任务 3: 400,000 sats" + +#: src/introduction.md:4 +msgid "" +"This handbook is a guide to ordinal theory. Ordinal theory concerns itself " +"with satoshis, giving them individual identities and allowing them to be " +"tracked, transferred, and imbued with meaning." +msgstr "" +"这本手册是序数理论(Ordinals Theory)的指南。 序数理论本身关注聪(Satoshi)," +"赋予它们个体身份,并允许它们被追踪、转移并赋予意义。" + +#: src/introduction.md:8 +msgid "" +"Satoshis, not bitcoin, are the atomic, native currency of the Bitcoin " +"network. One bitcoin can be sub-divided into 100,000,000 satoshis, but no " +"further." +msgstr "" +"聪(Satoshi),并非比特币,是比特币网络的原生货币和最小单位。一个比特币可以被" +"细分为100,000,000聪,但不能再细分了。" + +#: src/introduction.md:11 +msgid "" +"Ordinal theory does not require a sidechain or token aside from Bitcoin, and " +"can be used without any changes to the Bitcoin network. It works right now." +msgstr "" +"序数理论不需要比特币区块链之外的侧链或代币,并且可以在不对比特币网络进行任何" +"更改的情况下使用。它即刻可以有效使用。" + +#: src/introduction.md:14 +msgid "" +"Ordinal theory imbues satoshis with numismatic value, allowing them to be " +"collected and traded as curios." +msgstr "序数理论赋予聪以收藏价值,使它们可以作为古玩被收藏和交易。" + +#: src/introduction.md:17 +msgid "" +"Individual satoshis can be inscribed with arbitrary content, creating unique " +"Bitcoin-native digital artifacts that can be held in Bitcoin wallets and " +"transferred using Bitcoin transactions. Inscriptions are as durable, " +"immutable, secure, and decentralized as Bitcoin itself." +msgstr "" +"单个聪可以刻有任意内容,创建独特的比特币原生的数字文物(Digital Artifact)可" +"以保存在比特币钱包中并使用比特币交易进行传输。铭文(Inscription)与比特币本身" +"一样持久、永恒、安全和去中心化。" + +#: src/introduction.md:22 +msgid "" +"Other, more unusual use-cases are possible: off-chain colored-coins, public " +"key infrastructure with key rotation, a decentralized replacement for the " +"DNS. For now though, such use-cases are speculative, and exist only in the " +"minds of fringe ordinal theorists." +msgstr "" +"其他非常规的应用也是可能的:链下染色硬币,具有密钥轮换的公钥基础设施DNS 的去中" +"心化替代品等等。 不过就目前而言,这样的应用是推测性的,只存在于非主流的序数理" +"论家的脑海中。" + +#: src/introduction.md:27 +msgid "For more details on ordinal theory, see the [overview](overview.md)." +msgstr "有关序数理论的更多详细信息,请参阅 [概述](overview.md)." + +#: src/introduction.md:29 +msgid "For more details on inscriptions, see [inscriptions](inscriptions.md)." +msgstr "有关铭文的更多详细信息,请参阅[铭文](inscriptions.md)." + +#: src/introduction.md:31 +msgid "" +"When you're ready to get your hands dirty, a good place to start is with " +"[inscriptions](guides/inscriptions.md), a curious species of digital " +"artifact enabled by ordinal theory." +msgstr "" +"当您准备好亲自动手时,一个好的起点是[铭文](guides/inscriptions.md)这是一种由" +"序数理论支持的独特的数字文物。" + +#: src/introduction.md:35 +msgid "Links" +msgstr "链接" + +#: src/introduction.md:38 +msgid "[GitHub](https://github.com/ordinals/ord/)" +msgstr "[GitHub仓库](https://github.com/ordinals/ord/)" + +#: src/introduction.md:39 +msgid "[BIP](https://github.com/ordinals/ord/blob/master/bip.mediawiki)" +msgstr "[BIP](https://github.com/ordinals/ord/blob/master/bip.mediawiki)" + +#: src/introduction.md:40 +msgid "[Discord](https://discord.gg/ordinals)" +msgstr "[Discord](https://discord.gg/ordinals)" + +#: src/introduction.md:41 +msgid "[Open Ordinals Institute Website](https://ordinals.org/)" +msgstr "[Open Ordinals Institute 网站](https://ordinals.org/)" + +#: src/introduction.md:42 +msgid "[Open Ordinals Institute X](https://x.com/ordinalsorg)" +msgstr "[Open Ordinals Institute X账户](https://x.com/ordinalsorg)" + +#: src/introduction.md:43 +msgid "[Mainnet Block Explorer](https://ordinals.com)" +msgstr "[主网区块](https://ordinals.com)" + +#: src/introduction.md:44 +msgid "[Signet Block Explorer](https://signet.ordinals.com)" +msgstr "[Signet区块浏览器](https://signet.ordinals.com)" + +#: src/introduction.md:46 +msgid "Videos" +msgstr "视频" + +#: src/introduction.md:49 +msgid "" +"[Ordinal Theory Explained: Satoshi Serial Numbers and NFTs on Bitcoin]" +"(https://www.youtube.com/watch?v=rSS0O2KQpsI)" +msgstr "" +"[解释序数理论: 聪的序列号和比特币上的NFT](https://www.youtube.com/watch?" +"v=rSS0O2KQpsI)" + +#: src/introduction.md:50 +msgid "" +"[Ordinals Workshop with Rodarmor](https://www.youtube.com/watch?" +"v=MC_haVa6N3I)" +msgstr "" +"[CaseyRodarmor的序数理论工作坊 ](https://www.youtube.com/watch?v=MC_haVa6N3I)" + +#: src/introduction.md:51 +msgid "" +"[Ordinal Art: Mint Your own NFTs on Bitcoin w/ @rodarmor](https://www." +"youtube.com/watch?v=j5V33kV3iqo)" +msgstr "" +"[序数艺术:在比特币上铸造你自己的NFT w/ @rodarmor](https://www.youtube.com/" +"watch?v=j5V33kV3iqo)" + +#: src/overview.md:1 +msgid "Ordinal Theory Overview" +msgstr "序数理论概述" + +#: src/overview.md:4 +msgid "" +"Ordinals are a numbering scheme for satoshis that allows tracking and " +"transferring individual sats. These numbers are called [ordinal numbers]" +"(https://ordinals.com). Satoshis are numbered in the order in which they're " +"mined, and transferred from transaction inputs to transaction outputs first-" +"in-first-out. Both the numbering scheme and the transfer scheme rely on " +"_order_, the numbering scheme on the _order_ in which satoshis are mined, " +"and the transfer scheme on the _order_ of transaction inputs and outputs. " +"Thus the name, _ordinals_." +msgstr "" +"序数是一种比特币的编号方案,允许跟踪和转移单个聪。这些数字被称作[序号]" +"(https://ordinals.com)。比特币是按照它们被挖掘的顺序编号的,并从交易输入转移" +"到交易输出(遵循先进先出原则)。编号方案和传输方案都依赖于_顺序_,编号方案依" +"赖于比特币被挖掘的_顺序_,而传输方案依赖于交易输入和输出的_顺序_。因此得名,_" +"序数(Ordinals_。" + +#: src/overview.md:13 +msgid "" +"Technical details are available in [the BIP](https://github.com/ordinals/ord/" +"blob/master/bip.mediawiki)." +msgstr "" +"技术细节可以在[the BIP](https://github.com/ordinals/ord/blob/master/bip." +"mediawiki)获取." + +#: src/overview.md:16 +msgid "" +"Ordinal theory does not require a separate token, another blockchain, or any " +"changes to Bitcoin. It works right now." +msgstr "" +"序数理论不需要一个单独的代币,单独区块链,或者对比特币进行任何更改。它即刻可" +"以有效运转。" + +#: src/overview.md:19 +msgid "Ordinal numbers have a few different representations:" +msgstr "序号有几种不同的表示方式:" + +#: src/overview.md:21 +msgid "" +"_Integer notation_: [`2099994106992659`](https://ordinals.com/" +"sat/2099994106992659) The ordinal number, assigned according to the order in " +"which the satoshi was mined." +msgstr "" +"_整数符号_:[`2099994106992659`](https://ordinals.com/sat/2099994106992659) 这" +"个序号是根据挖掘聪的顺序分配。" + +#: src/overview.md:26 +msgid "" +"_Decimal notation_: [`3891094.16797`](https://ordinals.com/" +"sat/3891094.16797) The first number is the block height in which the satoshi " +"was mined, the second the offset of the satoshi within the block." +msgstr "" +"_十进制符号_: [`3891094.16797`](https://ordinals.com/sat/3891094.16797) 第一" +"个数字是挖掘聪的区块高度,第二个数字是区块内聪的偏移量。 " + +#: src/overview.md:31 +msgid "" +"_Degree notation_: [`3°111094′214″16797‴`](https://ordinals.com/" +"sat/3%C2%B0111094%E2%80%B2214%E2%80%B316797%E2%80%B4). We'll get to that in " +"a moment." +msgstr "" +"_度数符号_: [`3°111094′214″16797‴`](https://ordinals.com/" +"sat/3%C2%B0111094%E2%80%B2214%E2%80%B316797%E2%80%B4) 我们马上就会讲到。 " + +#: src/overview.md:35 +msgid "" +"_Percentile notation_: [`99.99971949060254%`](https://ordinals.com/" +"sat/99.99971949060254%25) . The satoshi's position in Bitcoin's supply, " +"expressed as a percentage." +msgstr "" +"_百分数_: [`99.99971949060254%`](https://ordinals.com/" +"sat/99.99971949060254%25) . 以百分比表示聪在比特币供应中的位置 " + +#: src/overview.md:39 +msgid "" +"_Name_: [`satoshi`](https://ordinals.com/sat/satoshi). An encoding of the " +"ordinal number using the characters `a` through `z`." +msgstr "" +"_名字_: [`satoshi`](https://ordinals.com/sat/satoshi). 一种使用字母`a` 到 `z`" +"对序号进行编码的方法" + +#: src/overview.md:42 +msgid "" +"Arbitrary assets, such as NFTs, security tokens, accounts, or stablecoins " +"can be attached to satoshis using ordinal numbers as stable identifiers." +msgstr "" +"任意资产,如NFT、安全令牌、帐户或稳定币, 都可以使用序数作为稳定标识符附加到" +"聪上。" + +#: src/overview.md:45 +msgid "" +"Ordinals is an open-source project, developed [on GitHub](https://github.com/" +"ordinals/ord). The project consists of a BIP describing the ordinal scheme, " +"an index that communicates with a Bitcoin Core node to track the location of " +"all satoshis, a wallet that allows making ordinal-aware transactions, a " +"block explorer for interactive exploration of the blockchain, functionality " +"for inscribing satoshis with digital artifacts, and this manual." +msgstr "" +"Ordinals是一个开源项目,部署在[on GitHub](https://github.com/ordinals/ord). " +"该项目包括一个描述序数方案的BIP、 一个与比特币核心节点通信以跟踪所有聪位置的" +"索引一个允许进行序号感知交易的钱包、 一个用于区块链交互探索的区块资源管理器、" +"用数字文物嵌入聪的功能,以及本手册。 " + +#: src/overview.md:52 +msgid "Rarity" +msgstr "稀缺度" + +#: src/overview.md:55 +msgid "" +"Humans are collectors, and since satoshis can now be tracked and " +"transferred, people will naturally want to collect them. Ordinal theorists " +"can decide for themselves which sats are rare and desirable, but there are " +"some hints…" +msgstr "" +"人类是收藏者。由于聪现在可以被追踪和转移,人们自然会想要收藏它们。 序数理论家" +"可以自己决定哪些聪是稀有和合意的, 这里有一些提示…" + +#: src/overview.md:59 +msgid "" +"Bitcoin has periodic events, some frequent, some more uncommon, and these " +"naturally lend themselves to a system of rarity. These periodic events are:" +msgstr "" +"比特币有周期性的事件,有些频繁,有些不常见,这些事件自然而然地形成了一个稀有" +"度系统。这些周期性事件是:" + +#: src/overview.md:62 +msgid "" +"_Blocks_: A new block is mined approximately every 10 minutes, from now " +"until the end of time." +msgstr "_区块_: 从现在到时间结束,大约每10分钟挖掘一个新区块。" + +#: src/overview.md:65 +msgid "" +"_Difficulty adjustments_: Every 2016 blocks, or approximately every two " +"weeks, the Bitcoin network responds to changes in hashrate by adjusting the " +"difficulty target which blocks must meet in order to be accepted." +msgstr "" +"_难度调整_: 每2016个区块,或大约每两周, 比特币网络通过调整区块必须满足的难度" +"目标来响应哈希率的变化。 " + +#: src/overview.md:69 +msgid "" +"_Halvings_: Every 210,000 blocks, or roughly every four years, the amount of " +"new sats created in every block is cut in half." +msgstr "" +"_减半_: 每21万个区块,或者大约每四年,每个区块产生的新聪的数量就会减半。 " + +#: src/overview.md:72 +msgid "" +"_Cycles_: Every six halvings, something magical happens: the halving and the " +"difficulty adjustment coincide. This is called a conjunction, and the time " +"period between conjunctions a cycle. A conjunction occurs roughly every 24 " +"years. The first conjunction should happen sometime in 2032." +msgstr "" +"_周期_: 每六次减半就会发生一些神奇的事情:减半和难度调整会同时发生,这就是所" +"谓的相合,相合之间的时间周期是一个周期。 大约每24年就会发生一次相合,第一次相" +"合应该会发生在2032年的某个时候。 " + +#: src/overview.md:77 +msgid "This gives us the following rarity levels:" +msgstr "这给了我们以下稀缺度等级:" + +#: src/overview.md:79 +msgid "`common`: Any sat that is not the first sat of its block" +msgstr "`普通`: 指所有不是其区块第一个聪的聪" + +#: src/overview.md:80 +msgid "`uncommon`: The first sat of each block" +msgstr "`非普通`: 每个区块的第一个聪" + +#: src/overview.md:81 +msgid "`rare`: The first sat of each difficulty adjustment period" +msgstr "`罕见`: 每一个难度调整周期的第一个聪" + +#: src/overview.md:82 +msgid "`epic`: The first sat of each halving epoch" +msgstr "`史诗`: 每个减半周期的第一个聪h" + +#: src/overview.md:83 +msgid "`legendary`: The first sat of each cycle" +msgstr "`传奇`: 每一个循环周期的第一个聪" + +#: src/overview.md:84 +msgid "`mythic`: The first sat of the genesis block" +msgstr "`神话`: 创世区块的第一个聪" + +#: src/overview.md:86 +msgid "" +"Which brings us to degree notation, which unambiguously represents an " +"ordinal number in a way that makes the rarity of a satoshi easy to see at a " +"glance:" +msgstr "" +"这给我们带来了度数表示法,它以一种使聪的稀有性一目了然的方式明确地表示一个序" +"数: " + +#: src/overview.md:89 +msgid "" +"```\n" +"A°B′C″D‴\n" +"│ │ │ ╰─ Index of sat in the block\n" +"│ │ ╰─── Index of block in difficulty adjustment period\n" +"│ ╰───── Index of block in halving epoch\n" +"╰─────── Cycle, numbered starting from 0\n" +"```" +msgstr "" +"```\n" +"A°B′C″D‴\n" +"│ │ │ ╰─ 聪的索引位置\n" +"│ │ ╰─── 难度调整期的区块位置\n" +"│ ╰───── 减半周期区块的索引位置\n" +"╰─────── 循环周期,从0数字开始\n" +"```" + +#: src/overview.md:97 +msgid "" +"Ordinal theorists often use the terms \"hour\", \"minute\", \"second\", and " +"\"third\" for _A_, _B_, _C_, and _D_, respectively." +msgstr "" +"序数理论家通常使用 \"小时\", \"分钟\", \"秒\", 以及 \"第三\" 等专用词汇来对应" +"的表示 _A_, _B_, _C_, 和 _D_。" + +#: src/overview.md:100 +msgid "Now for some examples. This satoshi is common:" +msgstr "现在我们来举一些例子,这是一颗普通的聪" + +#: src/overview.md:102 +msgid "" +"```\n" +"1°1′1″1‴\n" +"│ │ │ ╰─ Not first sat in block\n" +"│ │ ╰─── Not first block in difficulty adjustment period\n" +"│ ╰───── Not first block in halving epoch\n" +"╰─────── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°1′1″1‴\n" +"│ │ │ ╰─ 不是区块的第一个聪\n" +"│ │ ╰─── 不是难度调整周期的第一个聪\n" +"│ ╰───── 不是减半周期的第一个聪\n" +"╰─────── 第二个循环周期\n" +"```" + +#: src/overview.md:111 +msgid "This satoshi is uncommon:" +msgstr "这是一颗不普通的聪" + +#: src/overview.md:113 +msgid "" +"```\n" +"1°1′1″0‴\n" +"│ │ │ ╰─ First sat in block\n" +"│ │ ╰─── Not first block in difficulty adjustment period\n" +"│ ╰───── Not first block in halving epoch\n" +"╰─────── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°1′1″0‴\n" +"│ │ │ ╰─ 是区块的第一颗聪\n" +"│ │ ╰─── 不是难度调整周期的第一个聪\n" +"│ ╰───── 不是减半周期的第一个聪\n" +"╰─────── 第二个循环周期\n" +"```" + +#: src/overview.md:121 +msgid "This satoshi is rare:" +msgstr "这是一颗罕见的聪" + +#: src/overview.md:123 +msgid "" +"```\n" +"1°1′0″0‴\n" +"│ │ │ ╰─ First sat in block\n" +"│ │ ╰─── First block in difficulty adjustment period\n" +"│ ╰───── Not the first block in halving epoch\n" +"╰─────── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°1′0″0‴\n" +"│ │ │ ╰─ 是区块的第一颗聪\n" +"│ │ ╰─── 是难度调整周期的第一个聪\n" +"│ ╰───── 不是减半周期的第一个聪\n" +"╰─────── 第二个循环周期\n" +"```" + +#: src/overview.md:131 +msgid "This satoshi is epic:" +msgstr "这是一个史诗级的聪" + +#: src/overview.md:133 +msgid "" +"```\n" +"1°0′1″0‴\n" +"│ │ │ ╰─ First sat in block\n" +"│ │ ╰─── Not first block in difficulty adjustment period\n" +"│ ╰───── First block in halving epoch\n" +"╰─────── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°0′1″0‴\n" +"│ │ │ ╰─ 是区块的第一颗聪\n" +"│ │ ╰─── 不是难度调整周期的第一个聪\n" +"│ ╰───── 是减半周期的第一个聪\n" +"╰─────── 第二个循环周期\n" +"```" + +#: src/overview.md:141 +msgid "This satoshi is legendary:" +msgstr "这是一颗传奇级的聪" + +#: src/overview.md:143 +msgid "" +"```\n" +"1°0′0″0‴\n" +"│ │ │ ╰─ First sat in block\n" +"│ │ ╰─── First block in difficulty adjustment period\n" +"│ ╰───── First block in halving epoch\n" +"╰─────── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°0′0″0‴\n" +"│ │ │ ╰─ 是区块的第一颗聪\n" +"│ │ ╰─── 是难度调整周期的第一个聪\n" +"│ ╰───── 是减半周期的第一个聪\n" +"╰─────── 第二个循环周期\n" +"```" + +#: src/overview.md:151 +msgid "And this satoshi is mythic:" +msgstr "这是神话级别的聪:" + +#: src/overview.md:153 +msgid "" +"```\n" +"0°0′0″0‴\n" +"│ │ │ ╰─ First sat in block\n" +"│ │ ╰─── First block in difficulty adjustment period\n" +"│ ╰───── First block in halving epoch\n" +"╰─────── First cycle\n" +"```" +msgstr "" +"```\n" +"0°0′0″0‴\n" +"│ │ │ ╰─ 是区块的第一颗聪\n" +"│ │ ╰─── 是难度调整周期的第一个聪\n" +"│ ╰───── 是减半周期的第一个聪\n" +"╰─────── 第一个循环周期\n" +"```" + +#: src/overview.md:161 +msgid "" +"If the block offset is zero, it may be omitted. This is the uncommon satoshi " +"from above:" +msgstr "如果区块偏移量为零,则可以省略。这是对比以上的非普通的聪:" + +#: src/overview.md:164 +msgid "" +"```\n" +"1°1′1″\n" +"│ │ ╰─ Not first block in difficulty adjustment period\n" +"│ ╰─── Not first block in halving epoch\n" +"╰───── Second cycle\n" +"```" +msgstr "" +"```\n" +"1°1′1″\n" +"│ │ ╰─── 不是难度调整周期的第一个聪\n" +"│ ╰───── 不是减半周期的第一个聪\n" +"╰─────── 第二个循环周期\n" +"```" + +#: src/overview.md:171 +msgid "Rare Satoshi Supply" +msgstr "稀有聪的总供给量" + +#: src/overview.md:174 +msgid "Total Supply" +msgstr "总供给" + +#: src/overview.md:176 +msgid "`common`: 2.1 quadrillion" +msgstr "`普通`: 2千100万亿" + +#: src/overview.md:177 +msgid "`uncommon`: 6,929,999" +msgstr "`非普通`: 6,929,999" + +#: src/overview.md:178 +msgid "`rare`: 3437" +msgstr "`罕见`: 3437" + +#: src/overview.md:179 +msgid "`epic`: 32" +msgstr "`史诗`: 32" + +#: src/overview.md:180 +msgid "`legendary`: 5" +msgstr "`传奇`: 5" + +#: src/overview.md:181 src/overview.md:190 +msgid "`mythic`: 1" +msgstr "`神话`: 1" + +#: src/overview.md:183 +msgid "Current Supply" +msgstr "现有的供给量" + +#: src/overview.md:185 +msgid "`common`: 1.9 quadrillion" +msgstr "`普通`: 1千900万亿" + +#: src/overview.md:186 +msgid "`uncommon`: 745,855" +msgstr "`非普通`: 745,855" + +#: src/overview.md:187 +msgid "`rare`: 369" +msgstr "`稀有`: 369" + +#: src/overview.md:188 +msgid "`epic`: 3" +msgstr "`史诗`: 3" + +#: src/overview.md:189 +msgid "`legendary`: 0" +msgstr "`传奇`: 0" + +#: src/overview.md:192 +msgid "" +"At the moment, even uncommon satoshis are quite rare. As of this writing, " +"745,855 uncommon satoshis have been mined - one per 25.6 bitcoin in " +"circulation." +msgstr "" +"目前即使是非普通的聪也非常罕见。 截至撰写本文时, 已开采出 745,855 个非普通的" +"聪-大约在每 25.6个流通比特币中会有一个。 " + +#: src/overview.md:196 +msgid "Names" +msgstr "名字" + +#: src/overview.md:199 +msgid "" +"Each satoshi has a name, consisting of the letters _A_ through _Z_, that get " +"shorter the further into the future the satoshi was mined. They could start " +"short and get longer, but then all the good, short names would be trapped in " +"the unspendable genesis block." +msgstr "" +"每个聪都有一个名字,由字母 _A_ 到 _Z_构成 随着聪被开采的时间越长,名字越短。 " +"如果他们从短开始,然后变得更长,那么所有好的、短的名字都会被困在无法使用的创" +"世块中。 " + +#: src/overview.md:204 +msgid "" +"As an example, 1905530482684727°'s name is \"iaiufjszmoba\". The name of the " +"last satoshi to be mined is \"a\". Every combination of 10 characters or " +"less is out there, or will be out there, someday." +msgstr "" +"举个例子, 1905530482684727°'的名字是 \"iaiufjszmoba\".最后一个被挖掘的聪的名" +"字会是\"a\"。10个字母或更少字符的组合都会存在,或者总有一天会存在。" + +#: src/overview.md:208 +msgid "Exotics" +msgstr "奇特的" + +#: src/overview.md:211 +msgid "" +"Satoshis may be prized for reasons other than their name or rarity. This " +"might be due to a quality of the number itself, like having an integer " +"square or cube root. Or it might be due to a connection to a historical " +"event, such as satoshis from block 477,120, the block in which SegWit " +"activated, or 2099999997689999°, the last satoshi that will ever be mined." +msgstr "" +"除了它们的名字或稀有性之外,聪可能还因为其他原因而受到重视。这可能是由于数字" +"本身的性质,比如具有整数的平方根或立方根。或者它与某件历史事件有关,例如来自" +"区块477,120的聪(SegWit激活的区块)是 2099999997689999°,这是最后一个被挖出来" +"的聪。" + +#: src/overview.md:217 +msgid "" +"Such satoshis are termed \"exotic\". Which satoshis are exotic and what " +"makes them so is subjective. Ordinal theorists are encouraged to seek out " +"exotics based on criteria of their own devising." +msgstr "" +"这种比特币被称为“奇特的”。哪些聪是“奇特的”?是什么让他们如此被重视?序数理论" +"家被鼓励根据他们自己设计的标准来寻找“奇特的”聪。" + +#: src/overview.md:224 +msgid "" +"Satoshis can be inscribed with arbitrary content, creating Bitcoin-native " +"digital artifacts. Inscribing is done by sending the satoshi to be inscribed " +"in a transaction that reveals the inscription content on-chain. This content " +"is then inextricably linked to that satoshi, turning it into an immutable " +"digital artifact that can be tracked, transferred, hoarded, bought, sold, " +"lost, and rediscovered." +msgstr "" +"聪可以刻有任意内容,从而创建比特币原生的数字文物(数字艺术)。铭刻是通过将要" +"铭刻的内容发送到交易中来完成的,该交易会在链上显示铭文内容。由于铭文内容与聪" +"有着密不可分的联系,从将创造了一个不可改变的数字人工制品。这个数字文物可以被" +"追踪、转移、储存、购买、出售、丢失和重新发现。" + +#: src/overview.md:231 +msgid "Archaeology" +msgstr "考古" + +#: src/overview.md:234 +msgid "" +"A lively community of archaeologists devoted to cataloging and collecting " +"early NFTs has sprung up. [Here's a great summary of historical NFTs by " +"Chainleft.](https://mirror.xyz/chainleft.eth/MzPWRsesC9mQflxlLo-" +"N29oF4iwCgX3lacrvaG9Kjko)" +msgstr "" +"致力于编目和收集早期 NFT 的活跃考古学家社区如雨后春笋般涌现 [Chainleft对历史" +"NFT的精彩总结](https://mirror.xyz/chainleft.eth/MzPWRsesC9mQflxlLo-" +"N29oF4iwCgX3lacrvaG9Kjko)" + +#: src/overview.md:238 +msgid "" +"A commonly accepted cut-off for early NFTs is March 19th, 2018, the date the " +"first ERC-721 contract, [SU SQUARES](https://tenthousandsu.com/), was " +"deployed on Ethereum." +msgstr "" +"普遍接受的古老NFT 的截止日期是 2018年3月19日,即 第一个 ERC-721 合约,[SU " +"SQUARES](https://tenthousandsu.com/), 被部署在以太坊上的时间 " + +#: src/overview.md:242 +msgid "" +"Whether or not ordinals are of interest to NFT archaeologists is an open " +"question! In one sense, ordinals were created in early 2022, when the " +"Ordinals specification was finalized. In this sense, they are not of " +"historical interest." +msgstr "" +"NFT 考古学家是否对序数感兴趣是一个悬而未决的问题! 从某种意义上说,序数是在 " +"2022 年初创建的,当时序数规范已定稿" + +#: src/overview.md:247 +msgid "" +"In another sense though, ordinals were in fact created by Satoshi Nakamoto " +"in 2009 when he mined the Bitcoin genesis block. In this sense, ordinals, " +"and especially early ordinals, are certainly of historical interest." +msgstr "" +"从这个意义上说,它们不具有历史意义。但从另一种意义上说,序数实际上是由中本聪" +"在 2009 年开采比特币创世块时创造的。从这个意义上说,序数,尤其是早期的序数," +"当然具有历史意义。" + +#: src/overview.md:251 +msgid "" +"Many ordinal theorists favor the latter view. This is not least because the " +"ordinals were independently discovered on at least two separate occasions, " +"long before the era of modern NFTs began." +msgstr "" +"许多序数理论家赞成后一种观点。这不仅仅是因为序数是在至少两个不同的场合独立发" +"现的,远早于现代 NFT 时代开始。" + +#: src/overview.md:255 +msgid "" +"On August 21st, 2012, Charlie Lee [posted a proposal to add proof-of-stake " +"to Bitcoin to the Bitcoin Talk forum](https://bitcointalk.org/index.php?" +"topic=102355.0). This wasn't an asset scheme, but did use the ordinal " +"algorithm, and was implemented but never deployed." +msgstr "" +"2012 年 8 月 21 日,Charlie Lee 在 Charlie Lee [在Bitcoin Talk论坛上发布一项" +"将比特币权益证明Proof-of-stake添加的提案](https://bitcointalk.org/index.php?" +"topic=102355.0). 这不是资产方案,但确实使用了序数算法,并且已实施但从未部署" +"过。" + +#: src/overview.md:261 +msgid "" +"On October 8th, 2012, jl2012 [posted a scheme to the same forum](https://" +"bitcointalk.org/index.php?topic=117224.0) which uses decimal notation and " +"has all the important properties of ordinals. The scheme was discussed but " +"never implemented." +msgstr "" +"2012 年 10 月 8 日,jl2012 在[同一论坛上发布了一个方案](https://bitcointalk." +"org/index.php?topic=117224.0) 该方案使用十进制表示法并具有序数的所有重要属" +"性。 该计划进行了讨论,但从未实施。" + +#: src/overview.md:266 +msgid "" +"These independent inventions of ordinals indicate in some way that ordinals " +"were discovered, or rediscovered, and not invented. The ordinals are an " +"inevitability of the mathematics of Bitcoin, stemming not from their modern " +"documentation, but from their ancient genesis. They are the culmination of a " +"sequence of events set in motion with the mining of the first block, so many " +"years ago." +msgstr "" +"这些序数的独立发明在某种程度上表明序数是被发现的, 或者是重新发现的,而不是发" +"明的。 序数是比特币数学的必然性, 不是源于它们的现代文档,而是源于它们古老的" +"起源。 它们是许多年前随着第一个区块的开采而启动的一系列事件的高潮。" + +#: src/digital-artifacts.md:4 +msgid "" +"Imagine a physical artifact. A rare coin, say, held safe for untold years in " +"the dark, secret clutch of a Viking hoard, now dug from the earth by your " +"grasping hands. It…" +msgstr "" +"想象有一个实体的人工制品。 比方说,一枚稀有的硬币,在维京人的宝库的黑暗中秘密" +"保存了无数年,现在被你亲手从地下挖了出来。 它…" + +#: src/digital-artifacts.md:8 +msgid "" +"…has an owner. You. As long as you keep it safe, nobody can take it from you." +msgstr "…有了一个主人. 那就是您. 只要您妥善保管,就没有人能从您手中夺走它。" + +#: src/digital-artifacts.md:10 +msgid "…is complete. It has no missing parts." +msgstr "…是完整的。 它没有任何遗漏的部分。" + +#: src/digital-artifacts.md:12 +msgid "" +"…can only be changed by you. If you were a trader, and you made your way to " +"18th century China, none but you could stamp it with your chop-mark." +msgstr "" +"…只能由您来改变。如果您是一名商人,并且您来到了 18世纪的中国,那么除您之外," +"无人可以在上面盖章。" + +#: src/digital-artifacts.md:15 +msgid "" +"…can only be disposed of by you. The sale, trade, or gift is yours to make, " +"to whomever you wish." +msgstr "……只能由您处置。 销售、交易或赠送都是您的决定,您想给谁就给谁。 " + +#: src/digital-artifacts.md:18 +msgid "" +"What are digital artifacts? Simply put, they are the digital equivalent of " +"physical artifacts." +msgstr "" +"什么是数字文物(数字工件、数字人工制品)? 简而言之,它们是物理人工制品的数字" +"等价物。" + +#: src/digital-artifacts.md:21 +msgid "" +"For a digital thing to be a digital artifact, it must be like that coin of " +"yours:" +msgstr "要使数字化事物成为数字人工制品,它必须像您的那枚硬币:" + +#: src/digital-artifacts.md:24 +msgid "" +"Digital artifacts can have owners. A number is not a digital artifact, " +"because nobody can own it." +msgstr "数字文物可以有所有者,因此数字不同于数字文物,因为没有人可以拥有数字。" + +#: src/digital-artifacts.md:27 +msgid "" +"Digital artifacts are complete. An NFT that points to off-chain content on " +"IPFS or Arweave is incomplete, and thus not a digital artifact." +msgstr "" +"数字文物是完整的,指向 IPFS 或 Arweave 上链下内容的 NFT 是不完整的,因此不是" +"数字文物。" + +#: src/digital-artifacts.md:30 +msgid "" +"Digital artifacts are permissionless. An NFT which cannot be sold without " +"paying a royalty is not permissionless, and thus not a digital artifact." +msgstr "" +"数字文物是无需许可的,不支付版税就不能出售的 NFT 不是无需许可的,因此不是数字" +"文物。" + +#: src/digital-artifacts.md:33 +msgid "" +"Digital artifacts are uncensorable. Perhaps you can change a database entry " +"on a centralized ledger today, but maybe not tomorrow, and thus one cannot " +"be a digital artifact." +msgstr "" +"数字文物是不可审查的, 也许你今天可以更改集中式分类账上的数据库条目,但明天可" +"能不行 因此一个不是数字文物" + +#: src/digital-artifacts.md:37 +msgid "" +"Digital artifacts are immutable. An NFT with an upgrade key is not a digital " +"artifact." +msgstr "数字文物是不可篡改的,带有升级密钥的NFT不是数字文物。" + +#: src/digital-artifacts.md:40 +msgid "" +"The definition of a digital artifact is intended to reflect what NFTs " +"_should_ be, sometimes are, and what inscriptions _always_ are, by their " +"very nature." +msgstr "" +"数字文物的定义旨在从其特定的本质上反映NFT _应该_ 是什么, 有时是什么, 以及铭文" +"_始终_ 是什么 " + +#: src/inscriptions.md:4 +msgid "" +"Inscriptions inscribe sats with arbitrary content, creating bitcoin-native " +"digital artifacts, more commonly known as NFTs. Inscriptions do not require " +"a sidechain or separate token." +msgstr "" +"铭文里可刻有任意内容,从而创造了比特币原生的数字人工制品,通常被称为 NFT。铭" +"文不需要侧链或单独的代币。 " + +#: src/inscriptions.md:8 +msgid "" +"These inscribed sats can then be transferred using bitcoin transactions, " +"sent to bitcoin addresses, and held in bitcoin UTXOs. These transactions, " +"addresses, and UTXOs are normal bitcoin transactions, addresses, and UTXOS " +"in all respects, with the exception that in order to send individual sats, " +"transactions must control the order and value of inputs and outputs " +"according to ordinal theory." +msgstr "" +"这些铭刻的聪,可以使用比特币交易传输发送到比特币地址,保存在比特币 UTXO 中。" +"这些交易、地址 和 UTXO 在所有方面都是正常的比特币交易、地址和 UTXO。除了为了" +"发送单个聪,交易必须根据序数理论控制输入和输出的顺序和值。 " + +#: src/inscriptions.md:15 +msgid "" +"The inscription content model is that of the web. An inscription consists of " +"a content type, also known as a MIME type, and the content itself, which is " +"a byte string. This allows inscription content to be returned from a web " +"server, and for creating HTML inscriptions that use and remix the content of " +"other inscriptions." +msgstr "" +"铭文内容是基于万维网标准的。铭文由内容类型(也称为 MIME 类型)和内容本身(字" +"节串)组成。这允许从 Web 服务器返回铭文内容,并用于创建和使用HTML铭文并重新混" +"合其他铭文内容。" + +#: src/inscriptions.md:21 +msgid "" +"Inscription content is entirely on-chain, stored in taproot script-path " +"spend scripts. Taproot scripts have very few restrictions on their content, " +"and additionally receive the witness discount, making inscription content " +"storage relatively economical." +msgstr "" +"铭文内容完全在链上,存储在taproot script-path spend脚本中。 Taproot 脚本对其" +"内容的限制很少,并且额外获得见证折扣,使得铭文内容存储相对经济。" + +#: src/inscriptions.md:26 +msgid "" +"Since taproot script spends can only be made from existing taproot outputs, " +"inscriptions are made using a two-phase commit/reveal procedure. First, in " +"the commit transaction, a taproot output committing to a script containing " +"the inscription content is created. Second, in the reveal transaction, the " +"output created by the commit transaction is spent, revealing the inscription " +"content on-chain." +msgstr "" +"因为taproot script-path spend脚本只能从现有的 taproot 输出中产生,因此使用两" +"阶段commit/reveal过程进行铭刻。首先,在commit中,创建一个提交到包含铭文内容的" +"脚本的taproot 输出。 其次,在reveal交易中,使用commit交易产生的输出,来显示链" +"上的铭文内容。" + +#: src/inscriptions.md:33 +msgid "" +"Inscription content is serialized using data pushes within unexecuted " +"conditionals, called \"envelopes\". Envelopes consist of an `OP_FALSE OP_IF " +"… OP_ENDIF` wrapping any number of data pushes. Because envelopes are " +"effectively no-ops, they do not change the semantics of the script in which " +"they are included, and can be combined with any other locking script." +msgstr "" +"铭文内容使用未执行条件中的数据推送进行序列化,称为“信封”。信封由 OP_FALSE " +"OP_IF … OP_ENDIF 组成,包装任意数量的数据推送。因为信封实际上是空操作,所以它" +"们不会改变包含它们的脚本的语义,并且可以与任何其他锁定脚本结合使用。" + +#: src/inscriptions.md:39 +msgid "" +"A text inscription containing the string \"Hello, world!\" is serialized as " +"follows:" +msgstr "包含字符串“Hello, world!”的文本铭文 序列化如下:" + +#: src/inscriptions.md:42 +msgid "" +"```\n" +"OP_FALSE\n" +"OP_IF\n" +" OP_PUSH \"ord\"\n" +" OP_PUSH 1\n" +" OP_PUSH \"text/plain;charset=utf-8\"\n" +" OP_PUSH 0\n" +" OP_PUSH \"Hello, world!\"\n" +"OP_ENDIF\n" +"```" +msgstr "" + +#: src/inscriptions.md:53 +msgid "" +"First the string `ord` is pushed, to disambiguate inscriptions from other " +"uses of envelopes." +msgstr "首先字符串`ord`被推送,以消除铭文与信封其他用途的歧义。" + +#: src/inscriptions.md:56 +#, fuzzy +msgid "" +"`OP_PUSH 1` indicates that the next push contains the content type, and " +"`OP_PUSH 0`indicates that subsequent data pushes contain the content itself. " +"Multiple data pushes must be used for large inscriptions, as one of " +"taproot's few restrictions is that individual data pushes may not be larger " +"than 520 bytes." +msgstr "" +"`OP_PUSH 1` 表示下一次推送包含内容类型, `OP_PUSH 0` 表示后续数据推送包含内容" +"本身,大型铭文必须使用多次数据推送,因为 taproot 的少数限制之一是单个数据推送" +"不得大于 520 字节。" + +#: src/inscriptions.md:62 +msgid "" +"The inscription content is contained within the input of a reveal " +"transaction, and the inscription is made on the first sat of its input. This " +"sat can then be tracked using the familiar rules of ordinal theory, allowing " +"it to be transferred, bought, sold, lost to fees, and recovered." +msgstr "" +"铭文内容包含在reveal交易的输入中,并且铭文是铭刻在其第一个输出的第一个聪" +"(Satoshi)上。我们可以使用熟悉的序数理论规则来跟踪这个聪 sat,允许它被转移、" +"购买、出售、丢失和恢复。" + +#: src/inscriptions.md:67 +msgid "Content" +msgstr "内容" + +#: src/inscriptions.md:70 +msgid "" +"The data model of inscriptions is that of a HTTP response, allowing " +"inscription content to be served by a web server and viewed in a web browser." +msgstr "" +"铭文的数据模型是 HTTP 响应的数据模型,允许铭文由网络服务器提供服务并在网络浏" +"览器中查看的内容。" + +#: src/inscriptions.md:73 +msgid "Fields" +msgstr "字段" + +#: src/inscriptions.md:76 +msgid "" +"Inscriptions may include fields before an optional body. Each field consists " +"of two data pushes, a tag and a value." +msgstr "" +"铭文可以在可选主体之前包含字段。每个字段都包含两个数据推送,一个标签和一个" +"值。" + +#: src/inscriptions.md:79 +msgid "" +"Currently, the only defined field is `content-type`, with a tag of `1`, " +"whose value is the MIME type of the body." +msgstr "" +"目前,唯一定义的字段是‘content-type’,标签为‘1’,其值是正文的 MIME 类型。" + +#: src/inscriptions.md:82 +msgid "" +"The beginning of the body and end of fields is indicated with an empty data " +"push." +msgstr "正文的开头和字段的结尾用'空数据'指示推送。" + +#: src/inscriptions.md:85 +msgid "" +"Unrecognized tags are interpreted differently depending on whether they are " +"even or odd, following the \"it's okay to be odd\" rule used by the " +"Lightning Network." +msgstr "" +"无法识别的标签的解释不同,取决于它们是否是偶数或奇数,遵循闪电网络\"可以是奇" +"数\"的规则。" + +#: src/inscriptions.md:89 +msgid "" +"Even tags are used for fields which may affect creation, initial assignment, " +"or transfer of an inscription. Thus, inscriptions with unrecognized even " +"fields must be displayed as \"unbound\", that is, without a location." +msgstr "" +"甚至标签也用于可能影响创建、初始分配的字段,或铭文的转移。因此,即使无法识别" +"的铭文,字段也必须显示为\"未绑定\",即没有位置。" + +#: src/inscriptions.md:93 +msgid "" +"Odd tags are used for fields which do not affect creation, initial " +"assignment, or transfer, such as additional metadata, and thus are safe to " +"ignore." +msgstr "" +"奇数标签用于不影响创建、初始的字段,分配或转移,例如附加元数据,因此是选择忽略" +"是安全的。" + +#: src/inscriptions.md:96 +msgid "Inscription IDs" +msgstr "铭文身份ID" + +#: src/inscriptions.md:99 +msgid "" +"The inscriptions are contained within the inputs of a reveal transaction. In " +"order to uniquely identify them they are assigned an ID of the form:" +msgstr "" +"铭文包含在揭示交易的输入中。为了唯一地识别他们,他们被分配了一个以下形式的 " +"ID:" + +#: src/inscriptions.md:102 +msgid "`521f8eccffa4c41a3a7728dd012ea5a4a02feed81f41159231251ecf1e5c79dai0`" +msgstr "" + +#: src/inscriptions.md:104 +msgid "" +"The part in front of the `i` is the transaction ID (`txid`) of the reveal " +"transaction. The number after the `i` defines the index (starting at 0) of " +"new inscriptions being inscribed in the reveal transaction." +msgstr "" +" `i` 的前面部分是交易ID (`txid`),在`i`之后的数字定义了新的铭文在交易总被铭刻" +"的索引的位置 (从 0 开始)" + +#: src/inscriptions.md:108 +msgid "" +"Inscriptions can either be located in different inputs, within the same " +"input or a combination of both. In any case the ordering is clear, since a " +"parser would go through the inputs consecutively and look for all " +"inscription `envelopes`." +msgstr "" +"铭文可以位于同一输入中的不同输入中,可以是同一个输入或两者的组合。在任何情况" +"下,顺序都是明确的,因为解析器将连续检查输入并查找所有铭文`信封`" + +#: src/inscriptions.md:112 +msgid "Input" +msgstr "" + +#: src/inscriptions.md:112 +msgid "Inscription Count" +msgstr "" + +#: src/inscriptions.md:112 +msgid "Indices" +msgstr "" + +#: src/inscriptions.md:114 src/inscriptions.md:117 +msgid "0" +msgstr "" + +#: src/inscriptions.md:114 src/inscriptions.md:116 +msgid "2" +msgstr "" + +#: src/inscriptions.md:114 +msgid "i0, i1" +msgstr "" + +#: src/inscriptions.md:115 src/inscriptions.md:118 +msgid "1" +msgstr "" + +#: src/inscriptions.md:115 +msgid "i2" +msgstr "" + +#: src/inscriptions.md:116 src/inscriptions.md:117 +msgid "3" +msgstr "" + +#: src/inscriptions.md:116 +msgid "i3, i4, i5" +msgstr "" + +#: src/inscriptions.md:118 +msgid "4" +msgstr "" + +#: src/inscriptions.md:118 +msgid "i6" +msgstr "" + +#: src/inscriptions.md:120 +msgid "Sandboxing" +msgstr "沙盒化" + +#: src/inscriptions.md:123 +msgid "" +"HTML and SVG inscriptions are sandboxed in order to prevent references to " +"off-chain content, thus keeping inscriptions immutable and self-contained." +msgstr "" +"HTML 和 SVG 铭文被沙箱化,以防止引用链下内容,从而保持铭文的不可变性和独立" +"性。" + +#: src/inscriptions.md:126 +msgid "" +"This is accomplished by loading HTML and SVG inscriptions inside `iframes` " +"with the `sandbox` attribute, as well as serving inscription content with " +"`Content-Security-Policy` headers." +msgstr "" +"这是通过在“iframes”中加载 HTML 和 SVG 铭文来完成的`sandbox` 属性,以及提供铭" +"文内容Content-Security-Policy”标头。" + +#: src/inscriptions/provenance.md:4 +msgid "" +"The owner of an inscription can create child inscriptions, trustlessly " +"establishing the provenance of those children on-chain as having been " +"created by the owner of the parent inscription. This can be used for " +"collections, with the children of a parent inscription being members of the " +"same collection." +msgstr "" +"铭文的所有者可以创建子铭文,在链上无需信任地建立这些子铭文的'溯源'," +"证明它们是由父铭文的所有者创建的。这可以用于集合,父铭文的子铭文会成为同一集合的成员。" + +#: src/inscriptions/provenance.md:9 +msgid "" +"Children can themselves have children, allowing for complex hierarchies. For " +"example, an artist might create an inscription representing themselves, with " +"sub inscriptions representing collections that they create, with the " +"children of those sub inscriptions being items in those collections." +msgstr "" +"子铭文自己也可以有子铭文,从而形成复杂的层级结构。" +"例如,一位艺术家可能创建一个代表自己的铭文,子铭文代表他们创建的合辑,而那些子铭文的子项就是合辑中的项目。" + +#: src/inscriptions/provenance.md:14 +msgid "Specification" +msgstr "规范" + +#: src/inscriptions/provenance.md:16 +msgid "To create a child inscription C with parent inscription P:" +msgstr "为父系铭文P创建一个子铭文C:" + +#: src/inscriptions/provenance.md:18 +msgid "Create an inscribe transaction T as usual for C." +msgstr "像通常一样为C创建常用的铭刻交易T。" + +#: src/inscriptions/provenance.md:19 +msgid "Spend the parent P in one of the inputs of T." +msgstr "在其中的一个T输入中加入父系铭文P" + +#: src/inscriptions/provenance.md:20 +msgid "" +"Include tag `3`, i.e. `OP_PUSH 3`, in C, with the value of the serialized " +"binary inscription ID of P, serialized as the 32-byte `TXID`, followed by " +"the four-byte little-endian `INDEX`, with trailing zeroes omitted." +msgstr "" +"在C中包含标签`3`,即`OP_PUSH 3`,其值为P的序列化二进制铭文ID序列化为32字节的`TXID`," +"后跟四字节的小端`INDEX`,不含末尾的零。" + +#: src/inscriptions/provenance.md:24 +msgid "" +"_NB_ The bytes of a bitcoin transaction ID are reversed in their text " +"representation, so the serialized transaction ID will be in the opposite " +"order." +msgstr "" +"_请注意_,比特币交易ID的字节在文本中的表现形式是反向的,所以序列化的交易ID会以相反的顺序呈现。" + +#: src/inscriptions/provenance.md:27 src/guides/testing.md:18 +#: src/guides/reindexing.md:15 +msgid "Example" +msgstr "示例" + +#: src/inscriptions/provenance.md:29 +msgid "" +"An example of a child inscription of " +"`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi0`:" +msgstr "" +"子铭文的一个示例 " +"`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi0`:" + +#: src/inscriptions/provenance.md:32 +msgid "" +"```\n" +"OP_FALSE\n" +"OP_IF\n" +" OP_PUSH \"ord\"\n" +" OP_PUSH 1\n" +" OP_PUSH \"text/plain;charset=utf-8\"\n" +" OP_PUSH 3\n" +" OP_PUSH " +"0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100\n" +" OP_PUSH 0\n" +" OP_PUSH \"Hello, world!\"\n" +"OP_ENDIF\n" +"```" +msgstr "" + +#: src/inscriptions/provenance.md:45 +msgid "" +"Note that the value of tag `3` is binary, not hex, and that for the child " +"inscription to be recognized as a child, " +"`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi0` must be " +"spent as one of the inputs of the inscribe transaction." +msgstr "" +"请注意,标签`3`的值是二进制的,而不是十六进制的,主要是为了让子铭文识别出来是个子铭文," +"`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi0`必须作为铭文交易的输入之一" + +#: src/inscriptions/provenance.md:50 +msgid "" +"Example encoding of inscription ID " +"`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi255`:" +msgstr "" +"铭文ID的编码示例 " +"`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi255`:" + +#: src/inscriptions/provenance.md:53 +msgid "" +"```\n" +"OP_FALSE\n" +"OP_IF\n" +" …\n" +" OP_PUSH 3\n" +" OP_PUSH " +"0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100ff\n" +" …\n" +"OP_ENDIF\n" +"```" +msgstr "" + +#: src/inscriptions/provenance.md:63 +msgid "" +"And of inscription ID " +"`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi256`:" +msgstr "" +"以及铭文 ID " +"`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi256`:" + +#: src/inscriptions/provenance.md:65 +msgid "" +"```\n" +"OP_FALSE\n" +"OP_IF\n" +" …\n" +" OP_PUSH 3\n" +" OP_PUSH " +"0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a090807060504030201000001\n" +" …\n" +"OP_ENDIF\n" +"```" +msgstr "" + +#: src/inscriptions/provenance.md:75 +msgid "Notes" +msgstr "注释" + +#: src/inscriptions/provenance.md:77 +msgid "" +"The tag `3` is used because it is the first available odd tag. Unrecognized " +"odd tags do not make an inscription unbound, so child inscriptions would be " +"recognized and tracked by old versions of `ord`." +msgstr "" +"标签 `3` 被使用是因为它是第一个可用的奇数标签。" +"未识别的奇数标签不会使铭文无法进行绑定,因此,旧版本的ord仍可以识别和追踪子铭文。" + +#: src/inscriptions/provenance.md:81 +msgid "" +"A collection can be closed by burning the collection's parent inscription, " +"which guarantees that no more items in the collection can be issued." +msgstr "" +"通过销毁集合的父铭文,可以关闭一个集合,这保证了该集合中不能再发行更多的项目。 " + +#: src/inscriptions/recursion.md:4 +msgid "" +"An important exception to [sandboxing](../inscriptions.md#sandboxing) is " +"recursion: access to `ord`'s `/content` endpoint is permitted, allowing " +"inscriptions to access the content of other inscriptions by requesting `/" +"content/`." +msgstr "" +"[沙盒化](../inscriptions.md#sandboxing)的一个重要例外是递归:访问“ord”的“/" +"content”允许端点,允许铭文访问其他端点的内容通过请求 `/content/" +"` 来获取铭文。" + +#: src/inscriptions/recursion.md:9 +msgid "This has a number of interesting use-cases:" +msgstr "这有许多有趣的用例:" + +#: src/inscriptions/recursion.md:11 +msgid "Remixing the content of existing inscriptions." +msgstr "重新混合现有铭文的内容。" + +#: src/inscriptions/recursion.md:13 +msgid "" +"Publishing snippets of code, images, audio, or stylesheets as shared public " +"resources." +msgstr "将代码、图像、音频或样式表片段发布为公共的共享资源。" + +#: src/inscriptions/recursion.md:16 +msgid "" +"Generative art collections where an algorithm is inscribed as JavaScript, " +"and instantiated from multiple inscriptions with unique seeds." +msgstr "" +"生成艺术收藏,其中算法使用JavaScript刻写,并从具有独特种子的多个铭文中实例" +"化。" + +#: src/inscriptions/recursion.md:19 +msgid "" +"Generative profile picture collections where accessories and attributes are " +"inscribed as individual images, or in a shared texture atlas, and then " +"combined, collage-style, in unique combinations in multiple inscriptions." +msgstr "" +"生成个人资料图片集,其中包含配件和属性刻录为单独的图像,或刻录在共享纹理图集" +"中,然后组合,拼贴风格,在多个铭文中以独特的组合。" + +#: src/inscriptions/recursion.md:23 +msgid "A few other endpoints that inscriptions may access are the following:" +msgstr "铭文可以访问的其他几个端点如下:" + +#: src/inscriptions/recursion.md:25 +msgid "`/blockheight`: latest block height." +msgstr "`/blockheight`:最新区块高度。" + +#: src/inscriptions/recursion.md:26 +msgid "`/blockhash`: latest block hash." +msgstr "`/blockhash`:最新的块哈希。" + +#: src/inscriptions/recursion.md:27 +msgid "`/blockhash/`: block hash at given block height." +msgstr "`/blockhash/`:给定块高度的块哈希。" + +#: src/inscriptions/recursion.md:28 +msgid "`/blocktime`: UNIX time stamp of latest block." +msgstr "`/blocktime`:最新块的 UNIX 时间戳。" + +#: src/faq.md:1 +msgid "Ordinal Theory FAQ" +msgstr "序数理论常见问题" + +#: src/faq.md:4 +msgid "What is ordinal theory?" +msgstr "什么是序数理论" + +#: src/faq.md:7 +msgid "" +"Ordinal theory is a protocol for assigning serial numbers to satoshis, the " +"smallest subdivision of a bitcoin, and tracking those satoshis as they are " +"spent by transactions." +msgstr "" +"序数理论是一种为聪(satoshi,以下写作“聪”,比特币的最小单位)分配序列号的协" +"议,并在交易中跟踪这些聪。" + +#: src/faq.md:11 +msgid "" +"These serial numbers are large numbers, like this 804766073970493. Every " +"satoshi, which is ¹⁄₁₀₀₀₀₀₀₀₀ of a bitcoin, has an ordinal number." +msgstr "" +"这些序号都是很大的数字,比如,804766073970493. 每一个聪satoshi, 也都是比特币" +"的 ¹⁄₁₀₀₀₀₀₀₀₀ 都有一个序数号号码" + +#: src/faq.md:14 +msgid "" +"Does ordinal theory require a side chain, a separate token, or changes to " +"Bitcoin?" +msgstr "序数理论是否需要一个侧链,一个单独的代币,或对比特币做出改变?" + +#: src/faq.md:17 +msgid "" +"Nope! Ordinal theory works right now, without a side chain, and the only " +"token needed is bitcoin itself." +msgstr "" +"完全不需要!序数理论现在有效可用,没有侧链,唯一需要的代币是比特币本身。" + +#: src/faq.md:20 +msgid "What is ordinal theory good for?" +msgstr "序数理论有什么用?" + +#: src/faq.md:23 +msgid "" +"Collecting, trading, and scheming. Ordinal theory assigns identities to " +"individual satoshis, allowing them to be individually tracked and traded, as " +"curios and for numismatic value." +msgstr "" +"收集、交易和策划。序数理论将身份分配给单个聪,允许它们作为古玩和钱币价值被单" +"独跟踪和交易。" + +#: src/faq.md:27 +msgid "" +"Ordinal theory also enables inscriptions, a protocol for attaching arbitrary " +"content to individual satoshis, turning them into bitcoin-native digital " +"artifacts." +msgstr "" +"序数理论还赋能铭文,这是一种将任意内容附加到单个聪的协议,将它们变成比特币原" +"生的数字文物。" + +#: src/faq.md:31 +msgid "How does ordinal theory work?" +msgstr "序数理论是如何运作的?" + +#: src/faq.md:34 +msgid "" +"Ordinal numbers are assigned to satoshis in the order in which they are " +"mined. The first satoshi in the first block has ordinal number 0, the second " +"has ordinal number 1, and the last satoshi of the first block has ordinal " +"number 4,999,999,999." +msgstr "" +"序数是按照挖矿的顺序分配给聪的。第一个区块的首聪序数为0,第二个聪的序数为1," +"第一个区块的最后一个聪的序数为4,999,999,999。" + +#: src/faq.md:39 +msgid "" +"Satoshis live in outputs, but transactions destroy outputs and create new " +"ones, so ordinal theory uses an algorithm to determine how satoshis hop from " +"the inputs of a transaction to its outputs." +msgstr "" +"聪存在于输出中,但交易会破坏输出并创建新的输出,因此序数理论使用一种算法来确" +"定聪如何从交易的输入跳到其输出" + +#: src/faq.md:43 +msgid "Fortunately, that algorithm is very simple." +msgstr "幸运的是,这个算法非常简单。" + +#: src/faq.md:45 +msgid "" +"Satoshis transfer in first-in-first-out order. Think of the inputs to a " +"transaction as being a list of satoshis, and the outputs as a list of slots, " +"waiting to receive a satoshi. To assign input satoshis to slots, go through " +"each satoshi in the inputs in order, and assign each to the first available " +"slot in the outputs." +msgstr "" +"聪按照先进先出的顺序进行转账。 将交易的输入视为聪列表,将输出视为插槽slot列" +"表,等待接收聪。 要将输入聪分配给插槽,按顺序检查输入中的每个聪,并将每个聪分" +"配给输出中的第一个可用插槽。" + +#: src/faq.md:51 +msgid "" +"Let's imagine a transaction with three inputs and two outputs. The inputs " +"are on the left of the arrow and the outputs are on the right, all labeled " +"with their values:" +msgstr "" +"让我们想象一个具有三个输入和两个输出的交易。 输入在箭头的左边,输出在右边,都" +"标有它们的值:" + +#: src/faq.md:55 +msgid "" +"```\n" +"[2] [1] [3] → [4] [2]\n" +"```" +msgstr "" + +#: src/faq.md:57 +msgid "" +"Now let's label the same transaction with the ordinal numbers of the " +"satoshis that each input contains, and question marks for each output slot. " +"Ordinal numbers are large, so let's use letters to represent them:" +msgstr "" +"现在,我们用每个输入包含的聪序数标记同一笔交易,并为每个输出插槽标记问号。 序" +"数号很大,所以我们用字母来表示它们:" + +#: src/faq.md:61 +msgid "" +"```\n" +"[a b] [c] [d e f] → [? ? ? ?] [? ?]\n" +"```" +msgstr "" + +#: src/faq.md:63 +msgid "" +"To figure out which satoshi goes to which output, go through the input " +"satoshis in order and assign each to a question mark:" +msgstr "要弄清楚哪个聪到哪个输出,请按顺序检查输入聪并将每个聪分配给一个问号:" + +#: src/faq.md:66 +msgid "" +"```\n" +"[a b] [c] [d e f] → [a b c d] [e f]\n" +"```" +msgstr "" + +#: src/faq.md:68 +msgid "" +"What about fees, you might ask? Good question! Let's imagine the same " +"transaction, this time with a two satoshi fee. Transactions with fees send " +"more satoshis in the inputs than are received by the outputs, so to make our " +"transaction into one that pays fees, we'll remove the second output:" +msgstr "" +"你可能会问交易费用呢? 好问题! 让我们想象一下同一笔交易,这次是两个聪的费" +"用。收费交易在输入中发送的聪 多于输出接收的聪,因此为了使我们的交易成为支付费" +"用的交易,我们将删除第二个输出:" + +#: src/faq.md:73 +msgid "" +"```\n" +"[2] [1] [3] → [4]\n" +"```" +msgstr "" + +#: src/faq.md:75 +msgid "The satoshis " +msgstr "聪" + +#: src/faq.md:75 +msgid "e" +msgstr "" + +#: src/faq.md:75 +msgid " and " +msgstr " 和 " + +#: src/faq.md:75 +msgid "f" +msgstr "" + +#: src/faq.md:75 +msgid " now have nowhere to go in the outputs:" +msgstr "现在在输出中无处可去" + +#: src/faq.md:78 +msgid "" +"```\n" +"[a b] [c] [d e f] → [a b c d]\n" +"```" +msgstr "" +"```\n" +"[a b] [c] [d e f] → [a b c d]\n" +"```" + +#: src/faq.md:80 +msgid "" +"So they go to the miner who mined the block as fees. [The BIP](https://" +"github.com/ordinals/ord/blob/master/bip.mediawiki) has the details, but in " +"short, fees paid by transactions are treated as extra inputs to the coinbase " +"transaction, and are ordered how their corresponding transactions are " +"ordered in the block. The coinbase transaction of the block might look like " +"this:" +msgstr "" +"所以他们作为“费用”去到挖这个区块的矿工那里。[The BIP](https://github.com/" +"ordinals/ord/blob/master/bip.mediawiki) 有更详细的描述,但简而言之,交易支付的" +"费用被视为对Coinbase交易的额外输入,并按照其对应的交易在区块中的顺序进行排" +"序。该区块的Coinbase交易可能是这样的:" + +#: src/faq.md:87 +msgid "" +"```\n" +"[SUBSIDY] [e f] → [SUBSIDY e f]\n" +"```" +msgstr "" + +#: src/faq.md:89 +msgid "Where can I find the nitty-gritty details?" +msgstr "我在哪里可以找到这些详细信息" + +#: src/faq.md:92 +msgid "[The BIP!](https://github.com/ordinals/ord/blob/master/bip.mediawiki)" +msgstr "" + +#: src/faq.md:94 +msgid "" +"Why are sat inscriptions called \"digital artifacts\" instead of \"NFTs\"?" +msgstr "为什么聪的铭文被称为“数字文物”而不是“NFT”?" + +#: src/faq.md:97 +msgid "" +"An inscription is an NFT, but the term \"digital artifact\" is used instead, " +"because it's simple, suggestive, and familiar." +msgstr "" +"铭文也是一种NFT,但使用术语“数字文物”代替,因为它简单、有启发性且熟悉。" + +#: src/faq.md:100 +msgid "" +"The phrase \"digital artifact\" is highly suggestive, even to someone who " +"has never heard the term before. In comparison, NFT is an acronym, and " +"doesn't provide any indication of what it means if you haven't heard the " +"term before." +msgstr "" +"\"数字文物\"(数字工件,数字人工制品)这些词具有很强的暗示性,即使对以前从未" +"听说过这个词的人来说也是如此相比之下,NFT是一个首字母缩略词,如果你以前没有听" +"过这个术语,它就无法说明它的意思。" + +#: src/faq.md:104 +msgid "" +"Additionally, \"NFT\" feels like financial terminology, and the both word " +"\"fungible\" and sense of the word \"token\" as used in \"NFT\" is uncommon " +"outside of financial contexts." +msgstr "" +"此外,\"NFT\"感觉像是金融术语,\"NFT\"中使用的\"同质化\"一词和\"代币\"一词的" +"含义在金融语境之外并不常见。" + +#: src/faq.md:108 +msgid "How do sat inscriptions compare to…" +msgstr "聪上的铭文与其他的对比" + +#: src/faq.md:111 +msgid "Ethereum NFTs?" +msgstr "以太坊NFT" + +#: src/faq.md:113 +msgid "_Inscriptions are always immutable._" +msgstr "_铭文永恒不变_" + +#: src/faq.md:115 +msgid "" +"There is simply no way to for the creator of an inscription, or the owner of " +"an inscription, to modify it after it has been created." +msgstr "铭文的创建者或铭文的所有者根本无法在创建铭文后对其进行修改。" + +#: src/faq.md:118 +msgid "" +"Ethereum NFTs _can_ be immutable, but many are not, and can be changed or " +"deleted by the NFT contract owner." +msgstr "" +"以太坊NFTs_可以_是不可更改的,但很多都不是,且是可以由 NFT 合约所有者更改或删" +"除。" + +#: src/faq.md:121 +msgid "" +"In order to make sure that a particular Ethereum NFT is immutable, the " +"contract code must be audited, which requires detailed knowledge of the EVM " +"and Solidity semantics." +msgstr "" +"为了确保特定的以太坊 NFT 是不可变的,必须审计合约代码,这需要详细了解 EVM 和 " +"Solidity 语义。" + +#: src/faq.md:125 +msgid "" +"It is very hard for a non-technical user to determine whether or not a given " +"Ethereum NFT is mutable or immutable, and Ethereum NFT platforms make no " +"effort to distinguish whether an NFT is mutable or immutable, and whether " +"the contract source code is available and has been audited." +msgstr "" +"对于非技术用户来说,很难确定某以太坊NFT是否可变,以太坊NFT平台也没有努力去区" +"分NFT是否可变,以及合约源代码是否可用并已经过审计。" + +#: src/faq.md:130 +msgid "_Inscription content is always on-chain._" +msgstr "_铭文内容永久链上_" + +#: src/faq.md:132 +msgid "" +"There is no way for an inscription to refer to off-chain content. This makes " +"inscriptions more durable, because content cannot be lost, and scarcer, " +"because inscription creators must pay fees proportional to the size of the " +"content." +msgstr "" +"铭文无法引用链下内容。因为内容不会丢失,这使得铭文更加持久,也使得铭文创作者" +"必须支付与内容大小成比例的费用。" + +#: src/faq.md:136 +msgid "" +"Some Ethereum NFT content is on-chain, but much is off-chain, and is stored " +"on platforms like IPFS or Arweave, or on traditional, fully centralized web " +"servers. Content on IPFS is not guaranteed to continue to be available, and " +"some NFT content stored on IPFS has already been lost. Platforms like " +"Arweave rely on weak economic assumptions, and will likely fail " +"catastrophically when these economic assumptions are no longer met. " +"Centralized web servers may disappear at any time." +msgstr "" +"一些以太坊 NFT 内容在链上的,但大部分内容在链下,存储在 IPFS 或 Arweave 等平" +"台上,或传统完全中心化的网络服务器上。IPFS上的内容不保证继续可用,一些存储在" +"IPFS上的NFT内容已经丢失。像Arweave这样的平台依赖于薄弱的经济假设,当这些经济" +"假设不再满足时,它们很可能会发生灾难性的失败。中心化的网络服务器随时可能消" +"失。" + +#: src/faq.md:144 +msgid "" +"It is very hard for a non-technical user to determine where the content of a " +"given Ethereum NFT is stored." +msgstr "对于非技术用户来说,很难确定某以太坊NFT的内容存储在哪里。" + +#: src/faq.md:147 +msgid "_Inscriptions are much simpler._" +msgstr "_铭文要简单得多_" + +#: src/faq.md:149 +msgid "" +"Ethereum NFTs depend on the Ethereum network and virtual machine, which are " +"highly complex, constantly changing, and which introduce changes via " +"backwards-incompatible hard forks." +msgstr "" +"以太坊 NFT 依赖于以太坊网络和虚拟机,它们高度复杂、不断变化,并通过向后不兼容" +"的硬分叉引入变化。" + +#: src/faq.md:153 +msgid "" +"Inscriptions, on the other hand, depend on the Bitcoin blockchain, which is " +"relatively simple and conservative, and which introduces changes via " +"backwards-compatible soft forks." +msgstr "" +"相反,铭文依赖于比特币区块链,它相对简单和保守,并通过向后兼容的软分叉引入变" +"化。" + +#: src/faq.md:157 +msgid "_Inscriptions are more secure._" +msgstr "_铭文更安全_" + +#: src/faq.md:159 +msgid "" +"Inscriptions inherit Bitcoin's transaction model, which allow a user to see " +"exactly which inscriptions are being transferred by a transaction before " +"they sign it. Inscriptions can be offered for sale using partially signed " +"transactions, which don't require allowing a third party, such as an " +"exchange or marketplace, to transfer them on the user's behalf." +msgstr "" +"铭文继承了比特币的交易模型,允许用户在签名之前准确地看到交易中转移了哪些铭" +"文。铭文可以使用部分签名交易进行销售,不需要允许第三方(如交易所或市场)代表" +"用户转让它们。" + +#: src/faq.md:165 +msgid "" +"By comparison, Ethereum NFTs are plagued with end-user security " +"vulnerabilities. It is commonplace to blind-sign transactions, grant third-" +"party apps unlimited permissions over a user's NFTs, and interact with " +"complex and unpredictable smart contracts. This creates a minefield of " +"hazards for Ethereum NFT users which are simply not a concern for ordinal " +"theorists." +msgstr "" +"相比之下,以太坊NFT受到终端用户安全漏洞的困扰。盲签交易、授予第三方应用程序对" +"用户NFT的无限权限,以及与复杂且不可预测的智能合约交互都是司空见惯的事情。这为" +"以太坊 NFT 用户制造了一个危险雷区,而这些对于序号理论家来说,根本毋需操心。" + +#: src/faq.md:171 +msgid "_Inscriptions are scarcer._" +msgstr "_铭文更加稀缺_" + +#: src/faq.md:173 +msgid "" +"Inscriptions require bitcoin to mint, transfer, and store. This seems like a " +"downside on the surface, but the raison d'etre of digital artifacts is to be " +"scarce and thus valuable." +msgstr "" +"铭文需要比特币来铸造、转移和存储。从表面上看,这似乎是一个阻碍,但数字文物存" +"在的价值目的正是稀缺。" + +#: src/faq.md:177 +msgid "" +"Ethereum NFTs, on the other hand, can be minted in virtually unlimited " +"qualities with a single transaction, making them inherently less scarce, and " +"thus, potentially less valuable." +msgstr "" +"另一方面,以太坊 NFT 可以通过单笔交易以几乎无限的质量进行铸造,使它们本质上不" +"那么稀缺,因此可能没太多价值。" + +#: src/faq.md:181 +msgid "_Inscriptions do not pretend to support on-chain royalties._" +msgstr "_铭文不会假装支持链上版税_" + +#: src/faq.md:183 +msgid "" +"On-chain royalties are a good idea in theory but not in practice. Royalty " +"payment cannot be enforced on-chain without complex and invasive " +"restrictions. The Ethereum NFT ecosystem is currently grappling with " +"confusion around royalties, and is collectively coming to grips with the " +"reality that on-chain royalties, which were messaged to artists as an " +"advantage of NFTs, are not possible, while platforms race to the bottom and " +"remove royalty support." +msgstr "" +"“链上版税”理论上是个好主意,但在实践中却行不通。 如果没有复杂和侵入性的限制," +"就不能在链上强制执行版税支付。以太坊 NFT 生态系统正在努力地解决围绕版税的难" +"题,并且也在共同面对一个现实:即向艺术家传达NFT 链上版税这个利器其实是不可行" +"的,与此同时,多个平台则在竞相删除对版税的支持。" + +#: src/faq.md:190 +msgid "" +"Inscriptions avoid this situation entirely by making no false promises of " +"supporting royalties on-chain, thus avoiding the confusion, chaos, and " +"negativity of the Ethereum NFT situation." +msgstr "" +"铭文完全避免了这种情况,不虚假地承诺支持链上版税,从而避免了和以太坊NFT一样混" +"乱又消极的状况。" + +#: src/faq.md:194 +msgid "_Inscriptions unlock new markets._" +msgstr "_铭文开启了新的市场_" + +#: src/faq.md:196 +msgid "" +"Bitcoin's market capitalization and liquidity are greater than Ethereum's by " +"a large margin. Much of this liquidity is not available to Ethereum NFTs, " +"since many Bitcoiners prefer not to interact with the Ethereum ecosystem due " +"to concerns related to simplicity, security, and decentralization." +msgstr "" +"比特币的市值和流动性都大大超越以太坊。以太坊NFT无法获得此类大部分的流动性,因" +"为许多比特币使用者出于简单性、安全性和去中心化的考虑,不愿意与以太坊生态系统" +"进行交互。" + +#: src/faq.md:201 +msgid "" +"Such Bitcoiners may be more interested in inscriptions than Ethereum NFTs, " +"unlocking new classes of collector." +msgstr "" +"与以太坊 NFT 相比,此类比特币拥护者可能对铭文更感兴趣,从而解锁了新的类别的收" +"藏家。" + +#: src/faq.md:204 +msgid "_Inscriptions have a richer data model._" +msgstr "_铭文有更丰富的数据模型_" + +#: src/faq.md:206 +msgid "" +"Inscriptions consist of a content type, also known as a MIME type, and " +"content, which is an arbitrary byte string. This is the same data model used " +"by the web, and allows inscription content to evolve with the web, and come " +"to support any kind of content supported by web browsers, without requiring " +"changes to the underlying protocol." +msgstr "" +"铭文由内容类型(也称为MIME类型)和内容(任意字节字符串)组成。这相同于 web 使" +"用的数据模型,允许铭文内容随着 web 的发展而发展,并支持 web 浏览器支持的任何" +"类型的内容,而无需更改底层协议。" + +#: src/faq.md:212 +msgid "RGB and Taro assets?" +msgstr "RGB 和 Taro 资产?" + +#: src/faq.md:214 +msgid "" +"RGB and Taro are both second-layer asset protocols built on Bitcoin. " +"Compared to inscriptions, they are much more complicated, but much more " +"featureful." +msgstr "" +"RGB 和 Taro 都是建立在比特币之上的二层资产协议。 与铭文相比,它们要复杂得多," +"但也更有特色。" + +#: src/faq.md:217 +msgid "" +"Ordinal theory has been designed from the ground up for digital artifacts, " +"whereas the primary use-case of RGB and Taro are fungible tokens, so the " +"user experience for inscriptions is likely to be simpler and more polished " +"than the user experience for RGB and Taro NFTs." +msgstr "" +"序号理论是为数字人工制品而设计的,而 RGB 和 Taro 的主要用例是可替代代币,因此" +"铭文的用户体验可能比 RGB 和 Taro NFT 的用户体验更简单、更完善 。" + +#: src/faq.md:222 +msgid "" +"RGB and Taro both store content off-chain, which requires additional " +"infrastructure, and which may be lost. By contrast, inscription content is " +"stored on-chain, and cannot be lost." +msgstr "" +"RGB 和 Taro 都在链下存储内容,这需要额外的基础设施,而且可能会丢失。相比之" +"下,铭文内容存储在链上,不会丢失。" + +#: src/faq.md:226 +msgid "" +"Ordinal theory, RGB, and Taro are all very early, so this is speculation, " +"but ordinal theory's focus may give it the edge in terms of features for " +"digital artifacts, including a better content model, and features like " +"globally unique symbols." +msgstr "" +"序数理论、RGB和Taro都是非常早期的,所以这只是推测,但序号理论的重点可能使其在" +"数字艺术品的特性方面具有优势,包括更好的内容模型,以及像全球唯一符号这样的特" +"性。" + +#: src/faq.md:231 +msgid "Counterparty assets?" +msgstr "Counterparty资产" + +#: src/faq.md:233 +msgid "" +"Counterparty has its own token, XCP, which is required for some " +"functionality, which makes most bitcoiners regard it as an altcoin, and not " +"an extension or second layer for bitcoin." +msgstr "" +"Counterparty 有自己的代币 XCP,它是某些功能所必需的,这使得大多数比特币持有者" +"将其视为山寨币,而不是比特币的扩展或第二层。" + +#: src/faq.md:237 +msgid "" +"Ordinal theory has been designed from the ground up for digital artifacts, " +"whereas Counterparty was primarily designed for financial token issuance." +msgstr "" +"序数理论是为数字文物从头开始设计的,而Counterparty主要是为金融代币发行而设计" +"的。" + +#: src/faq.md:240 +msgid "Inscriptions for…" +msgstr "铭文可以为..." + +#: src/faq.md:243 +msgid "Artists" +msgstr "艺术家" + +#: src/faq.md:245 +msgid "" +"_Inscriptions are on Bitcoin._ Bitcoin is the digital currency with the " +"highest status and greatest chance of long-term survival. If you want to " +"guarantee that your art survives into the future, there is no better way to " +"publish it than as inscriptions." +msgstr "" +"_铭文在比特币上_ 比特币是目前地位最高、长期生存机会最大的数字货币。 如果你想" +"保证你的艺术作品能流传到未来,没有比铭文更好的发布方式了。" + +#: src/faq.md:250 +msgid "" +"_Cheaper on-chain storage._ At $20,000 per BTC and the minimum relay fee of " +"1 satoshi per vbyte, publishing inscription content costs $50 per 1 million " +"bytes." +msgstr "" +"_链上存储更便宜_按每个比特币2万美元和每 vbyte 1聪的最低中继费用计算,发布铭文" +"内容的成本为每100万字节50美元。" + +#: src/faq.md:254 +msgid "" +"_Inscriptions are early!_ Inscriptions are still in development, and have " +"not yet launched on mainnet. This gives you an opportunity to be an early " +"adopter, and explore the medium as it evolves." +msgstr "" +"_铭文还处于项目早期_ 铭文仍在开发中,尚未在主网上发布(建议更新)。 这使您有" +"机会成为早期采用者,并随着媒体的发展探索它。" + +#: src/faq.md:258 +msgid "" +"_Inscriptions are simple._ Inscriptions do not require writing or " +"understanding smart contracts." +msgstr "_铭文很简单_ 铭文不需要你编写或理解智能合约。" + +#: src/faq.md:261 +msgid "" +"_Inscriptions unlock new liquidity._ Inscriptions are more accessible and " +"appealing to bitcoin holders, unlocking an entirely new class of collector." +msgstr "" +"_铭文解锁新的流动性_对于比特币持有者来说,铭文更容易获得,也更有吸引力,从而" +"带来全新的收藏者。" + +#: src/faq.md:264 +msgid "" +"_Inscriptions are designed for digital artifacts._ Inscriptions are designed " +"from the ground up to support NFTs, and feature a better data model, and " +"features like globally unique symbols and enhanced provenance." +msgstr "" +"_铭文是为数字文物设计_ 全新设计的铭文是为了支持 NFT,并具有更好的数据模型,以" +"及全球独特符号和增强来源等功能。" + +#: src/faq.md:268 +msgid "" +"_Inscriptions do not support on-chain royalties._ This is negative, but only " +"depending on how you look at it. On-chain royalties have been a boon for " +"creators, but have also created a huge amount of confusion in the Ethereum " +"NFT ecosystem. The ecosystem now grapples with this issue, and is engaged in " +"a race to the bottom, towards a royalties-optional future. Inscriptions have " +"no support for on-chain royalties, because they are technically infeasible. " +"If you choose to create inscriptions, there are many ways you can work " +"around this limitation: withhold a portion of your inscriptions for future " +"sale, to benefit from future appreciation, or perhaps offer perks for users " +"who respect optional royalties." +msgstr "" +"_铭文不鼓励链上版税_ 这可能不是个好消息,但也取决于你如何看待它。链上版税一直" +"是创作者的福音,但也在以太坊 NFT生态系统中造成了巨大的混乱。以太坊现在正努力" +"解决这个问题,也是一场逐底竞赛,以实现一个“可选版税”的未来。铭文不支持链上版" +"税,因为它们在技术上不可行。如果您选择创建铭文,有许多方法可以绕过这个限制:" +"保留一部分铭文供未来售卖,以受益于未来的升值,或者为尊重可选版税的用户提供额" +"外津贴。" + +#: src/faq.md:279 +msgid "Collectors" +msgstr "收藏者" + +#: src/faq.md:281 +msgid "" +"_Inscriptions are simple, clear, and have no surprises._ They are always " +"immutable and on-chain, with no special due diligence required." +msgstr "" +"_铭文很简单_,清晰并无意外* 它们始终是不可变的并且在链上,不需要特殊的尽职调" +"查。" + +#: src/faq.md:284 +msgid "" +"_Inscriptions are on Bitcoin._ You can verify the location and properties of " +"inscriptions easily with Bitcoin full node that you control." +msgstr "" +"_铭文在比特币上_ 您可以使用您控制的比特币全节点轻松验证铭文的位置和属性。" + +#: src/faq.md:287 +msgid "Bitcoiners" +msgstr "比特币信仰者" + +#: src/faq.md:289 +msgid "" +"Let me begin this section by saying: the most important thing that the " +"Bitcoin network does is decentralize money. All other use-cases are " +"secondary, including ordinal theory. The developers of ordinal theory " +"understand and acknowledge this, and believe that ordinal theory helps, at " +"least in a small way, Bitcoin's primary mission." +msgstr "" +"让我在开头说明一下:比特币网络所做的最重要的事情是货币去中心化。所有其他用例" +"都是次要的,包括序数理论。序数理论的开发者理解并承认这一点,并相信序数理论至" +"少在很小的程度上有助于比特币的主要任务。" + +#: src/faq.md:295 +msgid "" +"Unlike many other things in the altcoin space, digital artifacts have merit. " +"There are, of course, a great deal of NFTs that are ugly, stupid, and " +"fraudulent. However, there are many that are fantastically creative, and " +"creating and collecting art has been a part of the human story since its " +"inception, and predates even trade and money, which are also ancient " +"technologies." +msgstr "" +"与其他山寨币领域的事物不同,数字文物有其优点。当然,有大量的NFT是丑陋、愚蠢和" +"存在欺骗性的。然而,还是有很多有奇妙的创意,创造和收藏艺术本来就是人类故事的" +"一部分,甚至早于贸易和金钱这些同样古老的技术。" + +#: src/faq.md:302 +msgid "" +"Bitcoin provides an amazing platform for creating and collecting digital " +"artifacts in a secure, decentralized way, that protects users and artists in " +"the same way that it provides an amazing platform for sending and receiving " +"value, and for all the same reasons." +msgstr "" +"比特币提供了一个精彩的平台,以一种安全、去中心化的方式创造、收集数字文物,也" +"以同样的方式保护了用户和艺术家,更同时提供了一个优秀的平台来发送和接收价值。" + +#: src/faq.md:307 +msgid "" +"Ordinals and inscriptions increase demand for Bitcoin block space, which " +"increase Bitcoin's security budget, which is vital for safeguarding " +"Bitcoin's transition to a fee-dependent security model, as the block subsidy " +"is halved into insignificance." +msgstr "" +"序数和铭文增加了对比特币区块空间的需求,这也增加了比特币的安全预算。这对于保" +"障比特币向费用依赖型的安全模式过渡至关重要,因为区块补贴减半已少得微不足道。" + +#: src/faq.md:312 +msgid "" +"Inscription content is stored on-chain, and thus the demand for block space " +"for use in inscriptions is unlimited. This creates a buyer of last resort " +"for _all_ Bitcoin block space. This will help support a robust fee market, " +"which ensures that Bitcoin remains secure." +msgstr "" +"铭文内容存储在链上,因此对用于铭文区块空间的需求是无限的。这就为所有比特币区" +"块空间创造了一个最后买家。这将有助于支持一个强大的收费市场,从而确保比特币一" +"直安全。" + +#: src/faq.md:317 +msgid "" +"Inscriptions also counter the narrative that Bitcoin cannot be extended or " +"used for new use-cases. If you follow projects like DLCs, Fedimint, " +"Lightning, Taro, and RGB, you know that this narrative is false, but " +"inscriptions provide a counter argument which is easy to understand, and " +"which targets a popular and proven use case, NFTs, which makes it highly " +"legible." +msgstr "" +"铭文还反驳了比特币不能扩展或用于新用例的说法。 如果你关注 DLC、Fedimint、" +"Lightning、Taro 和 RGB 等项目,你就会知道这种说法是错误的。铭文提供了一个易于" +"理解的反论点,并且针对一个流行且经过验证的用例:NFT,这使得它非常易理解。" + +#: src/faq.md:323 +msgid "" +"If inscriptions prove, as the authors hope, to be highly sought after " +"digital artifacts with a rich history, they will serve as a powerful hook " +"for Bitcoin adoption: come for the fun, rich art, stay for the decentralized " +"digital money." +msgstr "" +"如果像作者所希望的那样,铭文被证明是具有丰富历史的数字文物,并且受到高度追" +"捧,它们将会成为比特币采用的强大吸引力:被乐趣、丰富的艺术吸引而来,也为去中" +"心化的数字货币而愿意留下来。" + +#: src/faq.md:327 +msgid "" +"Inscriptions are an extremely benign source of demand for block space. " +"Unlike, for example, stablecoins, which potentially give large stablecoin " +"issuers influence over the future of Bitcoin development, or DeFi, which " +"might centralize mining by introducing opportunities for MEV, digital art " +"and collectables on Bitcoin, are unlikely to produce individual entities " +"with enough power to corrupt Bitcoin. Art is decentralized." +msgstr "" +"铭文是区块空间需求的一个极其良性的来源,不像稳定币,可能会让大型发行人对比特" +"币的未来发展产生影响;也不像DeFi,可能通过在比特币上引入MEV、数字艺术和收藏品" +"的机会来集中挖矿。艺术是去中心化的,任何实体都不可能运用权力去破坏得了比特" +"币。" + +#: src/faq.md:334 +msgid "" +"Inscription users and service providers are incentivized to run Bitcoin full " +"nodes, to publish and track inscriptions, and thus throw their economic " +"weight behind the honest chain." +msgstr "" +"铭文用户和服务提供商被激励运行比特币全节点,以及发布跟踪铭文,从而将他们的经" +"济权重投向诚实的链。" + +#: src/faq.md:338 +msgid "" +"Ordinal theory and inscriptions do not meaningfully affect Bitcoin's " +"fungibility. Bitcoin users can ignore both and be unaffected." +msgstr "" +"序数理论和铭文不会对比特币的可替代性产生重大影响。比特币用户即使忽略这两者也" +"不会受到影响。" + +#: src/faq.md:341 +msgid "" +"We hope that ordinal theory strengthens and enriches bitcoin, and gives it " +"another dimension of appeal and functionality, enabling it more effectively " +"serve its primary use case as humanity's decentralized store of value." +msgstr "" +"我们希望序数理论能够加强、丰富比特币,并赋予它另一个维度的吸引力和功能,使其" +"能够更有效地服务于其作为人类去中心化价值存储的主要用例。" + +#: src/contributing.md:1 +msgid "Contributing to `ord`" +msgstr "如何为`ord`做贡献" + +#: src/contributing.md:4 +msgid "Suggested Steps" +msgstr "建议的步骤" + +#: src/contributing.md:7 +msgid "Find an issue you want to work on." +msgstr "找到一个你想解决的问题。" + +#: src/contributing.md:8 +msgid "" +"Figure out what would be a good first step towards resolving the issue. This " +"could be in the form of code, research, a proposal, or suggesting that it be " +"closed, if it's out of date or not a good idea in the first place." +msgstr "" +"弄清楚什么是解决这个问题的良好的第一步,这可以是代码,研究和提案的形式,或者" +"是如果它已经过时,或者一开始就不是一个好主意,则建议将其关闭。" + +#: src/contributing.md:11 +msgid "" +"Comment on the issue with an outline of your suggested first step, and " +"asking for feedback. Of course, you can dive in and start writing code or " +"tests immediately, but this avoids potentially wasted effort, if the issue " +"is out of date, not clearly specified, blocked on something else, or " +"otherwise not ready to implement." +msgstr "" +"概述您所建议的第一步,对问题进行评论,并征求反馈。当然你也可以立即投入并开始" +"编写代码或者测试。但是如果问题已经过时、未明确制定、因其他原因受阻或者未准备" +"好实施,这一步可以避免潜在的精力浪费。" + +#: src/contributing.md:16 +msgid "" +"If the issue requires a code change or bugfix, open a draft PR with tests, " +"and ask for feedback. This makes sure that everyone is on the same page " +"about what needs to be done, or what the first step in solving the issue " +"should be. Also, since tests are required, writing the tests first makes it " +"easy to confirm that the change can be tested easily." +msgstr "" +"如果问题需要更改代码或者修复错误,请打开测试PR草稿,并征求反馈意见。这将保证" +"每一个人会同步知道需要做一些什么,或者解决这个问题的第一步是什么。同样,调试" +"是必须的,所以首先写出测试草案并确认更新是可以被容易的测试的。" + +#: src/contributing.md:21 +msgid "" +"Mash the keyboard randomly until the tests pass, and refactor until the code " +"is ready to submit." +msgstr "随机敲击键盘直到测试通过,然后重构直到代码准备好提交。" + +#: src/contributing.md:23 +msgid "Mark the PR as ready to review." +msgstr "将 PR 标记为审查就绪。" + +#: src/contributing.md:24 +msgid "Revise the PR as needed." +msgstr "根据需要修改 PR 。" + +#: src/contributing.md:25 +msgid "And finally, mergies!" +msgstr "最后一步,合并!" + +#: src/contributing.md:27 +msgid "Start small" +msgstr "集腋成裘" + +#: src/contributing.md:30 +msgid "" +"Small changes will allow you to make an impact quickly, and if you take the " +"wrong tack, you won't have wasted much time." +msgstr "" +"小的改变可以让你迅速的产生影响力,即便你采取了错误的策略,你也不会浪费太多的" +"时间。" + +#: src/contributing.md:33 +msgid "Ideas for small issues:" +msgstr "一些小问题的思路:" + +#: src/contributing.md:34 +msgid "Add a new test or test case that increases test coverage" +msgstr "增加新的测试或者测试案例以增加测试的覆盖率" + +#: src/contributing.md:35 +msgid "Add or improve documentation" +msgstr "增加或者改进文档" + +#: src/contributing.md:36 +msgid "" +"Find an issue that needs more research, and do that research and summarize " +"it in a comment" +msgstr "找到一个需要更多研究的问题,进行研究并在评论中进行总结" + +#: src/contributing.md:38 +msgid "Find an out-of-date issue and comment that it can be closed" +msgstr "找到一个过时的问题,并评论使其关闭" + +#: src/contributing.md:39 +msgid "" +"Find an issue that shouldn't be done, and provide constructive feedback " +"detailing why you think that is the case" +msgstr "" +"找到一个本不该做的问题,并提供建设性的反馈,详细说明您认为会出现这种情况的原" +"因" + +#: src/contributing.md:42 +msgid "Merge early and often" +msgstr "早合并,勤合并" + +#: src/contributing.md:45 +msgid "" +"Break up large tasks into multiple smaller steps that individually make " +"progress. If there's a bug, you can open a PR that adds a failing ignored " +"test. This can be merged, and the next step can be to fix the bug and " +"unignore the test. Do research or testing, and report on your results. Break " +"a feature into small sub-features, and implement them one at a time." +msgstr "" +"将大大型的任务分成多个较小的步骤,这些步骤可以单独取的进展。如果有程序错误," +"您也可以打开一个PR,添加一个失败的忽略测试。这可以合并,下一步可以修复错误并" +"忽略测试。将你的研究或者测试结果进行报告。将一个大的功能分解为小的子功能并一" +"次一个的逐步实现它们。" + +#: src/contributing.md:51 +msgid "" +"Figuring out how to break down a larger PR into smaller PRs where each can " +"be merged is an art form well-worth practicing. The hard part is that each " +"PR must itself be an improvement." +msgstr "" +"弄清楚如何将一个较大的PR分解成较小的PR,每个PR都可以合并是一种非常值得练习," +"这也是编程的一种艺术。 困难的部分是每个PR本身必须是一个改进。" + +#: src/contributing.md:55 +msgid "" +"I strive to follow this advice myself, and am always better off when I do." +msgstr "我自己努力遵循这个建议,而且当我这样做时,我总是可以做的更好。" + +#: src/contributing.md:57 +msgid "" +"Small changes are fast to write, review, and merge, which is much more fun " +"than laboring over a single giant PR that takes forever to write, review, " +"and merge. Small changes don't take much time, so if you need to stop " +"working on a small change, you won't have wasted much time as compared to a " +"larger change that represents many hours of work. Getting a PR in quickly " +"improves the project a little bit immediately, instead of having to wait a " +"long time for larger improvement. Small changes are less likely to " +"accumulate merge conflict. As the Athenians said: _The fast commit what they " +"will, the slow merge what they must._" +msgstr "" +"小的更改可以快速编写、审查和合并,这比为一个需要永远编写、审查和合并的大型的" +"PR工作要有趣得多。小的更改不会花费太多时间,因此如果您需要停止处理一个小的更" +"改,与代表许多小时工作的较大更改相比,您不会浪费太多时间。 快速获得PR可以立即" +"改进项目,而不必等待很长时间才能进行更大的改进。 小的更改不太可能累积合并冲" +"突。正如雅典人所说:_快者尽其所愿,慢者兼并其所必须。_" + +#: src/contributing.md:67 +msgid "Get help" +msgstr "寻求帮助" + +#: src/contributing.md:70 +msgid "" +"If you're stuck for more than 15 minutes, ask for help, like a Rust Discord, " +"Stack Exchange, or in a project issue or discussion." +msgstr "" +"如果您遇到困难超过 15 分钟,请寻求帮助,例如 Rust Discord、Stack Exchange,或" +"者在项目问题或讨论中寻求帮助。" + +#: src/contributing.md:73 +msgid "Practice hypothesis-driven debugging" +msgstr "实践'假说驱动'的调试" + +#: src/contributing.md:76 +msgid "" +"Formulate a hypothesis as to what is causing the problem. Figure out how to " +"test that hypothesis. Perform that tests. If it works, great, you fixed the " +"issue or now you know how to fix the issue. If not, repeat with a new " +"hypothesis." +msgstr "" +"就导致问题的原因提出假设。 弄清楚如何检验该假设。 执行该测试。 如果有效,那太" +"好了,您解决了问题,或者现在您知道如何解决问题了。 如果不是,请重复一个新的假" +"设。" + +#: src/contributing.md:81 +msgid "Pay attention to error messages" +msgstr "关注错误信息" + +#: src/contributing.md:84 +msgid "Read all error messages and don't tolerate warnings." +msgstr "阅读所有错误消息,不要容忍警告。" + +#: src/donate.md:4 +msgid "" +"Ordinals is open-source and community funded. The current lead maintainer of " +"`ord` is [raphjaph](https://github.com/raphjaph/). Raph's work on `ord` is " +"entirely funded by donations. If you can, please consider donating!" +msgstr "" +"Ordinals序数是开源的,由社区资助的项目。目前`ord`的首席维护者是[raphjaph]" +"(https://github.com/raphjaph/).Raph在 `ord` 上的维护工作全部由捐赠的资金完" +"成。你如果可以的话,请考虑捐赠!" + +#: src/donate.md:8 +msgid "" +"The donation address for Bitcoin is " +"[bc1q8kt9pyd6r27k2840l8g5d7zshz3cg9v6rfda0m248lva3ve5072q3sxelt](https://" +"mempool.space/address/" +"bc1q8kt9pyd6r27k2840l8g5d7zshz3cg9v6rfda0m248lva3ve5072q3sxelt). The " +"donation address for inscriptions is " +"[bc1qn3map8m9hmk5jyqdkkwlwvt335g94zvxwd9aql7q3vdkdw9r5eyqvlvec0](https://" +"mempool.space/address/" +"bc1qn3map8m9hmk5jyqdkkwlwvt335g94zvxwd9aql7q3vdkdw9r5eyqvlvec0)." +msgstr "" +"捐赠地址为 [bc1q8kt9pyd6r27k2840l8g5d7zshz3cg9v6rfda0m248lva3ve5072q3sxelt]" +"(https://mempool.space/address/" +"bc1q8kt9pyd6r27k2840l8g5d7zshz3cg9v6rfda0m248lva3ve5072q3sxelt). 铭文的捐赠地" +"址为 [bc1qn3map8m9hmk5jyqdkkwlwvt335g94zvxwd9aql7q3vdkdw9r5eyqvlvec0]" +"(https://mempool.space/address/" +"bc1qn3map8m9hmk5jyqdkkwlwvt335g94zvxwd9aql7q3vdkdw9r5eyqvlvec0)." + +#: src/donate.md:11 +msgid "" +"Both addresses are in a 2 of 4 multisig wallet with keys held by [raphjaph]" +"(https://twitter.com/raphjaph), [erin](https://twitter.com/realizingerin), " +"[rodarmor](https://twitter.com/rodarmor), and [ordinally](https://twitter." +"com/veryordinally)." +msgstr "" +"上述两个地址是由以下多签人(2/4)持有管理: [raphjaph](https://twitter.com/" +"raphjaph), [erin](https://twitter.com/realizingerin), [rodarmor](https://" +"twitter.com/rodarmor), and [ordinally](https://twitter.com/veryordinally)." + +#: src/donate.md:17 +msgid "" +"Donations received will go towards funding maintenance and development of " +"`ord`, as well as hosting costs for [ordinals.com](https://ordinals.com)." +msgstr "" +"收到的捐赠款将用于资助 `ord`的维护和进一步开发,同时将支付[ordinals.com]" +"(https://ordinals.com)的托管费用。" + +#: src/donate.md:20 +msgid "Thank you for donating!" +msgstr "感谢您的捐赠!" + +#: src/guides.md:1 +msgid "Ordinal Theory Guides" +msgstr "序数理论指引" + +#: src/guides.md:4 +msgid "" +"See the table of contents for a list of guides, including a guide to the " +"explorer, a guide for sat hunters, and a guide to inscriptions." +msgstr "请参阅目录以获取指南列表,包括区块浏览器指南、猎聪指南和铭文指南。" + +#: src/guides/explorer.md:1 +msgid "Ordinal Explorer" +msgstr "序数浏览器" + +#: src/guides/explorer.md:4 +msgid "" +"The `ord` binary includes a block explorer. We host a instance of the block " +"explorer on mainnet at [ordinals.com](https://ordinals.com), and on signet " +"at [signet.ordinals.com](https://signet.ordinals.com)." +msgstr "" +"`ord` 文件包含一个区块浏览器。我们的主网区块链器部署在 [ordinals.com]" +"(https://ordinals.com), signet部署在[signet.ordinals.com](https://signet." +"ordinals.com)." + +#: src/guides/explorer.md:8 +msgid "Running The Explorer" +msgstr "运行浏览器" + +#: src/guides/explorer.md:9 +msgid "The server can be run locally with:" +msgstr "服务器可以使用本地运行:" + +#: src/guides/explorer.md:11 +msgid "`ord server`" +msgstr "" + +#: src/guides/explorer.md:13 +msgid "To specify a port add the `--http-port` flag:" +msgstr "指定端口使用`--http-port`标记" + +#: src/guides/explorer.md:15 +msgid "`ord server --http-port 8080`" +msgstr "" + +#: src/guides/explorer.md:17 +msgid "To test how your inscriptions will look you can run:" +msgstr "测试你的铭文你可以运行:" + +#: src/guides/explorer.md:19 +msgid "`ord preview ...`" +msgstr "" + +#: src/guides/explorer.md:21 +msgid "Search" +msgstr "搜索" + +#: src/guides/explorer.md:24 +msgid "The search box accepts a variety of object representations." +msgstr "搜索框可以使用各种对象:" + +#: src/guides/explorer.md:26 +msgid "Blocks" +msgstr "区块" + +#: src/guides/explorer.md:28 +msgid "Blocks can be searched by hash, for example, the genesis block:" +msgstr "区块可以通过哈希来查找,例如创世区块:" + +#: src/guides/explorer.md:30 +msgid "" +"[000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f](https://" +"ordinals.com/" +"search/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f)" +msgstr "" + +#: src/guides/explorer.md:32 +msgid "Transactions" +msgstr "交易" + +#: src/guides/explorer.md:34 +msgid "" +"Transactions can be searched by hash, for example, the genesis block " +"coinbase transaction:" +msgstr "可以通过哈希查找交易,例如创世区块的coinbase交易:" + +#: src/guides/explorer.md:37 +msgid "" +"[4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b](https://" +"ordinals.com/" +"search/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b)" +msgstr "" + +#: src/guides/explorer.md:39 +msgid "Outputs" +msgstr "输出" + +#: src/guides/explorer.md:41 +msgid "" +"Transaction outputs can searched by outpoint, for example, the only output " +"of the genesis block coinbase transaction:" +msgstr "可以通过outpoint搜索交易输出,例如创世块coinbase交易的唯一输出:" + +#: src/guides/explorer.md:44 +msgid "" +"[4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0](https://" +"ordinals.com/" +"search/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0)" +msgstr "" + +#: src/guides/explorer.md:46 +msgid "Sats" +msgstr "聪" + +#: src/guides/explorer.md:48 +msgid "" +"Sats can be searched by integer, their position within the entire bitcoin " +"supply:" +msgstr "聪 可以按整数搜索,它们在整个比特币供应中的位置:" + +#: src/guides/explorer.md:51 +msgid "[2099994106992659](https://ordinals.com/search/2099994106992659)" +msgstr "" + +#: src/guides/explorer.md:53 +msgid "By decimal, their block and offset within that block:" +msgstr "按十进制,它们的块和该块内的偏移量:" + +#: src/guides/explorer.md:55 +msgid "[481824.0](https://ordinals.com/search/481824.0)" +msgstr "" + +#: src/guides/explorer.md:57 +msgid "" +"By degree, their cycle, blocks since the last halving, blocks since the last " +"difficulty adjustment, and offset within their block:" +msgstr "" +"按度数,他们的周期,自上次减半以来的区块,自上次难度调整以来的区块,以及区块" +"内的偏移量:" + +#: src/guides/explorer.md:60 +msgid "[1°0′0″0‴](https://ordinals.com/search/1°0′0″0‴)" +msgstr "" + +#: src/guides/explorer.md:62 +msgid "" +"By name, their base 26 representation using the letters \"a\" through \"z\":" +msgstr "按照名称,它们使用字母\"a\"到\"z\"的 26个字母组合表示:" + +#: src/guides/explorer.md:64 +msgid "[ahistorical](https://ordinals.com/search/ahistorical)" +msgstr "" + +#: src/guides/explorer.md:66 +msgid "" +"Or by percentile, the percentage of bitcoin's supply that has been or will " +"have been issued when they are mined:" +msgstr "或者按百分位数,在开采时已经或将要发行的比特币供应量的百分比:" + +#: src/guides/explorer.md:69 +msgid "[100%](https://ordinals.com/search/100%)" +msgstr "" + +#: src/guides/inscriptions.md:1 +msgid "Ordinal Inscription Guide" +msgstr "铭文指引" + +#: src/guides/inscriptions.md:4 +msgid "" +"Individual sats can be inscribed with arbitrary content, creating Bitcoin-" +"native digital artifacts that can be held in a Bitcoin wallet and " +"transferred using Bitcoin transactions. Inscriptions are as durable, " +"immutable, secure, and decentralized as Bitcoin itself." +msgstr "" +"单个 聪 可以刻有任意内容,创建可以保存在比特币钱包中并使用比特币交易传输的比" +"特币原生数字人工制品。铭文与比特币本身一样持久、不变、安全和去中心化。" + +#: src/guides/inscriptions.md:9 +msgid "" +"Working with inscriptions requires a Bitcoin full node, to give you a view " +"of the current state of the Bitcoin blockchain, and a wallet that can create " +"inscriptions and perform sat control when constructing transactions to send " +"inscriptions to another wallet." +msgstr "" +"使用铭文需要一个比特币完整节点,让您了解比特币区块链的当前状态,以及一个可以" +"创建铭文并在构建交易以将铭文发送到另一个钱包时执行 聪 控制的钱包。" + +#: src/guides/inscriptions.md:14 +msgid "" +"Bitcoin Core provides both a Bitcoin full node and wallet. However, the " +"Bitcoin Core wallet cannot create inscriptions and does not perform sat " +"control." +msgstr "" +"Bitcoin Core 提供比特币全节点和钱包。 但是,Bitcoin Core 钱包不能创建铭文,不" +"执行 聪 控制。" + +#: src/guides/inscriptions.md:17 +msgid "" +"This requires [`ord`](https://github.com/ordinals/ord), the ordinal utility. " +"`ord` doesn't implement its own wallet, so `ord wallet` subcommands interact " +"with Bitcoin Core wallets." +msgstr "" +"这需要[`ord`](https://github.com/ordinals/ord),序数实用程序。 `ord` 没有自己" +"的钱包,因此 `ord wallet`子命令与 Bitcoin Core 钱包交互。" + +#: src/guides/inscriptions.md:21 +msgid "This guide covers:" +msgstr "本指南涵盖:" + +#: src/guides/inscriptions.md:23 src/guides/inscriptions.md:39 +msgid "Installing Bitcoin Core" +msgstr "安装 Bitcoin Core" + +#: src/guides/inscriptions.md:24 +msgid "Syncing the Bitcoin blockchain" +msgstr "同步比特币区块链" + +#: src/guides/inscriptions.md:25 +msgid "Creating a Bitcoin Core wallet" +msgstr "创建 Bitcoin Core 钱包" + +#: src/guides/inscriptions.md:26 +msgid "Using `ord wallet receive` to receive sats" +msgstr "使用 `ord wallet receive`收取聪" + +#: src/guides/inscriptions.md:27 +msgid "Creating inscriptions with `ord wallet inscribe`" +msgstr "使用`ord wallet inscribe`创建铭文" + +#: src/guides/inscriptions.md:28 +msgid "Sending inscriptions with `ord wallet send`" +msgstr "使用 `ord wallet send`发送铭文" + +#: src/guides/inscriptions.md:29 +msgid "Receiving inscriptions with `ord wallet receive`" +msgstr "使用`ord wallet receive`收取铭文" + +#: src/guides/inscriptions.md:31 +msgid "Getting Help" +msgstr "寻求帮助" + +#: src/guides/inscriptions.md:34 +msgid "" +"If you get stuck, try asking for help on the [Ordinals Discord Server]" +"(https://discord.com/invite/87cjuz4FYg), or checking GitHub for relevant " +"[issues](https://github.com/ordinals/ord/issues) and [discussions](https://" +"github.com/ordinals/ord/discussions)." +msgstr "" +"如果你遇到困难,可以在[Ordinals Discord Server](https://discord.com/" +"invite/87cjuz4FYg),或者检查Github上的相关内容[问题](https://github.com/" +"ordinals/ord/issues) 和[讨论](https://github.com/ordinals/ord/discussions)." + +#: src/guides/inscriptions.md:42 +msgid "" +"Bitcoin Core is available from [bitcoincore.org](https://bitcoincore.org/) " +"on the [download page](https://bitcoincore.org/en/download/)." +msgstr "" +"Bitcoin Core 可以在 [bitcoincore.org](https://bitcoincore.org/) 上的[下载页" +"面](https://bitcoincore.org/en/download/)." + +#: src/guides/inscriptions.md:45 +msgid "Making inscriptions requires Bitcoin Core 24 or newer." +msgstr "制作铭文需要Bitcoin Core 24 或者更新版本。" + +#: src/guides/inscriptions.md:47 +msgid "" +"This guide does not cover installing Bitcoin Core in detail. Once Bitcoin " +"Core is installed, you should be able to run `bitcoind -version` " +"successfully from the command line." +msgstr "" +"本指南不包括如何详细安装 Bitcoin Core;当你成功安装Bitcoin Core以后,你应该可" +"以在命令行使用 `bitcoind -version`命令。" + +#: src/guides/inscriptions.md:51 +msgid "Configuring Bitcoin Core" +msgstr "配置 Bitcoin Core" + +#: src/guides/inscriptions.md:54 +msgid "`ord` requires Bitcoin Core's transaction index." +msgstr "`ord` 需要Bitcoin Core 的交易索引" + +#: src/guides/inscriptions.md:56 +msgid "" +"To configure your Bitcoin Core node to maintain a transaction index, add the " +"following to your `bitcoin.conf`:" +msgstr "" +"配置你的Bitcoin Core阶段去维护一个交易索引,需要在`bitcoin.conf`里面添加:" + +#: src/guides/inscriptions.md:59 src/guides/sat-hunting.md:30 +msgid "" +"```\n" +"txindex=1\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:63 +msgid "Or, run `bitcoind` with `-txindex`:" +msgstr "或者, 运行 `bitcoind` 和 `-txindex`:" + +#: src/guides/inscriptions.md:65 src/guides/inscriptions.md:74 +msgid "" +"```\n" +"bitcoind -txindex\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:69 +msgid "Syncing the Bitcoin Blockchain" +msgstr "比特币区块同步" + +#: src/guides/inscriptions.md:72 +msgid "To sync the chain, run:" +msgstr "区块同步,运行:" + +#: src/guides/inscriptions.md:78 +msgid "…and leave it running until `getblockcount`:" +msgstr "…直到运行 `getblockcount`:" + +#: src/guides/inscriptions.md:80 +msgid "" +"```\n" +"bitcoin-cli getblockcount\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:84 +msgid "" +"agrees with the block count on a block explorer like [the mempool.space " +"block explorer](https://mempool.space/). `ord` interacts with `bitcoind`, so " +"you should leave `bitcoind` running in the background when you're using " +"`ord`." +msgstr "" +"像区块链浏览器[the mempool.space block explorer](https://mempool.space/)一样" +"对区块进行记述. `ord`同`bitcoind`进行交互, 所以你在使用`ord`时候需要让" +"`bitcoind` 在后台运行。" + +#: src/guides/inscriptions.md:88 +msgid "Installing `ord`" +msgstr "安装 `ord`" + +#: src/guides/inscriptions.md:91 +msgid "" +"The `ord` utility is written in Rust and can be built from [source](https://" +"github.com/ordinals/ord). Pre-built binaries are available on the [releases " +"page](https://github.com/ordinals/ord/releases)." +msgstr "" +"`ord` 程序使用Rust语言写成,可以从[源码](https://github.com/ordinals/ord)安" +"装. 预制文件可以从[版本发布页](https://github.com/ordinals/ord/releases)下" +"载。" + +#: src/guides/inscriptions.md:95 +msgid "You can install the latest pre-built binary from the command line with:" +msgstr "你也可以在命令行中使用下面命令来安装最新的文件:" + +#: src/guides/inscriptions.md:97 +msgid "" +"```sh\n" +"curl --proto '=https' --tlsv1.2 -fsLS https://ordinals.com/install.sh | bash " +"-s\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:101 +msgid "Once `ord` is installed, you should be able to run:" +msgstr "当 `ord` 成功安装以后,你可以运行 :" + +#: src/guides/inscriptions.md:103 +msgid "" +"```\n" +"ord --version\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:107 +msgid "Which prints out `ord`'s version number." +msgstr "这会返回 `ord`的版本信息." + +#: src/guides/inscriptions.md:109 +msgid "Creating a Bitcoin Core Wallet" +msgstr "创建一个Bitcoin Core钱包" + +#: src/guides/inscriptions.md:112 +msgid "" +"`ord` uses Bitcoin Core to manage private keys, sign transactions, and " +"broadcast transactions to the Bitcoin network." +msgstr "`ord` 使用Bitcoin Core来管理私钥,签署交易以及向比特币网络广播交易。" + +#: src/guides/inscriptions.md:115 +msgid "To create a Bitcoin Core wallet named `ord` for use with `ord`, run:" +msgstr "创建一个名为`ord` 的Bitcoin Core 钱包,运行:" + +#: src/guides/inscriptions.md:117 +msgid "" +"```\n" +"ord wallet create\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:121 +msgid "Receiving Sats" +msgstr "接收聪" + +#: src/guides/inscriptions.md:124 +msgid "" +"Inscriptions are made on individual sats, using normal Bitcoin transactions " +"that pay fees in sats, so your wallet will need some sats." +msgstr "" +"铭文是在单个聪上制作的,使用聪来支付费用的普通比特币交易,因此你的钱包将需要" +"一些 聪(比特币)。" + +#: src/guides/inscriptions.md:127 +msgid "Get a new address from your `ord` wallet by running:" +msgstr "为你的 `ord` 钱包创建一个新地址,运行:" + +#: src/guides/inscriptions.md:129 src/guides/inscriptions.md:201 +#: src/guides/inscriptions.md:229 +msgid "" +"```\n" +"ord wallet receive\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:133 +msgid "And send it some funds." +msgstr "向上面地址发送一些资金。" + +#: src/guides/inscriptions.md:135 +msgid "You can see pending transactions with:" +msgstr "你可以使用以下命令看到交易情况:" + +#: src/guides/inscriptions.md:137 src/guides/inscriptions.md:213 +#: src/guides/inscriptions.md:240 +msgid "" +"```\n" +"ord wallet transactions\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:141 +msgid "" +"Once the transaction confirms, you should be able to see the transactions " +"outputs with `ord wallet outputs`." +msgstr "一旦交易确认,你应该可以使用 `ord wallet outputs`看到交易的输出;" + +#: src/guides/inscriptions.md:144 +msgid "Creating Inscription Content" +msgstr "创建铭文内容" + +#: src/guides/inscriptions.md:147 +msgid "" +"Sats can be inscribed with any kind of content, but the `ord` wallet only " +"supports content types that can be displayed by the `ord` block explorer." +msgstr "" +"聪上可以刻录任何类型的内容,但`ord`钱包只支持`ord`区块浏览器可以显示的内容类" +"型。" + +#: src/guides/inscriptions.md:150 +msgid "" +"Additionally, inscriptions are included in transactions, so the larger the " +"content, the higher the fee that the inscription transaction must pay." +msgstr "" +"另外,铭文是包含在交易中的,所以内容越大,铭文交易需要支付的费用就越高。" + +#: src/guides/inscriptions.md:153 +msgid "" +"Inscription content is included in transaction witnesses, which receive the " +"witness discount. To calculate the approximate fee that an inscribe " +"transaction will pay, divide the content size by four and multiply by the " +"fee rate." +msgstr "" +"铭文内容包含在交易见证中,获得见证折扣。要计算写入交易将支付的大概费用,请将" +"内容大小除以四,然后乘以费率。" + +#: src/guides/inscriptions.md:157 +msgid "" +"Inscription transactions must be less than 400,000 weight units, or they " +"will not be relayed by Bitcoin Core. One byte of inscription content costs " +"one weight unit. Since an inscription transaction includes not just the " +"inscription content, limit inscription content to less than 400,000 weight " +"units. 390,000 weight units should be safe." +msgstr "" +"铭文交易必须少于 400,000 个权重计量单位,否则不会被 Bitcoin Core 中继。一个字" +"节的铭文内容需要一个权重计量单位。 由于铭文交易不只是铭文内容,铭文内容限制在" +"400,000权重计量单位以内。390,000 个权重计量单位应该是安全的。" + +#: src/guides/inscriptions.md:163 +msgid "Creating Inscriptions" +msgstr "创建铭文" + +#: src/guides/inscriptions.md:166 +msgid "To create an inscription with the contents of `FILE`, run:" +msgstr "以`FILE`的内容创建一个铭文,需要运行:" + +#: src/guides/inscriptions.md:168 +msgid "" +"```\n" +"ord wallet inscribe --fee-rate FEE_RATE FILE\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:172 +msgid "" +"Ord will output two transactions IDs, one for the commit transaction, and " +"one for the reveal transaction, and the inscription ID. Inscription IDs are " +"of the form `TXIDiN`, where `TXID` is the transaction ID of the reveal " +"transaction, and `N` is the index of the inscription in the reveal " +"transaction." +msgstr "" +"Ord会输出两个交易ID,一个是commit交易,一个是reveal交易,还有铭文ID。铭文 ID " +"的格式为`TXIDiN`,其中`TXID` 是揭示交易的交易 ID,`N` 是揭示交易中铭文的索" +"引。" + +#: src/guides/inscriptions.md:177 +msgid "" +"The commit transaction commits to a tapscript containing the content of the " +"inscription, and the reveal transaction spends from that tapscript, " +"revealing the content on chain and inscribing it on the first sat of the " +"input that contains the corresponding tapscript." +msgstr "" +"Commit交易提交到包含铭文内容的 tapscript,reveal交易则从该 tapscript 中花费," +"显示链上的内容并将它们铭刻在reveal交易的第一个输出的第一个 sat 上。" + +#: src/guides/inscriptions.md:182 +msgid "" +"Wait for the reveal transaction to be mined. You can check the status of the " +"commit and reveal transactions using [the mempool.space block explorer]" +"(https://mempool.space/)." +msgstr "" +"在等待reveal交易被记录的同时,你可以使用[the mempool.space block explorer]" +"(https://mempool.space/)来检查交易的状态。" + +#: src/guides/inscriptions.md:186 +msgid "" +"Once the reveal transaction has been mined, the inscription ID should be " +"printed when you run:" +msgstr "一旦reveal交易完成记账,你可以使用以下命令查询铭文ID:" + +#: src/guides/inscriptions.md:189 src/guides/inscriptions.md:220 +#: src/guides/inscriptions.md:246 +msgid "" +"```\n" +"ord wallet inscriptions\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:193 +msgid "" +"And when you visit [the ordinals explorer](https://ordinals.com/) at " +"`ordinals.com/inscription/INSCRIPTION_ID`." +msgstr "" +"你可以在 [the ordinals explorer](https://ordinals.com/) 上用一下格式访问铭文" +"`ordinals.com/inscription/INSCRIPTION_ID`." + +#: src/guides/inscriptions.md:196 +msgid "Sending Inscriptions" +msgstr "发送铭文" + +#: src/guides/inscriptions.md:199 +msgid "Ask the recipient to generate a new address by running:" +msgstr "铭文接收方使用一下命令生成地址" + +#: src/guides/inscriptions.md:205 +msgid "Send the inscription by running:" +msgstr "使用命令格式发送铭文:" + +#: src/guides/inscriptions.md:207 +msgid "" +"```\n" +"ord wallet send --fee-rate
\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:211 src/guides/inscriptions.md:239 +msgid "See the pending transaction with:" +msgstr "检查未完成交易情况:" + +#: src/guides/inscriptions.md:217 +msgid "" +"Once the send transaction confirms, the recipient can confirm receipt by " +"running:" +msgstr "一旦交易确认,接收方可以使用一下命令查看接收到的铭文" + +#: src/guides/inscriptions.md:224 +msgid "Receiving Inscriptions" +msgstr "接收铭文" + +#: src/guides/inscriptions.md:227 +msgid "Generate a new receive address using:" +msgstr "使用以下命令生成一个新的接收地址" + +#: src/guides/inscriptions.md:233 +msgid "The sender can transfer the inscription to your address using:" +msgstr "发送方使用命令发送铭文到你的地址" + +#: src/guides/inscriptions.md:235 +msgid "" +"```\n" +"ord wallet send ADDRESS INSCRIPTION_ID\n" +"```" +msgstr "" + +#: src/guides/inscriptions.md:244 +msgid "" +"Once the send transaction confirms, you can can confirm receipt by running:" +msgstr "一旦交易确认,你可以使用以下命令确认收到" + +#: src/guides/sat-hunting.md:4 +msgid "" +"_This guide is out of date. Since it was written, the `ord` binary was " +"changed to only build the full satoshi index when the `--index-sats` flag is " +"supplied. Additionally, `ord` now has a built-in wallet that wraps a Bitcoin " +"Core wallet. See `ord wallet --help`._" +msgstr "" +"_本指南已过时。自编写以来,“ord”安装文件已更改仅当提供“--index-sats”标志时才" +"构建完整的聪索引。此外,“ord”现在有一个内置钱包,其中包含比特币核心钱包。请参" +"阅`ord wallet --help`。_" + +#: src/guides/sat-hunting.md:9 +msgid "" +"Ordinal hunting is difficult but rewarding. The feeling of owning a wallet " +"full of UTXOs, redolent with the scent of rare and exotic sats, is beyond " +"compare." +msgstr "" + +#: src/guides/sat-hunting.md:12 +msgid "" +"Ordinals are numbers for satoshis. Every satoshi has an ordinal number and " +"every ordinal number has a satoshi." +msgstr "" + +#: src/guides/sat-hunting.md:15 +msgid "Preparation" +msgstr "" + +#: src/guides/sat-hunting.md:18 +msgid "There are a few things you'll need before you start." +msgstr "" + +#: src/guides/sat-hunting.md:20 +msgid "" +"First, you'll need a synced Bitcoin Core node with a transaction index. To " +"turn on transaction indexing, pass `-txindex` on the command-line:" +msgstr "" + +#: src/guides/sat-hunting.md:23 +msgid "" +"```sh\n" +"bitcoind -txindex\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:27 +msgid "" +"Or put the following in your [Bitcoin configuration file](https://github.com/" +"bitcoin/bitcoin/blob/master/doc/bitcoin-conf.md#configuration-file-path):" +msgstr "" + +#: src/guides/sat-hunting.md:34 +msgid "" +"Launch it and wait for it to catch up to the chain tip, at which point the " +"following command should print out the current block height:" +msgstr "" + +#: src/guides/sat-hunting.md:37 +msgid "" +"```sh\n" +"bitcoin-cli getblockcount\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:41 +msgid "Second, you'll need a synced `ord` index." +msgstr "" + +#: src/guides/sat-hunting.md:43 +msgid "Get a copy of `ord` from [the repo](https://github.com/ordinals/ord/)." +msgstr "" + +#: src/guides/sat-hunting.md:45 +msgid "" +"Run `RUST_LOG=info ord index`. It should connect to your bitcoin core node " +"and start indexing." +msgstr "" + +#: src/guides/sat-hunting.md:48 +msgid "Wait for it to finish indexing." +msgstr "" + +#: src/guides/sat-hunting.md:50 +msgid "Third, you'll need a wallet with UTXOs that you want to search." +msgstr "" + +#: src/guides/sat-hunting.md:52 +msgid "Searching for Rare Ordinals" +msgstr "" + +#: src/guides/sat-hunting.md:55 +msgid "Searching for Rare Ordinals in a Bitcoin Core Wallet" +msgstr "" + +#: src/guides/sat-hunting.md:57 +msgid "" +"The `ord wallet` command is just a wrapper around Bitcoin Core's RPC API, so " +"searching for rare ordinals in a Bitcoin Core wallet is Easy. Assuming your " +"wallet is named `foo`:" +msgstr "" + +#: src/guides/sat-hunting.md:61 +msgid "Load your wallet:" +msgstr "" + +#: src/guides/sat-hunting.md:63 +msgid "" +"```sh\n" +"bitcoin-cli loadwallet foo\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:67 +msgid "Display any rare ordinals wallet `foo`'s UTXOs:" +msgstr "" + +#: src/guides/sat-hunting.md:69 src/guides/sat-hunting.md:132 +#: src/guides/sat-hunting.md:233 +msgid "" +"```sh\n" +"ord wallet sats\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:73 +msgid "Searching for Rare Ordinals in a Non-Bitcoin Core Wallet" +msgstr "" + +#: src/guides/sat-hunting.md:75 +msgid "" +"The `ord wallet` command is just a wrapper around Bitcoin Core's RPC API, so " +"to search for rare ordinals in a non-Bitcoin Core wallet, you'll need to " +"import your wallet's descriptors into Bitcoin Core." +msgstr "" + +#: src/guides/sat-hunting.md:79 +msgid "" +"[Descriptors](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors." +"md) describe the ways that wallets generate private keys and public keys." +msgstr "" + +#: src/guides/sat-hunting.md:82 +msgid "" +"You should only import descriptors into Bitcoin Core for your wallet's " +"public keys, not its private keys." +msgstr "" + +#: src/guides/sat-hunting.md:85 +msgid "" +"If your wallet's public key descriptor is compromised, an attacker will be " +"able to see your wallet's addresses, but your funds will be safe." +msgstr "" + +#: src/guides/sat-hunting.md:88 +msgid "" +"If your wallet's private key descriptor is compromised, an attacker can " +"drain your wallet of funds." +msgstr "" + +#: src/guides/sat-hunting.md:91 +msgid "" +"Get the wallet descriptor from the wallet whose UTXOs you want to search for " +"rare ordinals. It will look something like this:" +msgstr "" + +#: src/guides/sat-hunting.md:94 +msgid "" +"```\n" +"wpkh([bf1dd55e/84'/0'/0']xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)#csvefu29\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:98 +msgid "Create a watch-only wallet named `foo-watch-only`:" +msgstr "" + +#: src/guides/sat-hunting.md:100 +msgid "" +"```sh\n" +"bitcoin-cli createwallet foo-watch-only true true\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:104 +msgid "Feel free to give it a better name than `foo-watch-only`!" +msgstr "" + +#: src/guides/sat-hunting.md:106 +msgid "Load the `foo-watch-only` wallet:" +msgstr "" + +#: src/guides/sat-hunting.md:108 src/guides/sat-hunting.md:199 +msgid "" +"```sh\n" +"bitcoin-cli loadwallet foo-watch-only\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:112 +msgid "Import your wallet descriptors into `foo-watch-only`:" +msgstr "" + +#: src/guides/sat-hunting.md:114 +msgid "" +"```sh\n" +"bitcoin-cli importdescriptors \\\n" +" '[{ \"desc\": " +"\"wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)#tpnxnxax\", \"timestamp\":0 }]'\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:119 +msgid "" +"If you know the Unix timestamp when your wallet first started receive " +"transactions, you may use it for the value of `\"timestamp\"` instead of " +"`0`. This will reduce the time it takes for Bitcoin Core to search for your " +"wallet's UTXOs." +msgstr "" + +#: src/guides/sat-hunting.md:124 src/guides/sat-hunting.md:225 +msgid "Check that everything worked:" +msgstr "" + +#: src/guides/sat-hunting.md:126 src/guides/sat-hunting.md:227 +msgid "" +"```sh\n" +"bitcoin-cli getwalletinfo\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:130 src/guides/sat-hunting.md:231 +msgid "Display your wallet's rare ordinals:" +msgstr "" + +#: src/guides/sat-hunting.md:136 +msgid "" +"Searching for Rare Ordinals in a Wallet that Exports Multi-path Descriptors" +msgstr "" + +#: src/guides/sat-hunting.md:138 +msgid "" +"Some descriptors describe multiple paths in one descriptor using angle " +"brackets, e.g., `<0;1>`. Multi-path descriptors are not yet supported by " +"Bitcoin Core, so you'll first need to convert them into multiple " +"descriptors, and then import those multiple descriptors into Bitcoin Core." +msgstr "" + +#: src/guides/sat-hunting.md:143 +msgid "" +"First get the multi-path descriptor from your wallet. It will look something " +"like this:" +msgstr "" + +#: src/guides/sat-hunting.md:146 +msgid "" +"```\n" +"wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/" +"<0;1>/*)#fw76ulgt\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:150 +msgid "Create a descriptor for the receive address path:" +msgstr "" + +#: src/guides/sat-hunting.md:152 +msgid "" +"```\n" +"wpkh([bf1dd55e/84'/0'/0']xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:156 +msgid "And the change address path:" +msgstr "" + +#: src/guides/sat-hunting.md:158 +msgid "" +"```\n" +"wpkh([bf1dd55e/84'/0'/0']xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/1/" +"*)\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:162 +msgid "" +"Get and note the checksum for the receive address descriptor, in this case " +"`tpnxnxax`:" +msgstr "" + +#: src/guides/sat-hunting.md:165 +msgid "" +"```sh\n" +"bitcoin-cli getdescriptorinfo \\\n" +" 'wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)'\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:170 +msgid "" +"```json\n" +"{\n" +" \"descriptor\": " +"\"wpkh([bf1dd55e/84'/0'/0']xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)#csvefu29\",\n" +" \"checksum\": \"tpnxnxax\",\n" +" \"isrange\": true,\n" +" \"issolvable\": true,\n" +" \"hasprivatekeys\": false\n" +"}\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:180 +msgid "And for the change address descriptor, in this case `64k8wnd7`:" +msgstr "" + +#: src/guides/sat-hunting.md:182 +msgid "" +"```sh\n" +"bitcoin-cli getdescriptorinfo \\\n" +" 'wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/1/" +"*)'\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:187 +msgid "" +"```json\n" +"{\n" +" \"descriptor\": " +"\"wpkh([bf1dd55e/84'/0'/0']xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/1/" +"*)#fyfc5f6a\",\n" +" \"checksum\": \"64k8wnd7\",\n" +" \"isrange\": true,\n" +" \"issolvable\": true,\n" +" \"hasprivatekeys\": false\n" +"}\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:197 +msgid "Load the wallet you want to import the descriptors into:" +msgstr "" + +#: src/guides/sat-hunting.md:203 +msgid "" +"Now import the descriptors, with the correct checksums, into Bitcoin Core." +msgstr "" + +#: src/guides/sat-hunting.md:205 +msgid "" +"```sh\n" +"bitcoin-cli \\\n" +" importdescriptors \\\n" +" '[\n" +" {\n" +" \"desc\": " +"\"wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/0/" +"*)#tpnxnxax\"\n" +" \"timestamp\":0\n" +" },\n" +" {\n" +" \"desc\": " +"\"wpkh([bf1dd55e/84h/0h/0h]xpub6CcJtWcvFQaMo39ANFi1MyXkEXM8T8ZhnxMtSjQAdPmVSTHYnc8Hwoc11VpuP8cb8JUTboZB5A7YYGDonYySij4XTawL6iNZvmZwdnSEEep/1/" +"*)#64k8wnd7\",\n" +" \"timestamp\":0\n" +" }\n" +" ]'\n" +"```" +msgstr "" + +#: src/guides/sat-hunting.md:220 +msgid "" +"If you know the Unix timestamp when your wallet first started receive " +"transactions, you may use it for the value of the `\"timestamp\"` fields " +"instead of `0`. This will reduce the time it takes for Bitcoin Core to " +"search for your wallet's UTXOs." +msgstr "" + +#: src/guides/sat-hunting.md:237 +msgid "Exporting Descriptors" +msgstr "" + +#: src/guides/sat-hunting.md:241 +msgid "" +"Navigate to the `Settings` tab, then to `Script Policy`, and press the edit " +"button to display the descriptor." +msgstr "" + +#: src/guides/sat-hunting.md:244 +msgid "Transferring Ordinals" +msgstr "" + +#: src/guides/sat-hunting.md:246 +msgid "" +"The `ord` wallet supports transferring specific satoshis. You can also use " +"`bitcoin-cli` commands `createrawtransaction`, " +"`signrawtransactionwithwallet`, and `sendrawtransaction`, how to do so is " +"complex and outside the scope of this guide." +msgstr "" + +#: src/guides/collecting.md:4 +msgid "" +"Currently, [ord](https://github.com/ordinals/ord/) is the only wallet " +"supporting sat-control and sat-selection, which are required to safely store " +"and send rare sats and inscriptions, hereafter ordinals." +msgstr "" +"目前,[ord](https://github.com/ordinals/ord/) 是唯一支持 sat-control 和 sat-" +"selection 的钱包,这是安全存储和发送稀有 sats 和铭文(以下简称序数)所必需" +"的。" + +#: src/guides/collecting.md:8 +msgid "" +"The recommended way to send, receive, and store ordinals is with `ord`, but " +"if you are careful, it is possible to safely store, and in some cases send, " +"ordinals with other wallets." +msgstr "" +"发送、接收和存储序号的推荐方法是使用 `ord`,但如果你小心,可以安全地存储,在" +"某些情况下,使用其他钱包发送序号。" + +#: src/guides/collecting.md:12 +msgid "" +"As a general note, receiving ordinals in an unsupported wallet is not " +"dangerous. Ordinals can be sent to any bitcoin address, and are safe as long " +"as the UTXO that contains them is not spent. However, if that wallet is then " +"used to send bitcoin, it may select the UTXO containing the ordinal as an " +"input, and send the inscription or spend it to fees." +msgstr "" +"作为一般说明,在不受支持的钱包中接收序号并不危险。 序号可以发送到任何比特币地" +"址,只要包含它们的 UTXO 没有被花费,它就是安全的。 但是,如果该钱包随后用于发" +"送比特币,它可能会选择包含序号的 UTXO 作为输入,并发送铭文或将其用于费用。" + +#: src/guides/collecting.md:18 +msgid "" +"A [guide](./collecting/sparrow-wallet.md) to creating an `ord`\\-compatible " +"wallet with [Sparrow Wallet](https://sparrowwallet.com/), is available in " +"this handbook." +msgstr "" +"本手册提供了使用[Sparrow Wallet](https://sparrowwallet.com/)创建与 `ord`兼容" +"的钱包的[指南](./collecting/sparrow-wallet.md) 。" + +#: src/guides/collecting.md:21 +msgid "" +"Please note that if you follow this guide, you should not use the wallet you " +"create to send BTC, unless you perform manual coin-selection to avoid " +"sending ordinals." +msgstr "" +"请注意,如果您遵循本指南,则不应使用您创建的钱包发送 BTC,除非您执行手动硬币" +"选择以避免发送序号。" + +#: src/guides/collecting/sparrow-wallet.md:1 +msgid "Collecting Inscriptions and Ordinals with Sparrow Wallet" +msgstr "使用麻雀Sparrow钱包收藏铭文" + +#: src/guides/collecting/sparrow-wallet.md:4 +msgid "" +"Users who cannot or have not yet set up the [ord](https://github.com/" +"ordinals/ord) wallet can receive inscriptions and ordinals with alternative " +"bitcoin wallets, as long as they are _very_ careful about how they spend " +"from that wallet." +msgstr "" +"那些无法活着尚未设置[ord](https://github.com/ordinals/ord) 钱包的用户可以使用" +"其他比特币钱包接收铭文和序数,只要他们在使用该钱包时非常小心。" + +#: src/guides/collecting/sparrow-wallet.md:6 +msgid "" +"This guide gives some basic steps on how to create a wallet with [Sparrow " +"Wallet](https://sparrowwallet.com/) which is compatible with `ord` and can " +"be later imported into `ord`" +msgstr "" +"本指南提供了一些基本步骤,说明如何使用 [Sparrow Wallet](https://" +"sparrowwallet.com/) 创建一个与`ord`兼容的钱包,稍后可以将其导入到`ord`" + +#: src/guides/collecting/sparrow-wallet.md:8 +msgid "⚠️⚠️ Warning!! ⚠️⚠️" +msgstr "⚠️⚠️ 警告!! ⚠️⚠️" + +#: src/guides/collecting/sparrow-wallet.md:9 +msgid "" +"As a general rule if you take this approach, you should use this wallet with " +"the Sparrow software as a receive-only wallet." +msgstr "" +"一般来说,如果你选择这种方法,你应该将这个钱包作为接收款项的钱包,使用Sparrow" +"软件。" + +#: src/guides/collecting/sparrow-wallet.md:11 +msgid "" +"Do not spend any satoshis from this wallet unless you are sure you know what " +"you are doing. You could very easily inadvertently lose access to your " +"ordinals and inscriptions if you don't heed this warning." +msgstr "" +"除非你确定知道自己在做什么,否则不要从这个钱包中花费任何比特币。如果你不注意" +"这个警告,你可能会很容易无意间失去对序数和铭文的访问权限。" + +#: src/guides/collecting/sparrow-wallet.md:13 +msgid "Wallet Setup & Receiving" +msgstr "钱包设置和接收" + +#: src/guides/collecting/sparrow-wallet.md:15 +msgid "" +"Download the Sparrow Wallet from the [releases page](https://sparrowwallet." +"com/download/) for your particular operating system." +msgstr "" +"根据你的操作系统从 [发布页面](https://sparrowwallet.com/download/) 下载" +"Sparrow钱包。" + +#: src/guides/collecting/sparrow-wallet.md:17 +msgid "Select `File -> New Wallet` and create a new wallet called `ord`." +msgstr "选择 `File -> New Wallet`并创建一个名为`ord`的新钱包。" + +#: src/guides/collecting/sparrow-wallet.md:19 +msgid "![](images/wallet_setup_01.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:21 +msgid "" +"Change the `Script Type` to `Taproot (P2TR)` and select the `New or Imported " +"Software Wallet` option." +msgstr "" +"将`Script Type`更改为`Taproot (P2TR)`,然后选择`New or Imported Software " +"Wallet`选项。" + +#: src/guides/collecting/sparrow-wallet.md:23 +msgid "![](images/wallet_setup_02.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:25 +msgid "" +"Select `Use 12 Words` and then click `Generate New`. Leave the passphrase " +"blank." +msgstr "选择`Use 12 Words`,然后点击 `Generate New`。密码短语留空。" + +#: src/guides/collecting/sparrow-wallet.md:27 +msgid "![](images/wallet_setup_03.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:29 +msgid "" +"A new 12 word BIP39 seed phrase will be generated for you. Write this down " +"somewhere safe as this is your backup to get access to your wallet. NEVER " +"share or show this seed phrase to anyone else." +msgstr "" +"将为你生成一个新的12词BIP39种子短语。将此短语写在安全的地方,这是获取钱包访问" +"权限的备份。切勿与他人分享或显示这个种子短语。" + +#: src/guides/collecting/sparrow-wallet.md:31 +msgid "Once you have written down the seed phrase click `Confirm Backup`." +msgstr "一旦你把种子短语写下来,点击 `Confirm Backup`." + +#: src/guides/collecting/sparrow-wallet.md:33 +msgid "![](images/wallet_setup_04.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:35 +msgid "" +"Re-enter the seed phrase which you wrote down, and then click `Create " +"Keystore`." +msgstr "重新输入你记下的种子短语,然后点击 `Create Keystore`." + +#: src/guides/collecting/sparrow-wallet.md:37 +msgid "![](images/wallet_setup_05.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:39 +msgid "Click `Import Keystore`." +msgstr "点击 `Import Keystore`." + +#: src/guides/collecting/sparrow-wallet.md:41 +msgid "![](images/wallet_setup_06.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:43 +msgid "Click `Apply`. Add a password for the wallet if you want to." +msgstr "点击 `Apply`。如果你想的话,可以为钱包添加一个密码。" + +#: src/guides/collecting/sparrow-wallet.md:45 +msgid "![](images/wallet_setup_07.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:47 +msgid "" +"You now have a wallet which is compatible with `ord`, and can be imported " +"into `ord` using the BIP39 Seed Phrase. To receive ordinals or inscriptions, " +"click on the `Receive` tab and copy a new address." +msgstr "" +"你现在有了一个兼容`ord`的钱包,可以使用BIP39种子短语导入到 `ord`。要接收序数" +"或铭文,点击 `Receive`选项卡并复制一个新地址。" + +#: src/guides/collecting/sparrow-wallet.md:49 +msgid "" +"Each time you want to receive you should use a brand-new address, and not re-" +"use existing addresses." +msgstr "每次你想接收时,都应该使用一个全新的地址,而不是重复使用现有的地址。" + +#: src/guides/collecting/sparrow-wallet.md:51 +msgid "" +"Note that bitcoin is different to some other blockchain wallets, in that " +"this wallet can generate an unlimited number of new addresses. You can " +"generate a new address by clicking on the `Get Next Address` button. You can " +"see all of your addresses in the `Addresses` tab of the app." +msgstr "" +"注意,比特币与一些其他区块链钱包不同,这个钱包可以生成无限数量的新地址。你可" +"以通过点击获取下一个地址按钮生成新地址。你可以在应用程序的`Addresses`选项卡中" +"看到所有的地址。" + +#: src/guides/collecting/sparrow-wallet.md:53 +msgid "" +"You can add a label to each address, so you can keep track of what it was " +"used for." +msgstr "你可以给每个地址添加一个标签,这样你就可以跟踪它的用途。" + +#: src/guides/collecting/sparrow-wallet.md:55 +msgid "![](images/wallet_setup_08.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:57 +msgid "Validating / Viewing Received Inscriptions" +msgstr "验证/查看收到的铭文" + +#: src/guides/collecting/sparrow-wallet.md:59 +msgid "" +"Once you have received an inscription you will see a new transaction in the " +"`Transactions` tab of Sparrow, as well as a new UTXO in the `UTXOs` tab." +msgstr "" +"一旦你收到一条铭文,你将在 Sparrow 的 `Transactions` 选项卡中看到一个新的交" +"易,以及在`UTXOs`选项卡中看到一个新的 UTXO。" + +#: src/guides/collecting/sparrow-wallet.md:61 +msgid "" +"Initially this transaction may have an \"Unconfirmed\" status, and you will " +"need to wait for it to be mined into a bitcoin block before it is fully " +"received." +msgstr "" +"最初,这笔交易可能有一个\"未确认\"的状态,你需要等待它被挖矿到一个比特币块" +"中,才算真正收到。" + +#: src/guides/collecting/sparrow-wallet.md:63 +msgid "![](images/validating_viewing_01.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:65 +msgid "" +"To track the status of your transaction you can right-click on it, select " +"`Copy Transaction ID` and then paste that transaction id into [mempool.space]" +"(https://mempool.space)." +msgstr "" +"要跟踪你的交易状态,你可以右键点击它,选择`Copy Transaction ID`,然后将该交" +"易 id 粘贴到 [mempool.space](https://mempool.space)。" + +#: src/guides/collecting/sparrow-wallet.md:67 +msgid "![](images/validating_viewing_02.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:69 +msgid "" +"Once the transaction has confirmed, you can validate and view your " +"inscription by heading over to the `UTXOs` tab, finding the UTXO you want to " +"check, right-clicking on the `Output` and selecting `Copy Transaction " +"Output`. This transaction output id can then be pasted into the [ordinals." +"com](https://ordinals.com) search." +msgstr "" +"一旦交易被确认,你可以通过前往`UTXOs`选项卡,找到你想要检查的 UTXO,右键点击 " +"`Output` 并选择 `Copy Transaction Output` 来验证和查看你的铭文。然后,这个交" +"易输出 id 可以粘贴到 [ordinals.com](https://ordinals.com) 搜索。" + +#: src/guides/collecting/sparrow-wallet.md:72 +msgid "Freezing UTXO's" +msgstr "冻结 UTXO" + +#: src/guides/collecting/sparrow-wallet.md:73 +msgid "" +"As explained above, each of your inscriptions is stored in an Unspent " +"Transaction Output (UTXO). You want to be very careful not to accidentally " +"spend your inscriptions, and one way to make it harder for this to happen is " +"to freeze the UTXO." +msgstr "" +"如上所述,你的每一条铭文都存储在一个未花费的交易输出 (UTXO) 中。你需要非常小" +"心不要意外花费你的铭文,而冻结 UTXO 是使这种情况发生的难度增加的一种方式。" + +#: src/guides/collecting/sparrow-wallet.md:75 +msgid "" +"To do this, go to the `UTXOs` tab, find the UTXO you want to freeze, right-" +"click on the `Output` and select `Freeze UTXO`." +msgstr "" +"要做到这一点,去 UTXOs 选项卡,找到你想要冻结的 `UTXOs`,右键点击 `Output` " +"并选择`Freeze UTXO`。" + +#: src/guides/collecting/sparrow-wallet.md:77 +msgid "" +"This UTXO (Inscription) is now un-spendable within the Sparrow Wallet until " +"you unfreeze it." +msgstr "这个 UTXO (铭文) 现在在 Sparrow 钱包中是不可消费的,直到你解冻它。" + +#: src/guides/collecting/sparrow-wallet.md:79 +msgid "Importing into `ord` wallet" +msgstr "导入 `ord` 钱包" + +#: src/guides/collecting/sparrow-wallet.md:81 +msgid "" +"For details on setting up Bitcoin Core and the `ord` wallet check out the " +"[Inscriptions Guide](../inscriptions.md)" +msgstr "" +"关于设置比特币核心和 `ord` 钱包的详细信息,请查看[铭文指南](../inscriptions." +"md)" + +#: src/guides/collecting/sparrow-wallet.md:83 +msgid "" +"When setting up `ord`, instead of running `ord wallet create` to create a " +"brand-new wallet, you can import your existing wallet using `ord wallet " +"restore \"BIP39 SEED PHRASE\"` using the seed phrase you generated with " +"Sparrow Wallet." +msgstr "" +"设置 `ord` 时,你可以使用 `ord wallet restore \"BIP39 SEED PHRASE\"` 命令和你" +"用Sparrow Wallet生成的种子短语,导入你现有的钱包,而不是运行 `ord wallet " +"create` 来创建一个全新的钱包。" + +#: src/guides/collecting/sparrow-wallet.md:85 +msgid "" +"There is currently a [bug](https://github.com/ordinals/ord/issues/1589) " +"which causes an imported wallet to not be automatically rescanned against " +"the blockchain. To work around this you will need to manually trigger a " +"rescan using the bitcoin core cli: `bitcoin-cli -rpcwallet=ord " +"rescanblockchain 767430`" +msgstr "" +"目前存在一个[程序错误](https://github.com/ordinals/ord/issues/1589) 导致导入" +"的钱包无法自动重新扫描区块链。为解决这个问题,你需要手动触发重新扫描,使用比" +"特币核心命令行界面:" + +#: src/guides/collecting/sparrow-wallet.md:88 +msgid "" +"You can then check your wallet's inscriptions using `ord wallet inscriptions`" +msgstr "然后,你可以使用`ord wallet inscriptions`检查你的钱包的铭文." + +#: src/guides/collecting/sparrow-wallet.md:90 +msgid "" +"Note that if you have previously created a wallet with `ord`, then you will " +"already have a wallet with the default name, and will need to give your " +"imported wallet a different name. You can use the `--wallet` parameter in " +"all `ord` commands to reference a different wallet, eg:" +msgstr "" +"注意,如果你之前已经用 `ord` 创建过一个钱包,那么你已经有一个默认名称的钱包," +"需要给你导入的钱包取一个不同的名称。你可以在所有的 `ord`命令中使用 `--" +"wallet` 参数来引用不同的钱包,例如:" + +#: src/guides/collecting/sparrow-wallet.md:92 +msgid "`ord --wallet ord_from_sparrow wallet restore \"BIP39 SEED PHRASE\"`" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:94 +msgid "`ord --wallet ord_from_sparrow wallet inscriptions`" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:96 +msgid "`bitcoin-cli -rpcwallet=ord_from_sparrow rescanblockchain 767430`" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:98 +msgid "Sending inscriptions with Sparrow Wallet" +msgstr "使用麻雀钱包发送铭文" + +#: src/guides/collecting/sparrow-wallet.md:100 +msgid "⚠️⚠️ Warning ⚠️⚠️" +msgstr "⚠️⚠️ 警告 ⚠️⚠️" + +#: src/guides/collecting/sparrow-wallet.md:101 +msgid "" +"While it is highly recommended that you set up a bitcoin core node and run " +"the `ord` software, there are certain limited ways you can send inscriptions " +"out of Sparrow Wallet in a safe way. Please note that this is not " +"recommended, and you should only do this if you fully understand what you " +"are doing." +msgstr "" +"虽然强烈建议你设置一个比特币核心节点并运行 `ord` 软件,但是你可以通过一些安全" +"的方式在 Sparrow 钱包中发送铭文。请注意,这并不推荐,只有在你完全理解你正在做" +"什么的情况下才能这么做。" + +#: src/guides/collecting/sparrow-wallet.md:103 +msgid "" +"Using the `ord` software will remove much of the complexity we are " +"describing here, as it is able to automatically and safely handle sending " +"inscriptions in an easy way." +msgstr "" +"使用 `ord` 软件将大大简化我们在这里描述的复杂性,因为它能以一种简单的方式自动" +"并安全地处理发送铭文。" + +#: src/guides/collecting/sparrow-wallet.md:105 +msgid "⚠️⚠️ Additional Warning ⚠️⚠️" +msgstr "⚠️⚠️ 额外警告 ⚠️⚠️" + +#: src/guides/collecting/sparrow-wallet.md:106 +msgid "" +"Don't use your sparrow inscriptions wallet to do general sends of non-" +"inscription bitcoin. You can setup a separate wallet in sparrow if you need " +"to do normal bitcoin transactions, and keep your inscriptions wallet " +"separate." +msgstr "" +"不要用你的sparrow麻雀铭文钱包去发送非铭文比特币。如果你需要进行普通的比特币交" +"易,你可以在麻雀中设置一个单独的钱包,并保持你的铭文钱包独立。" + +#: src/guides/collecting/sparrow-wallet.md:108 +msgid "Bitcoin's UTXO model" +msgstr "比特币的UTXO模型" + +#: src/guides/collecting/sparrow-wallet.md:109 +msgid "" +"Before sending any transaction it's important that you have a good mental " +"model for bitcoin's Unspent Transaction Output (UTXO) system. The way " +"Bitcoin works is fundamentally different to many other blockchains such as " +"Ethereum. In Ethereum generally you have a single address in which you store " +"ETH, and you cannot differentiate between any of the ETH - it is just all a " +"single value of the total amount in that address. Bitcoin works very " +"differently in that we generate a new address in the wallet for each " +"receive, and every time you receive sats to an address in your wallet you " +"are creating a new UTXO. Each UTXO can be seen and managed individually. You " +"can select specific UTXO's which you want to spend, and you can choose not " +"to spend certain UTXO's." +msgstr "" +"在发送任何交易之前,你必须对比特币的未消费交易输出(UTXO)系统有一个良好的理" +"解。比特币的工作方式与以太坊等许多其他区块链有着根本的不同。在以太坊中,通常" +"你有一个存储ETH的单一地址,你无法区分其中的任何ETH - 它们只是该地址中的总金额" +"的单一值。而比特币的工作方式完全不同,我们为每个接收生成一个新地址,每次你向" +"钱包中的一个地址接收sats时,你都在创建一个新的UTXO。每个UTXO都可以单独查看和" +"管理。你可以选择想要花费的特定UTXO,也可以选择不花费某些UTXO。" + +#: src/guides/collecting/sparrow-wallet.md:111 +msgid "" +"Some Bitcoin wallets do not expose this level of detail, and they just show " +"you a single summed up value of all the bitcoin in your wallet. However, " +"when sending inscriptions it is important that you use a wallet like Sparrow " +"which allows for UTXO control." +msgstr "" +"有些比特币钱包并不显示这个级别的详细信息,它们只向你显示钱包中所有比特币的单" +"一总和值。然而,当发送铭文时,使用如麻雀这样允许UTXO控制的钱包非常重要。" + +#: src/guides/collecting/sparrow-wallet.md:113 +msgid "Inspecting your inscription before sending" +msgstr "在发送之前检查你的铭文" + +#: src/guides/collecting/sparrow-wallet.md:114 +msgid "" +"Like we have previously described inscriptions are inscribed onto sats, and " +"sats are stored within UTXOs. UTXO's are a collection of satoshis with some " +"particular value of the number of satoshis (the output value). Usually (but " +"not always) the inscription will be inscribed on the first satoshi in the " +"UTXO." +msgstr "" +"如我们之前所述,铭文是刻在聪上的,sats存储在UTXO中。UTXO是具有某个特定数量的" +"satoshi(输出值)的satoshi集合。通常(但不总是)铭文会被刻在UTXO中的第一个" +"satoshi上。" + +#: src/guides/collecting/sparrow-wallet.md:116 +msgid "" +"When inspecting your inscription before sending the main thing you will want " +"to check is which satoshi in the UTXO your inscription is inscribed on." +msgstr "" +"在发送前检查你的铭文时,你主要要检查的是你的铭文刻在UTXO中的哪个satoshi上。" + +#: src/guides/collecting/sparrow-wallet.md:118 +msgid "" +"To do this, you can follow the [Validating / Viewing Received Inscriptions]" +"(./sparrow-wallet.md#validating--viewing-received-inscriptions) described " +"above to find the inscription page for your inscription on ordinals.com" +msgstr "" +"为此,你可以按照上述 [验证/查看收到的铭文](./sparrow-wallet.md#validating--" +"viewing-received-inscriptions)来找到ordinals.com上你的铭文的铭文页面。" + +#: src/guides/collecting/sparrow-wallet.md:120 +msgid "" +"There you will find some metadata about your inscription which looks like " +"the following:" +msgstr "在那里,你会找到一些关于你铭文的元数据,如下所示:" + +#: src/guides/collecting/sparrow-wallet.md:122 +msgid "![](images/sending_01.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:124 +msgid "There is a few of important things to check here:" +msgstr "以下是需要检查的几个重要事项:" + +#: src/guides/collecting/sparrow-wallet.md:125 +msgid "" +"The `output` identifier matches the identifier of the UTXO you are going to " +"send" +msgstr "`output` 标识符与您将要发送的UTXO的标识符匹配" + +#: src/guides/collecting/sparrow-wallet.md:126 +msgid "" +"The `offset` of the inscription is `0` (this means that the inscription is " +"located on the first sat in the UTXO)" +msgstr "铭文的`offset`是 `0` (这意味着铭文位于UTXO的第一个sat上)" + +#: src/guides/collecting/sparrow-wallet.md:127 +msgid "" +"the `output_value` has enough sats to cover the transaction fee (postage) " +"for sending the transaction. The exact amount you will need depends on the " +"fee rate you will select for the transaction" +msgstr "" +"`output_value` 有足够的sats来支付发送交易的交易费(邮资),您需要的确切金额取" +"决于您为交易选择的费率" + +#: src/guides/collecting/sparrow-wallet.md:129 +msgid "" +"If all of the above are true for your inscription, it should be safe for you " +"to send it using the method below." +msgstr "" +"如果以上所有内容对于您的铭文都是正确的,那么您应该可以安全地使用以下方法发送" +"它。" + +#: src/guides/collecting/sparrow-wallet.md:131 +msgid "" +"⚠️⚠️ Be very careful sending your inscription particularly if the `offset` " +"value is not `0`. It is not recommended to use this method if that is the " +"case, as doing so you could accidentally send your inscription to a bitcoin " +"miner unless you know what you are doing." +msgstr "" +"⚠️⚠️ 发送铭文时要非常小心,特别是如果`offset` 值不是`0`。如果是这种情况,不建议" +"使用这种方法,否则您可能会无意中将您的雕文发送给比特币矿工,除非您知道自己在" +"做什么。" + +#: src/guides/collecting/sparrow-wallet.md:133 +msgid "Sending your inscription" +msgstr "发送您的铭文" + +#: src/guides/collecting/sparrow-wallet.md:134 +msgid "" +"To send an inscription navigate to the `UTXOs` tab, and find the UTXO which " +"you previously validated contains your inscription." +msgstr "" +"要发送铭文,请导航到`UTXOs`选项卡,并找到您之前验证包含您的雕文的UTXO。" + +#: src/guides/collecting/sparrow-wallet.md:136 +msgid "" +"If you previously froze the UXTO you will need to right-click on it and " +"unfreeze it." +msgstr "如果您之前冻结了UXTO,您将需要右键单击它并解冻它。" + +#: src/guides/collecting/sparrow-wallet.md:138 +msgid "" +"Select the UTXO you want to send, and ensure that is the _only_ UTXO is " +"selected. You should see `UTXOs 1/1` in the interface. Once you are sure " +"this is the case you can hit `Send Selected`." +msgstr "" +"选择您想要发送的UTXO,并确保这是唯一选中的UTXO。在界面中,您应该看到`UTXOs " +"1/1`。确定这个后,您可以点击`Send Selected`。" + +#: src/guides/collecting/sparrow-wallet.md:140 +msgid "![](images/sending_02.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:142 +msgid "" +"You will then be presented with the transaction construction interface. " +"There is a few things you need to check here to make sure that this is a " +"safe send:" +msgstr "" +"然后,您将看到交易构建界面。在这里,您需要检查几件事以确保这是一个安全的发" +"送:" + +#: src/guides/collecting/sparrow-wallet.md:144 +msgid "" +"The transaction should have only 1 input, and this should be the UTXO with " +"the label you want to send" +msgstr "交易应该只有1个输入,这应该是您想要发送的带有标签的UTXO" + +#: src/guides/collecting/sparrow-wallet.md:145 +msgid "" +"The transaction should have only 1 output, which is the address/label where " +"you want to send the inscription" +msgstr "交易应该只有1个输出,这是您想要发送铭文的地址/标签" + +#: src/guides/collecting/sparrow-wallet.md:147 +msgid "" +"If your transaction looks any different, for example you have multiple " +"inputs, or multiple outputs then this may not be a safe transfer of your " +"inscription, and you should abandon sending until you understand more, or " +"can import into the `ord` wallet." +msgstr "" +"如果您的交易看起来与此不同,例如您有多个输入或多个输出,那么这可能不是一种安" +"全的铭文传输方式,您应该放弃发送,直到您更了解或可以导入到`ord`钱包。" + +#: src/guides/collecting/sparrow-wallet.md:149 +msgid "" +"You should set an appropriate transaction fee, Sparrow will usually " +"recommend a reasonable one, but you can also check [mempool.space](https://" +"mempool.space) to see what the recommended fee rate is for sending a " +"transaction." +msgstr "" +"您应该设置合适的交易费用,Sparrow通常会推荐一个合理的费用,但您也可以查看" +"[mempool.space](https://mempool.space) 以查看发送交易的推荐费率。" + +#: src/guides/collecting/sparrow-wallet.md:151 +msgid "" +"You should add a label for the recipient address, a label like `alice " +"address for inscription #123` would be ideal." +msgstr "" +"您应该为收件人地址添加一个标签,如`alice address for inscription #123`就很理" +"想。" + +#: src/guides/collecting/sparrow-wallet.md:153 +msgid "" +"Once you have checked the transaction is a safe transaction using the checks " +"above, and you are confident to send it you can click `Create Transaction`." +msgstr "" +"在使用上述检查确认交易是安全的交易,并且有信心发送它后,您可以点击`Create " +"Transaction`。" + +#: src/guides/collecting/sparrow-wallet.md:155 +msgid "![](images/sending_03.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:157 +msgid "" +"Here again you can double check that your transaction looks safe, and once " +"you are confident you can click `Finalize Transaction for Signing`." +msgstr "" +"在这里,您可以再次确认您的交易是否安全,在确认后,您可以点击`Finalize " +"Transaction for Signing`。" + +#: src/guides/collecting/sparrow-wallet.md:159 +msgid "![](images/sending_04.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:161 +msgid "Here you can triple check everything before hitting `Sign`." +msgstr "在这里,你可以在点击`Sign`之前再次确认所有内容。" + +#: src/guides/collecting/sparrow-wallet.md:163 +msgid "![](images/sending_05.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:165 +msgid "" +"And then actually you get very very last chance to check everything before " +"hitting `Broadcast Transaction`. Once you broadcast the transaction it is " +"sent to the bitcoin network, and starts being propagated into the mempool." +msgstr "" +"然后实际上在点击`Broadcast Transaction`之前,你有最后一次检查所有内容的机会。" +"一旦你广播交易,它就会被发送到比特币网络,并开始在mempool中传播。" + +#: src/guides/collecting/sparrow-wallet.md:167 +msgid "![](images/sending_06.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:169 +msgid "" +"If you want to track the status of your transaction you can copy the " +"`Transaction Id (Txid)` and paste that into [mempool.space](https://mempool." +"space)" +msgstr "" +"如果你想跟踪你的交易状态,你可以复制`Transaction Id (Txid)`并粘贴到[mempool." +"space](https://mempool.space)" + +#: src/guides/collecting/sparrow-wallet.md:171 +msgid "" +"Once the transaction has confirmed you can check the inscription page on " +"[ordinals.com](https://ordinals.com) to validate that it has moved to the " +"new output location and address." +msgstr "" +"一旦交易确认,你可以在[ordinals.com](https://ordinals.com) 的铭文页面上验证它" +"是否已移动到新的输出位置和地址。" + +#: src/guides/collecting/sparrow-wallet.md:173 +msgid "Troubleshooting" +msgstr "故障排除" + +#: src/guides/collecting/sparrow-wallet.md:175 +msgid "" +"Sparrow wallet is not showing a transaction/UTXO, but I can see it on " +"mempool.space!" +msgstr "Sparrow钱包没有显示交易/UTXO,但我在mempool.space上看到了" + +#: src/guides/collecting/sparrow-wallet.md:177 +msgid "" +"Make sure that your wallet is connected to a bitcoin node. To validate this, " +"head into the `Preferences`\\-> `Server` settings, and click `Edit Existing " +"Connection`." +msgstr "" +"确保你的钱包连接到一个比特币节点。要验证这一点,转到`Preferences`\\-> " +"`Server` 设置,并点击 `Edit Existing Connection`。" + +#: src/guides/collecting/sparrow-wallet.md:179 +msgid "![](images/troubleshooting_01.png)" +msgstr "" + +#: src/guides/collecting/sparrow-wallet.md:181 +msgid "" +"From there you can select a node and click `Test Connection` to validate " +"that Sparrow is able to connect successfully." +msgstr "" +"从那里你可以选择一个节点并点击 `Test Connection` 来验证Sparrow是否能够成功连" +"接。" + +#: src/guides/collecting/sparrow-wallet.md:183 +msgid "![](images/troubleshooting_02.png)" +msgstr "" + +#: src/guides/testing.md:4 +msgid "" +"Ord can be tested using the following flags to specify the test network. For " +"more information on running Bitcoin Core for testing, see [Bitcoin's " +"developer documentation](https://developer.bitcoin.org/examples/testing." +"html)." +msgstr "" +"使用以下标志来指定测试网络,可以测试 Ord。有关运行比特币核心进行测试的更多信" +"息,请参见[比特币的开发者文档](https://developer.bitcoin.org/examples/" +"testing。" + +#: src/guides/testing.md:7 +msgid "" +"Most `ord` commands in [inscriptions](inscriptions.md) and [explorer]" +"(explorer.md) can be run with the following network flags:" +msgstr "" +"大多数在[铭文](inscriptions.md) 和 [浏览器](explorer.md) 中的 `ord`命令可以使" +"用以下网络标志运行:" + +#: src/guides/testing.md:10 +msgid "Network" +msgstr "" + +#: src/guides/testing.md:10 +msgid "Flag" +msgstr "" + +#: src/guides/testing.md:12 +msgid "Testnet" +msgstr "" + +#: src/guides/testing.md:12 +msgid "`--testnet` or `-t`" +msgstr "" + +#: src/guides/testing.md:13 +msgid "Signet" +msgstr "" + +#: src/guides/testing.md:13 +msgid "`--signet` or `-s`" +msgstr "" + +#: src/guides/testing.md:14 +msgid "Regtest" +msgstr "" + +#: src/guides/testing.md:14 +msgid "`--regtest` or `-r`" +msgstr "" + +#: src/guides/testing.md:16 +msgid "Regtest doesn't require downloading the blockchain or indexing ord." +msgstr "Regtest不需要下载区块链或者建立ord索引" + +#: src/guides/testing.md:21 +msgid "Run bitcoind in regtest with:" +msgstr "在regtest里运行bitcoind,使用:" + +#: src/guides/testing.md:22 +msgid "" +"```\n" +"bitcoind -regtest -txindex\n" +"```" +msgstr "" + +#: src/guides/testing.md:25 +msgid "Create a wallet in regtest with:" +msgstr "在regtest里创建钱包" + +#: src/guides/testing.md:26 +msgid "" +"```\n" +"ord -r wallet create\n" +"```" +msgstr "" + +#: src/guides/testing.md:29 +msgid "Get a regtest receive address with:" +msgstr "创建一个regtest接收地址" + +#: src/guides/testing.md:30 +msgid "" +"```\n" +"ord -r wallet receive\n" +"```" +msgstr "" + +#: src/guides/testing.md:33 +msgid "Mine 101 blocks (to unlock the coinbase) with:" +msgstr "挖取101个区块(解锁coinbase)使用:" + +#: src/guides/testing.md:34 +msgid "" +"```\n" +"bitcoin-cli generatetoaddress 101 \n" +"```" +msgstr "" + +#: src/guides/testing.md:37 +msgid "Inscribe in regtest with:" +msgstr "在regtest上铭刻" + +#: src/guides/testing.md:38 +msgid "" +"```\n" +"ord -r wallet inscribe --fee-rate 1 \n" +"```" +msgstr "" + +#: src/guides/testing.md:41 +msgid "Mine the inscription with:" +msgstr "挖取铭文" + +#: src/guides/testing.md:42 +msgid "" +"```\n" +"bitcoin-cli generatetoaddress 1 \n" +"```" +msgstr "" + +#: src/guides/testing.md:45 +msgid "View the inscription in the regtest explorer:" +msgstr "在regtest浏览器里查看铭文" + +#: src/guides/testing.md:46 +msgid "" +"```\n" +"ord -r server\n" +"```" +msgstr "" + +#: src/guides/testing.md:50 +msgid "Testing Recursion" +msgstr "测试递归" + +#: src/guides/testing.md:53 +msgid "" +"When testing out [recursion](../inscriptions/recursion.md), inscribe the " +"dependencies first (example with [p5.js](https://p5js.org):" +msgstr "" +"测试 [recursion](../inscriptions/recursion.md) 时,首先记下依赖项(以 [p5.js]" +"(https://p5js.org) 为例:" + +#: src/guides/testing.md:55 +msgid "" +"```\n" +"ord -r wallet inscribe --fee-rate 1 p5.js\n" +"```" +msgstr "" + +#: src/guides/testing.md:58 +msgid "" +"This should return a `inscription_id` which you can then reference in your " +"recursive inscription." +msgstr "这应该返回一个`inscription_id`,然后您可以在递归铭文中引用它。" + +#: src/guides/testing.md:61 +msgid "" +"ATTENTION: These ids will be different when inscribing on mainnet or signet, " +"so be sure to change those in your recursive inscription for each chain." +msgstr "" +"请注意,在主网和signet上铭刻的时候这些id有所不同,因此请务必更改每个链的递归" +"铭文中的内容。" + +#: src/guides/testing.md:65 +msgid "Then you can inscribe your recursive inscription with:" +msgstr "现在你可以使用以下命令来铭刻你的递归铭文:" + +#: src/guides/testing.md:66 +msgid "" +"```\n" +"ord -r wallet inscribe --fee-rate 1 recursive-inscription.html\n" +"```" +msgstr "" + +#: src/guides/testing.md:69 +msgid "Finally you will have to mine some blocks and start the server:" +msgstr "最终你可以挖取一些区块来开始服务器:" + +#: src/guides/testing.md:70 +msgid "" +"```\n" +"bitcoin-cli generatetoaddress 6 \n" +"ord -r server\n" +"```" +msgstr "" + +#: src/guides/moderation.md:4 +msgid "" +"`ord` includes a block explorer, which you can run locally with `ord server`." +msgstr "`ord` 包含了一个区块浏览器,你可以在本地运行`ord server`." + +#: src/guides/moderation.md:6 +msgid "" +"The block explorer allows viewing inscriptions. Inscriptions are user-" +"generated content, which may be objectionable or unlawful." +msgstr "" +"区块浏览器允许查看铭文。铭文是用户生成的内容,因此可能令人反感或非法的。" + +#: src/guides/moderation.md:9 +msgid "" +"It is the responsibility of each individual who runs an ordinal block " +"explorer instance to understand their responsibilities with respect to " +"unlawful content, and decide what moderation policy is appropriate for their " +"instance." +msgstr "" +"运行ord区块浏览器实例的每个人都有责任了解他们对非法内容的责任,并决定适合他们" +"实例的审核政策。" + +#: src/guides/moderation.md:13 +msgid "" +"In order to prevent particular inscriptions from being displayed on an `ord` " +"instance, they can be included in a YAML config file, which is loaded with " +"the `--config` option." +msgstr "" +"为了防止特定的铭文显示在`ord`实例上,它们可以包含在 YAML 配置文件中,该文件使" +"用 `--config`选项加载。" + +#: src/guides/moderation.md:17 +msgid "" +"To hide inscriptions, first create a config file, with the inscription ID " +"you want to hide:" +msgstr "要隐藏铭文,首先创建一个配置文件,其中包含要隐藏的铭文 ID:" + +#: src/guides/moderation.md:20 +msgid "" +"```yaml\n" +"hidden:\n" +"- 0000000000000000000000000000000000000000000000000000000000000000i0\n" +"```" +msgstr "" + +#: src/guides/moderation.md:25 +msgid "" +"The suggested name for `ord` config files is `ord.yaml`, but any filename " +"can be used." +msgstr "`ord` 配置文件的建议名称是 `ord.yaml`,但可以使用任何文件名。" + +#: src/guides/moderation.md:28 +msgid "Then pass the file to `--config` when starting the server:" +msgstr "然后将文件在服务启动的使用使用 `--config` :" + +#: src/guides/moderation.md:30 +msgid "`ord --config ord.yaml server`" +msgstr "" + +#: src/guides/moderation.md:32 +msgid "" +"Note that the `--config` option comes after `ord` but before the `server` " +"subcommand." +msgstr "请注意, `--config` 选项的位置在 `ord` 之后但是在 `server`子命令前。" + +#: src/guides/moderation.md:35 +msgid "`ord` must be restarted in to load changes to the config file." +msgstr "`ord` 必须重启才可以加载在配置文件中的更改。" + +#: src/guides/moderation.md:37 +msgid "`ordinals.com`" +msgstr "" + +#: src/guides/moderation.md:40 +msgid "" +"The `ordinals.com` instances use `systemd` to run the `ord server` service, " +"which is called `ord`, with a config file located at `/var/lib/ord/ord.yaml`." +msgstr "" +"`ordinals.com` 实例使用 `systemd` 运行名为 `ord`的 `ord server` 服务,配置文" +"件在 `/var/lib/ord/ord.yaml`." + +#: src/guides/moderation.md:43 +msgid "To hide an inscription on `ordinals.com`:" +msgstr "要在 ordinals.com 上隐藏铭文:" + +#: src/guides/moderation.md:45 +msgid "SSH into the server" +msgstr "使用SSH登陆服务器" + +#: src/guides/moderation.md:46 +msgid "Add the inscription ID to `/var/lib/ord/ord.yaml`" +msgstr "在 `/var/lib/ord/ord.yaml`中增加铭文ID" + +#: src/guides/moderation.md:47 +msgid "Restart the service with `systemctl restart ord`" +msgstr "使用 `systemctl restart ord` 重启服务" + +#: src/guides/moderation.md:48 +msgid "Monitor the restart with `journalctl -u ord`" +msgstr "通过 `journalctl -u ord` 重启" + +#: src/guides/moderation.md:50 +msgid "" +"Currently, `ord` is slow to restart, so the site will not come back online " +"immediately." +msgstr "目前,ord 重启速度较慢,因此站点不会立即恢复在线。" + +#: src/guides/reindexing.md:4 +msgid "" +"Sometimes the `ord` database must be reindexed, which means deleting the " +"database and restarting the indexing process with either `ord index run` or " +"`ord server`. Reasons to reindex are:" +msgstr "" +"有时必须重新索引‘ord’数据库,这意味着删除数据库并使用 `ord index run`或`ord " +"server`来重新索引数据库。重新索引的原因是:" + +#: src/guides/reindexing.md:8 +msgid "A new major release of ord, which changes the database scheme" +msgstr "ord 发布新的主要版本,更改了数据库架构" + +#: src/guides/reindexing.md:9 +msgid "The database got corrupted somehow" +msgstr "数据库可能会损坏" + +#: src/guides/reindexing.md:11 +msgid "" +"The database `ord` uses is called [redb](https://github.com/cberner/redb), " +"so we give the index the default file name `index.redb`. By default we store " +"this file in different locations depending on your operating system." +msgstr "" +"`ord` 使用的数据库称为 [redb](https://github.com/cberner/redb),所以我们为索" +"引指定默认文件名‘index.redb’。默认情况下我们存储根据您的操作系统,此文件位于" +"不同的位置。" + +#: src/guides/reindexing.md:15 +msgid "Platform" +msgstr "平台" + +#: src/guides/reindexing.md:15 +msgid "Value" +msgstr "" + +#: src/guides/reindexing.md:17 +msgid "Linux" +msgstr "" + +#: src/guides/reindexing.md:17 +msgid "`$XDG_DATA_HOME`/ord or `$HOME`/.local/share/ord" +msgstr "" + +#: src/guides/reindexing.md:17 +msgid "/home/alice/.local/share/ord" +msgstr "" + +#: src/guides/reindexing.md:18 +msgid "macOS" +msgstr "" + +#: src/guides/reindexing.md:18 +msgid "`$HOME`/Library/Application Support/ord" +msgstr "" + +#: src/guides/reindexing.md:18 +msgid "/Users/Alice/Library/Application Support/ord" +msgstr "" + +#: src/guides/reindexing.md:19 +msgid "Windows" +msgstr "" + +#: src/guides/reindexing.md:19 +msgid "`{FOLDERID_RoamingAppData}`\\\\ord" +msgstr "" + +#: src/guides/reindexing.md:19 +msgid "C:\\Users\\Alice\\AppData\\Roaming\\ord" +msgstr "" + +#: src/guides/reindexing.md:21 +msgid "" +"So to delete the database and reindex on MacOS you would have to run the " +"following commands in the terminal:" +msgstr "因此,要在 MacOS 上删除数据库并重新索引,您必须在终端中执行以下命令:" + +#: src/guides/reindexing.md:24 +msgid "" +"```bash\n" +"rm ~/Library/Application Support/ord/index.redb\n" +"ord index run\n" +"```" +msgstr "" + +#: src/guides/reindexing.md:29 +msgid "" +"You can of course also set the location of the data directory yourself with " +"`ord --data-dir index run` or give it a specific filename and path " +"with `ord --index index run`." +msgstr "" +"您当然也可以自己设置数据目录的位置,`ord --data-dir index run` 或为其指" +"定特定的文件名和路径,使用‘ord --index 索引运行’。" + +#: src/bounties.md:1 +msgid "Ordinal Bounty Hunting Hints" +msgstr "Ordinals赏金计划提示" + +#: src/bounties.md:4 +msgid "" +"The `ord` wallet can send and receive specific satoshis. Additionally, " +"ordinal theory is extremely simple. A clever hacker should be able to write " +"code from scratch to manipulate satoshis using ordinal theory in no time." +msgstr "" +"`ord` 钱包可以发送和接收特定的聪。此外序数理论非常简单。聪明的黑客应该能够很" +"快的从头开始编写代码,使用序数理论来操作聪;" + +#: src/bounties.md:8 +msgid "" +"For more information about ordinal theory, check out the [FAQ](./faq.md) for " +"an overview, the [BIP](https://github.com/ordinals/ord/blob/master/bip." +"mediawiki) for the technical details, and the [ord repo](https://github.com/" +"ordinals/ord) for the `ord` wallet and block explorer." +msgstr "" +"关于序数理论的更多信息,请查阅[FAQ](./faq.md) 来获取概述;查阅[BIP](https://" +"github.com/ordinals/ord/blob/master/bip.mediawiki) 来获取技术细节查阅[ord " +"repo](https://github.com/ordinals/ord)来获取`ord`钱包和浏览器的信息." + +#: src/bounties.md:14 +msgid "" +"Satoshi was the original developer of ordinal theory. However, he knew that " +"others would consider it heretical and dangerous, so he hid his knowledge, " +"and it was lost to the sands of time. This potent theory is only now being " +"rediscovered. You can help by researching rare satoshis." +msgstr "" +"中本聪是序数理论的原始开发者。然而,他知道其他人可能会认为这是异端邪说并且危" +"险,因此他隐藏了自己的知识,使其在时间的沙漠里失传。现在,这个强大的理论被重" +"新发现。您可以通过研究稀有的聪来帮助我们。" + +#: src/bounties.md:19 +msgid "Good luck and godspeed!" +msgstr "祝您一切顺利,好运!" + +#: src/bounty/0.md:1 +msgid "Ordinal Bounty 0" +msgstr "赏金任务 0" + +#: src/bounty/0.md:4 src/bounty/1.md:4 src/bounty/2.md:4 src/bounty/3.md:4 +msgid "Criteria" +msgstr "标准" + +#: src/bounty/0.md:7 +msgid "" +"Send a sat whose ordinal number ends with a zero to the submission address:" +msgstr "发送一个序数以“零”结尾的聪到提交地址:" + +#: src/bounty/0.md:9 +msgid "✅: [1857578125803250](https://ordinals.com/ordinal/1857578125803250)" +msgstr "" + +#: src/bounty/0.md:11 +msgid "❌: [1857578125803251](https://ordinals.com/ordinal/1857578125803251)" +msgstr "" + +#: src/bounty/0.md:13 +msgid "The sat must be the first sat of the output you send." +msgstr "聪必须是你发送的“输出”的第一个聪;" + +#: src/bounty/0.md:15 src/bounty/1.md:14 src/bounty/2.md:15 src/bounty/3.md:63 +msgid "Reward" +msgstr "奖励" + +#: src/bounty/0.md:18 +msgid "100,000 sats" +msgstr "" + +#: src/bounty/0.md:20 src/bounty/1.md:19 src/bounty/2.md:20 src/bounty/3.md:70 +msgid "Submission Address" +msgstr "提交地址" + +#: src/bounty/0.md:23 +msgid "" +"[`1PE7u4wbDP2RqfKN6geD1bG57v9Gj9FXm3`](https://mempool.space/" +"address/1PE7u4wbDP2RqfKN6geD1bG57v9Gj9FXm3)" +msgstr "" + +#: src/bounty/0.md:25 src/bounty/1.md:24 src/bounty/2.md:25 src/bounty/3.md:75 +msgid "Status" +msgstr "状态" + +#: src/bounty/0.md:28 +msgid "" +"Claimed by [@count_null](https://twitter.com/rodarmor/" +"status/1560793241473400833)!" +msgstr "" +"[@count_null](https://twitter.com/rodarmor/status/1560793241473400833)! 赢得" + +#: src/bounty/1.md:1 +msgid "Ordinal Bounty 1" +msgstr "赏金任务 1" + +#: src/bounty/1.md:7 +msgid "" +"The transaction that submits a UTXO containing the oldest sat, i.e., that " +"with the lowest number, amongst all submitted UTXOs will be judged the " +"winner." +msgstr "" +"提交一个包含最古老的聪的UTXO,譬如在所有提交的UTXO中,最小的数字将被判定为获" +"胜者;" + +#: src/bounty/1.md:10 +msgid "" +"The bounty is open for submissions until block 753984—the first block of " +"difficulty adjustment period 374. Submissions included in block 753984 or " +"later will not be considered." +msgstr "" +"赏金在区块高度 753984 前有效,区块高度753984是第一个难度调整期374后的第一个区" +"块。包含或者晚于区块高度 753984 的,将不会被考虑。" + +#: src/bounty/1.md:17 +msgid "200,000 sats" +msgstr "" + +#: src/bounty/1.md:22 +msgid "" +"[`145Z7PFHyVrwiMWwEcUmDgFbmUbQSU9aap`](https://mempool.space/" +"address/145Z7PFHyVrwiMWwEcUmDgFbmUbQSU9aap)" +msgstr "" + +#: src/bounty/1.md:27 +msgid "" +"Claimed by [@ordinalsindex](https://twitter.com/rodarmor/" +"status/1569883266508853251)!" +msgstr "" +"由 [@ordinalsindex](https://twitter.com/rodarmor/status/1569883266508853251)" +"赢得!" + +#: src/bounty/2.md:1 +msgid "Ordinal Bounty 2" +msgstr "赏金任务 2" + +#: src/bounty/2.md:7 +msgid "Send an " +msgstr "发送一个" + +#: src/bounty/2.md:7 +msgid "uncommon" +msgstr "不普通的" + +#: src/bounty/2.md:7 +msgid " sat to the submission address:" +msgstr "聪到下列地址" + +#: src/bounty/2.md:9 +msgid "✅: [347100000000000](https://ordinals.com/sat/347100000000000)" +msgstr "" + +#: src/bounty/2.md:11 +msgid "❌: [6685000001337](https://ordinals.com/sat/6685000001337)" +msgstr "" + +#: src/bounty/2.md:13 +msgid "" +"Confirm that the submission address has not received transactions before " +"submitting your entry. Only the first successful submission will be rewarded." +msgstr "" +"在提交之前确认上述地址并未在你之前收到其他的稀有聪,只有第一个成功的提交可以" +"获得奖励;" + +#: src/bounty/2.md:18 +msgid "300,000 sats" +msgstr "" + +#: src/bounty/2.md:23 +msgid "" +"[`1Hyr94uypwWq5CQffaXHvwUMEyBPp3TUZH`](https://mempool.space/" +"address/1Hyr94uypwWq5CQffaXHvwUMEyBPp3TUZH)" +msgstr "" + +#: src/bounty/2.md:28 +msgid "" +"Claimed by [@utxoset](https://twitter.com/rodarmor/" +"status/1582424455615172608)!" +msgstr "" +"由[@utxoset](https://twitter.com/rodarmor/status/1582424455615172608) 赢得!" + +#: src/bounty/3.md:1 +msgid "Ordinal Bounty 3" +msgstr "赏金任务 3" + +#: src/bounty/3.md:7 +msgid "" +"Ordinal bounty 3 has two parts, both of which are based on _ordinal names_. " +"Ordinal names are a modified base-26 encoding of ordinal numbers. To avoid " +"locking short names inside the unspendable genesis block coinbase reward, " +"ordinal names get _shorter_ as the ordinal number gets _longer_. The name of " +"sat 0, the first sat to be mined is `nvtdijuwxlp` and the name of sat " +"2,099,999,997,689,999, the last sat to be mined, is `a`." +msgstr "" +"任务3有两个部分,都是基于_序数名字_序数名字是把序数数字用修改后的base-26进行" +"的编码.为了避免将短名字锁定在不可花费的创世区块奖励中,随着序数的_变长_,序数" +"名字将变得_更短_ 比如第一个开采的0号聪的名字是`nvtdijuwxlp`,而最后一个被开采" +"的2,099,999,997,689,999号聪的名字,则是 `a`." + +#: src/bounty/3.md:14 +msgid "" +"The bounty is open for submissions until block 840000—the first block after " +"the fourth halvening. Submissions included in block 840000 or later will not " +"be considered." +msgstr "" +"赏金计划开放到区块高度840000-第四次减半后的第一个区块。区块高度840000以及以后" +"的区块将不被考虑。" + +#: src/bounty/3.md:18 +msgid "" +"Both parts use [frequency.tsv](frequency.tsv), a list of words and the " +"number of times they occur in the [Google Books Ngram dataset](http://" +"storage.googleapis.com/books/ngrams/books/datasetsv2.html). filtered to only " +"include the names of sats which will have been mined by the end of the " +"submission period, that appear at least 5000 times in the corpus." +msgstr "" +"两个部分任务都使用 [frequency.tsv](frequency.tsv), 一个单词的清单以及他们在 " +"[Google Books Ngram dataset](http://storage.googleapis.com/books/ngrams/" +"books/datasetsv2.html)中出现的次数。过滤后仅包含在提交期结束时能被挖掘的聪的" +"名字,这些名称在语料库中出现至少5000次。" + +#: src/bounty/3.md:24 +msgid "" +"`frequency.tsv` is a file of tab-separated values. The first column is the " +"word, and the second is the number of times it appears in the corpus. The " +"entries are sorted from least-frequently occurring to most-frequently " +"occurring." +msgstr "" +"`frequency.tsv` 制表符分割值的文件,第一列是单词,第二列是它在语料库里出现的" +"次数。这些条目从出现频率最低到出现频率最高的顺序进行排序。" + +#: src/bounty/3.md:29 +msgid "" +"`frequency.tsv` was compiled using [this program](https://github.com/casey/" +"onegrams)." +msgstr "" +"`frequency.tsv` 使用了[这个程序](https://github.com/casey/onegrams)进行的编" +"译." + +#: src/bounty/3.md:32 +msgid "" +"To search an `ord` wallet for sats with a name in `frequency.tsv`, use the " +"following [`ord`](https://github.com/ordinals/ord) command:" +msgstr "" +"在`ord`钱包里搜索`frequency.tsv`中所包含的聪的名字 , 使用下面的[`ord`]" +"(https://github.com/ordinals/ord)命令: " + +#: src/bounty/3.md:35 +msgid "" +"```\n" +"ord wallet sats --tsv frequency.tsv\n" +"```" +msgstr "" + +#: src/bounty/3.md:39 +msgid "" +"This command requires the sat index, so `--index-sats` must be passed to ord " +"when first creating the index." +msgstr "" +"这个命令需要聪的索引,所以 `--index-sats` 必须在首次创建索引的时候使用。" + +#: src/bounty/3.md:42 +msgid "Part 0" +msgstr "第0部分" + +#: src/bounty/3.md:44 +msgid "_Rare sats pair best with rare words._" +msgstr "_稀有聪和稀有名字的最佳搭配_" + +#: src/bounty/3.md:46 +msgid "" +"The transaction that submits the UTXO containing the sat whose name appears " +"with the lowest number of occurrences in `frequency.tsv` shall be the winner " +"of part 0." +msgstr "" +"提交的交易UTXO中包含的聪的名字,是`frequency.tsv`中出现的最低的频率者,即是第" +"0部分的获胜者。" + +#: src/bounty/3.md:50 +msgid "Part 1" +msgstr "第1部分" + +#: src/bounty/3.md:52 +msgid "_Popularity is the font of value._" +msgstr "_人气是价值的源泉_" + +#: src/bounty/3.md:54 +msgid "" +"The transaction that submits the UTXO containing the sat whose name appears " +"with the highest number of occurrences in `frequency.tsv` shall be the " +"winner of part 1." +msgstr "" +"提交的交易UTXO中包含的聪的名字,是`frequency.tsv`中出现的最高的频率者,是第 " +"1 部分的获胜者。" + +#: src/bounty/3.md:58 +msgid "Tie Breaking" +msgstr "平局情况" + +#: src/bounty/3.md:60 +msgid "" +"In the case of a tie, where two submissions occur with the same frequency, " +"the earlier submission shall be the winner." +msgstr "在平局情况下,如果两个提交的出现了相同的频率,则以较早者提交为获胜者。" + +#: src/bounty/3.md:66 +msgid "Part 0: 200,000 sats" +msgstr "" + +#: src/bounty/3.md:67 +msgid "Part 1: 200,000 sats" +msgstr "" + +#: src/bounty/3.md:68 +msgid "Total: 400,000 sats" +msgstr "" + +#: src/bounty/3.md:73 +msgid "" +"[`17m5rvMpi78zG8RUpCRd6NWWMJtWmu65kg`](https://mempool.space/" +"address/17m5rvMpi78zG8RUpCRd6NWWMJtWmu65kg)" +msgstr "" + +#: src/bounty/3.md:78 +msgid "Unclaimed!" +msgstr "仍然有效!" diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 9f9e404788..2ed5bace41 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -3,6 +3,7 @@ - [Overview](overview.md) - [Digital Artifacts](digital-artifacts.md) - [Inscriptions](inscriptions.md) + - [Provenance](inscriptions/provenance.md) - [Recursion](inscriptions/recursion.md) - [FAQ](faq.md) - [Contributing](contributing.md) @@ -15,6 +16,7 @@ - [Sparrow Wallet](guides/collecting/sparrow-wallet.md) - [Testing](guides/testing.md) - [Moderation](guides/moderation.md) + - [Reindexing](guides/reindexing.md) - [Bounties](bounties.md) - [Bounty 0: 100,000 sats Claimed!](bounty/0.md) - [Bounty 1: 200,000 sats Claimed!](bounty/1.md) diff --git a/docs/src/guides/reindexing.md b/docs/src/guides/reindexing.md new file mode 100644 index 0000000000..1cf3fe4816 --- /dev/null +++ b/docs/src/guides/reindexing.md @@ -0,0 +1,32 @@ +Reindexing +========== + +Sometimes the `ord` database must be reindexed, which means deleting the +database and restarting the indexing process with either `ord index run` or +`ord server`. Reasons to reindex are: + +1. A new major release of ord, which changes the database scheme +2. The database got corrupted somehow + +The database `ord` uses is called [redb](https://github.com/cberner/redb), +so we give the index the default file name `index.redb`. By default we store this +file in different locations depending on your operating system. + +|Platform | Value | Example | +| ------- | ------------------------------------------------ | -------------------------------------------- | +| Linux | `$XDG_DATA_HOME`/ord or `$HOME`/.local/share/ord | /home/alice/.local/share/ord | +| macOS | `$HOME`/Library/Application Support/ord | /Users/Alice/Library/Application Support/ord | +| Windows | `{FOLDERID_RoamingAppData}`\ord | C:\Users\Alice\AppData\Roaming\ord | + +So to delete the database and reindex on MacOS you would have to run the following +commands in the terminal: + +```bash +rm ~/Library/Application Support/ord/index.redb +ord index run +``` + +You can of course also set the location of the data directory yourself with `ord +--data-dir index run` or give it a specific filename and path with `ord +--index index run`. + diff --git a/docs/src/inscriptions.md b/docs/src/inscriptions.md index 056918dd2c..dad8216aa9 100644 --- a/docs/src/inscriptions.md +++ b/docs/src/inscriptions.md @@ -53,14 +53,15 @@ OP_ENDIF First the string `ord` is pushed, to disambiguate inscriptions from other uses of envelopes. -`OP_PUSH 1` indicates that the next push contains the content type, and `OP_PUSH -0` indicates that subsequent data pushes contain the content itself. Multiple data -pushes must be used for large inscriptions, as one of taproot's few -restrictions is that individual data pushes may not be larger than 520 bytes. +`OP_PUSH 1` indicates that the next push contains the content type, and +`OP_PUSH 0`indicates that subsequent data pushes contain the content itself. +Multiple data pushes must be used for large inscriptions, as one of taproot's +few restrictions is that individual data pushes may not be larger than 520 +bytes. The inscription content is contained within the input of a reveal transaction, -and the inscription is made on the first sat of its input. This sat can -then be tracked using the familiar rules of ordinal theory, allowing it to be +and the inscription is made on the first sat of its input. This sat can then be +tracked using the familiar rules of ordinal theory, allowing it to be transferred, bought, sold, lost to fees, and recovered. Content diff --git a/docs/src/inscriptions/provenance.md b/docs/src/inscriptions/provenance.md new file mode 100644 index 0000000000..22d3567c19 --- /dev/null +++ b/docs/src/inscriptions/provenance.md @@ -0,0 +1,82 @@ +Provenance +========== + +The owner of an inscription can create child inscriptions, trustlessly +establishing the provenance of those children on-chain as having been created +by the owner of the parent inscription. This can be used for collections, with +the children of a parent inscription being members of the same collection. + +Children can themselves have children, allowing for complex hierarchies. For +example, an artist might create an inscription representing themselves, with +sub inscriptions representing collections that they create, with the children +of those sub inscriptions being items in those collections. + +### Specification + +To create a child inscription C with parent inscription P: + +- Create an inscribe transaction T as usual for C. +- Spend the parent P in one of the inputs of T. +- Include tag `3`, i.e. `OP_PUSH 3`, in C, with the value of the serialized + binary inscription ID of P, serialized as the 32-byte `TXID`, followed by the + four-byte little-endian `INDEX`, with trailing zeroes omitted. + +_NB_ The bytes of a bitcoin transaction ID are reversed in their text +representation, so the serialized transaction ID will be in the opposite order. + +### Example + +An example of a child inscription of +`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi0`: + +``` +OP_FALSE +OP_IF + OP_PUSH "ord" + OP_PUSH 1 + OP_PUSH "text/plain;charset=utf-8" + OP_PUSH 3 + OP_PUSH 0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 + OP_PUSH 0 + OP_PUSH "Hello, world!" +OP_ENDIF +``` + +Note that the value of tag `3` is binary, not hex, and that for the child +inscription to be recognized as a child, +`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi0` must be +spent as one of the inputs of the inscribe transaction. + +Example encoding of inscription ID +`000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi255`: + +``` +OP_FALSE +OP_IF + … + OP_PUSH 3 + OP_PUSH 0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100ff + … +OP_ENDIF +``` + +And of inscription ID `000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi256`: + +``` +OP_FALSE +OP_IF + … + OP_PUSH 3 + OP_PUSH 0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a090807060504030201000001 + … +OP_ENDIF +``` + +### Notes + +The tag `3` is used because it is the first available odd tag. Unrecognized odd +tags do not make an inscription unbound, so child inscriptions would be +recognized and tracked by old versions of `ord`. + +A collection can be closed by burning the collection's parent inscription, +which guarantees that no more items in the collection can be issued. diff --git a/docs/src/inscriptions/recursion.md b/docs/src/inscriptions/recursion.md index 43a2eabdb7..d11e1bef99 100644 --- a/docs/src/inscriptions/recursion.md +++ b/docs/src/inscriptions/recursion.md @@ -1,9 +1,10 @@ Recursion ========= -An important exception to [sandboxing](../inscriptions.md#sandboxing) is recursion: access to `ord`'s `/content` -endpoint is permitted, allowing inscriptions to access the content of other -inscriptions by requesting `/content/`. +An important exception to [sandboxing](../inscriptions.md#sandboxing) is +recursion: access to `ord`'s `/content` endpoint is permitted, allowing +inscriptions to access the content of other inscriptions by requesting +`/content/`. This has a number of interesting use-cases: diff --git a/docs/theme/index.hbs b/docs/theme/index.hbs new file mode 100644 index 0000000000..04e3db03f7 --- /dev/null +++ b/docs/theme/index.hbs @@ -0,0 +1,387 @@ + + + + + + {{ title }} + {{#if is_print }} + + {{/if}} + {{#if base_url}} + + {{/if}} + + + + {{> head}} + + + + + + {{#if favicon_svg}} + + {{/if}} + {{#if favicon_png}} + + {{/if}} + + + + {{#if print_enable}} + + {{/if}} + + + + {{#if copy_fonts}} + + {{/if}} + + + + + + + + {{#each additional_css}} + + {{/each}} + + {{#if mathjax_support}} + + + {{/if}} + + +
+ + + + + + + + + + + + + + + + + +
+ +
+ {{> header}} + + + + {{#if search_enabled}} + + {{/if}} + + + + +
+
+ {{{ content }}} +
+ + +
+
+ + + +
+ + {{#if live_reload_endpoint}} + + + {{/if}} + + {{#if google_analytics}} + + + {{/if}} + + {{#if playground_line_numbers}} + + {{/if}} + + {{#if playground_copyable}} + + {{/if}} + + {{#if playground_js}} + + + + + + {{/if}} + + {{#if search_js}} + + + + {{/if}} + + + + + + + {{#each additional_js}} + + {{/each}} + + {{#if is_print}} + {{#if mathjax_support}} + + {{else}} + + {{/if}} + {{/if}} + +
+ + diff --git a/justfile b/justfile index 884191de5b..80ca3a77c2 100644 --- a/justfile +++ b/justfile @@ -157,11 +157,18 @@ build-snapshots: printf "$height_limit\t$((b - a))\n" >> time.txt done -serve-docs: - mdbook serve docs --open +serve-docs: build-docs + open http://127.0.0.1:8080 + python3 -m http.server --directory docs/build/html --bind 127.0.0.1 8080 build-docs: - mdbook build docs + #!/usr/bin/env bash + mdbook build docs -d build + for lang in "zh" "ja"; do + MDBOOK_BOOK__LANGUAGE=$lang \ + mdbook build docs -d build/$lang + mv docs/build/$lang/html docs/build/html/$lang + done update-changelog: echo >> CHANGELOG.md diff --git a/src/arguments.rs b/src/arguments.rs index 17c6050ebb..f348c5cfa3 100644 --- a/src/arguments.rs +++ b/src/arguments.rs @@ -1,11 +1,21 @@ -use super::*; +use { + super::*, + clap::builder::styling::{AnsiColor, Effects, Styles}, +}; #[derive(Debug, Parser)] -#[clap(version)] +#[command( + version, + styles = Styles::styled() + .header(AnsiColor::Green.on_default() | Effects::BOLD) + .usage(AnsiColor::Green.on_default() | Effects::BOLD) + .literal(AnsiColor::Blue.on_default() | Effects::BOLD) + .placeholder(AnsiColor::Cyan.on_default())) +] pub(crate) struct Arguments { - #[clap(flatten)] + #[command(flatten)] pub(crate) options: Options, - #[clap(subcommand)] + #[command(subcommand)] pub(crate) subcommand: Subcommand, } diff --git a/src/chain.rs b/src/chain.rs index 5b3ed06c2f..da19662a5d 100644 --- a/src/chain.rs +++ b/src/chain.rs @@ -4,9 +4,9 @@ use {super::*, clap::ValueEnum}; #[serde(rename_all = "kebab-case")] pub enum Chain { #[default] - #[clap(alias("main"))] + #[value(alias("main"))] Mainnet, - #[clap(alias("test"))] + #[value(alias("test"))] Testnet, Signet, Regtest, diff --git a/src/fee_rate.rs b/src/fee_rate.rs index 9a0290040d..9f85ac5133 100644 --- a/src/fee_rate.rs +++ b/src/fee_rate.rs @@ -23,7 +23,7 @@ impl TryFrom for FeeRate { } impl FeeRate { - pub(crate) fn fee(&self, vsize: usize) -> Amount { + pub fn fee(&self, vsize: usize) -> Amount { #[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_sign_loss)] Amount::from_sat((self.0 * vsize as f64).round() as u64) diff --git a/src/index.rs b/src/index.rs index ee956ddc00..68f0fc1a46 100644 --- a/src/index.rs +++ b/src/index.rs @@ -4,7 +4,6 @@ use { BlockHashValue, Entry, InscriptionEntry, InscriptionEntryValue, InscriptionIdValue, OutPointValue, SatPointValue, SatRange, }, - index::block_index::BlockIndex, reorg::*, updater::Updater, }, @@ -23,14 +22,13 @@ use { std::io::{BufWriter, Read, Write}, }; -pub mod block_index; mod entry; mod fetcher; mod reorg; mod rtx; mod updater; -const SCHEMA_VERSION: u64 = 5; +const SCHEMA_VERSION: u64 = 6; macro_rules! define_table { ($name:ident, $key:ty, $value:ty) => { @@ -45,15 +43,17 @@ macro_rules! define_multimap_table { }; } +define_multimap_table! { INSCRIPTION_ID_TO_CHILDREN, &InscriptionIdValue, &InscriptionIdValue } +define_multimap_table! { SATPOINT_TO_INSCRIPTION_ID, &SatPointValue, &InscriptionIdValue } +define_multimap_table! { SAT_TO_INSCRIPTION_ID, u64, &InscriptionIdValue } define_table! { HEIGHT_TO_BLOCK_HASH, u64, &BlockHashValue } +define_table! { HEIGHT_TO_LAST_INSCRIPTION_NUMBER, u64, (i64, i64) } define_table! { INSCRIPTION_ID_TO_INSCRIPTION_ENTRY, &InscriptionIdValue, InscriptionEntryValue } define_table! { INSCRIPTION_ID_TO_SATPOINT, &InscriptionIdValue, &SatPointValue } define_table! { INSCRIPTION_NUMBER_TO_INSCRIPTION_ID, i64, &InscriptionIdValue } define_table! { OUTPOINT_TO_SAT_RANGES, &OutPointValue, &[u8] } define_table! { OUTPOINT_TO_VALUE, &OutPointValue, u64} define_table! { REINSCRIPTION_ID_TO_SEQUENCE_NUMBER, &InscriptionIdValue, u64 } -define_multimap_table! { SATPOINT_TO_INSCRIPTION_ID, &SatPointValue, &InscriptionIdValue } -define_multimap_table! { SAT_TO_INSCRIPTION_ID, u64, &InscriptionIdValue } define_table! { SAT_TO_SATPOINT, u64, &SatPointValue } define_table! { STATISTIC_TO_COUNT, u64, u64 } define_table! { WRITE_TRANSACTION_STARTING_BLOCK_COUNT_TO_TIMESTAMP, u64, u128 } @@ -233,14 +233,16 @@ impl Index { tx.set_durability(durability); + tx.open_multimap_table(INSCRIPTION_ID_TO_CHILDREN)?; + tx.open_multimap_table(SATPOINT_TO_INSCRIPTION_ID)?; + tx.open_multimap_table(SAT_TO_INSCRIPTION_ID)?; tx.open_table(HEIGHT_TO_BLOCK_HASH)?; + tx.open_table(HEIGHT_TO_LAST_INSCRIPTION_NUMBER)?; tx.open_table(INSCRIPTION_ID_TO_INSCRIPTION_ENTRY)?; tx.open_table(INSCRIPTION_ID_TO_SATPOINT)?; tx.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?; tx.open_table(OUTPOINT_TO_VALUE)?; tx.open_table(REINSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; - tx.open_multimap_table(SATPOINT_TO_INSCRIPTION_ID)?; - tx.open_multimap_table(SAT_TO_INSCRIPTION_ID)?; tx.open_table(SAT_TO_SATPOINT)?; tx.open_table(WRITE_TRANSACTION_STARTING_BLOCK_COUNT_TO_TIMESTAMP)?; @@ -563,14 +565,14 @@ impl Index { } pub(crate) fn blocks(&self, take: usize) -> Result> { - let mut blocks = Vec::new(); - let rtx = self.begin_read()?; let block_count = rtx.block_count()?; let height_to_block_hash = rtx.0.open_table(HEIGHT_TO_BLOCK_HASH)?; + let mut blocks = Vec::with_capacity(block_count.try_into().unwrap()); + for next in height_to_block_hash.range(0..block_count)?.rev().take(take) { let next = next?; blocks.push((next.0.value(), Entry::load(*next.1.value()))); @@ -636,18 +638,35 @@ impl Index { self.client.get_block(&hash).into_option() } + pub(crate) fn get_children_by_inscription_id( + &self, + inscription_id: InscriptionId, + ) -> Result> { + self + .database + .begin_read()? + .open_multimap_table(INSCRIPTION_ID_TO_CHILDREN)? + .get(&inscription_id.store())? + .map(|result| { + result + .map(|inscription_id| InscriptionId::load(*inscription_id.value())) + .map_err(|err| err.into()) + }) + .collect() + } + pub(crate) fn get_inscription_ids_by_sat(&self, sat: Sat) -> Result> { let rtx = &self.database.begin_read()?; let mut ids = rtx .open_multimap_table(SAT_TO_INSCRIPTION_ID)? .get(&sat.n())? - .filter_map(|result| { + .map(|result| { result - .ok() .map(|inscription_id| InscriptionId::load(*inscription_id.value())) + .map_err(|err| err.into()) }) - .collect::>(); + .collect::>>()?; if ids.len() > 1 { let re_id_to_seq_num = rtx.open_table(REINSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; @@ -934,12 +953,68 @@ impl Index { Ok((inscriptions, prev, next, lowest, highest)) } - pub(crate) fn get_inscriptions_in_block( + pub(crate) fn get_inscriptions_in_block(&self, block_height: u64) -> Result> { + let rtx = self.database.begin_read()?; + + let height_to_last_inscription_number = rtx.open_table(HEIGHT_TO_LAST_INSCRIPTION_NUMBER)?; + let inscription_id_by_number = rtx.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?; + + let block_inscriptions = match ( + height_to_last_inscription_number + .get(block_height.saturating_sub(1))? + .map(|ag| ag.value()) + .unwrap_or((0, -1)), + height_to_last_inscription_number + .get(&block_height)? + .map(|ag| ag.value()), + ) { + ((oldest_blessed, oldest_cursed), Some((newest_blessed, newest_cursed))) => { + ((newest_cursed + 1)..=oldest_cursed) + .chain(oldest_blessed..newest_blessed) + .map(|num| match inscription_id_by_number.get(&num) { + Ok(Some(inscription_id)) => Ok(InscriptionId::load(*inscription_id.value())), + Ok(None) => Err(anyhow!( + "could not find inscription for inscription number {num}" + )), + Err(err) => Err(anyhow!(err)), + }) + .collect::>>()? + } + _ => Vec::new(), + }; + + Ok(block_inscriptions) + } + + pub(crate) fn get_highest_paying_inscriptions_in_block( &self, - block_index: &BlockIndex, block_height: u64, - ) -> Result> { - block_index.get_inscriptions_in_block(self, block_height) + n: usize, + ) -> Result<(Vec, usize)> { + let inscription_ids = self.get_inscriptions_in_block(block_height)?; + + let mut inscription_to_fee: Vec<(InscriptionId, u64)> = Vec::new(); + for id in &inscription_ids { + inscription_to_fee.push(( + *id, + self + .get_inscription_entry(*id)? + .ok_or_else(|| anyhow!("could not get entry for inscription {id}"))? + .fee, + )); + } + + inscription_to_fee.sort_by_key(|(_, fee)| *fee); + + Ok(( + inscription_to_fee + .iter() + .map(|(id, _)| *id) + .rev() + .take(n) + .collect(), + inscription_ids.len(), + )) } pub(crate) fn get_feed_inscriptions(&self, n: usize) -> Result> { @@ -1282,8 +1357,7 @@ mod tests { fn inscriptions_below_first_inscription_height_are_skipped() { let inscription = inscription("text/plain;charset=utf-8", "hello"); let template = TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription.to_witness(), + inputs: &[(1, 0, 0, inscription.to_witness())], ..Default::default() }; @@ -1363,7 +1437,7 @@ mod tests { context.mine_blocks(1); let split_coinbase_output = TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], outputs: 2, fee: 0, ..Default::default() @@ -1389,7 +1463,7 @@ mod tests { context.mine_blocks(2); let merge_coinbase_outputs = TransactionTemplate { - inputs: &[(1, 0, 0), (2, 0, 0)], + inputs: &[(1, 0, 0, Default::default()), (2, 0, 0, Default::default())], fee: 0, ..Default::default() }; @@ -1412,7 +1486,7 @@ mod tests { context.mine_blocks(1); let fee_paying_tx = TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], outputs: 2, fee: 10, ..Default::default() @@ -1446,12 +1520,12 @@ mod tests { context.mine_blocks(2); let first_fee_paying_tx = TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], fee: 10, ..Default::default() }; let second_fee_paying_tx = TransactionTemplate { - inputs: &[(2, 0, 0)], + inputs: &[(2, 0, 0, Default::default())], fee: 10, ..Default::default() }; @@ -1480,7 +1554,7 @@ mod tests { context.mine_blocks(1); let no_value_output = TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], fee: 50 * COIN_VALUE, ..Default::default() }; @@ -1499,7 +1573,7 @@ mod tests { context.mine_blocks(1); let no_value_output = TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], fee: 50 * COIN_VALUE, ..Default::default() }; @@ -1507,7 +1581,7 @@ mod tests { context.mine_blocks(1); let no_value_input = TransactionTemplate { - inputs: &[(2, 1, 0)], + inputs: &[(2, 1, 0, Default::default())], fee: 0, ..Default::default() }; @@ -1525,7 +1599,7 @@ mod tests { let context = Context::builder().arg("--index-sats").build(); context.mine_blocks(1); context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], fee: 0, ..Default::default() }); @@ -1608,7 +1682,7 @@ mod tests { let context = Context::builder().arg("--index-sats").build(); context.mine_blocks(1); let spend_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], fee: 0, ..Default::default() }); @@ -1628,8 +1702,7 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -1653,7 +1726,7 @@ mod tests { context.mine_blocks(1); context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], fee: 50 * 100_000_000, ..Default::default() }); @@ -1661,8 +1734,7 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 1, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(2, 1, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); @@ -1682,7 +1754,7 @@ mod tests { context.mine_blocks(1); context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(4, 0, 0)], + inputs: &[(4, 0, 0, Default::default())], fee: 50 * 100_000_000, ..Default::default() }); @@ -1690,8 +1762,7 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(5, 1, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(5, 1, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); @@ -1716,8 +1787,7 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -1734,7 +1804,7 @@ mod tests { ); let send_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 0, 0), (2, 1, 0)], + inputs: &[(2, 0, 0, Default::default()), (2, 1, 0, Default::default())], ..Default::default() }); @@ -1760,8 +1830,7 @@ mod tests { context.mine_blocks(2); let first_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); @@ -1771,8 +1840,7 @@ mod tests { }; let second_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 0, 0)], - witness: inscription("text/png", [1; 100]).to_witness(), + inputs: &[(2, 0, 0, inscription("text/png", [1; 100]).to_witness())], ..Default::default() }); let second_inscription_id = InscriptionId { @@ -1783,7 +1851,7 @@ mod tests { context.mine_blocks(1); let merged_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(3, 1, 0), (3, 2, 0)], + inputs: &[(3, 1, 0, Default::default()), (3, 2, 0, Default::default())], ..Default::default() }); @@ -1821,8 +1889,7 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -1839,7 +1906,7 @@ mod tests { ); let send_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 0, 0), (2, 1, 0)], + inputs: &[(2, 0, 0, Default::default()), (2, 1, 0, Default::default())], outputs: 2, ..Default::default() }); @@ -1870,8 +1937,7 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -1888,7 +1954,7 @@ mod tests { ); let send_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 0, 0), (2, 1, 0)], + inputs: &[(2, 0, 0, Default::default()), (2, 1, 0, Default::default())], ..Default::default() }); @@ -1914,8 +1980,7 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -1923,7 +1988,7 @@ mod tests { context.mine_blocks(1); context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 1, 0)], + inputs: &[(2, 1, 0, Default::default())], fee: 50 * COIN_VALUE, ..Default::default() }); @@ -1950,8 +2015,7 @@ mod tests { context.mine_blocks(2); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -1959,7 +2023,7 @@ mod tests { context.mine_blocks(1); context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 0, 0), (3, 1, 0)], + inputs: &[(2, 0, 0, Default::default()), (3, 1, 0, Default::default())], fee: 50 * COIN_VALUE, ..Default::default() }); @@ -1986,9 +2050,8 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], fee: 50 * COIN_VALUE, - witness: inscription("text/plain", "hello").to_witness(), ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -2015,9 +2078,8 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], fee: 50 * COIN_VALUE, - witness: inscription("text/plain", "hello").to_witness(), ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -2041,9 +2103,8 @@ mod tests { context.mine_blocks(1); let first_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], fee: 50 * COIN_VALUE, - witness: inscription("text/plain", "hello").to_witness(), ..Default::default() }); let first_inscription_id = InscriptionId { @@ -2055,9 +2116,8 @@ mod tests { context.mine_blocks(1); let second_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(3, 0, 0)], + inputs: &[(3, 0, 0, inscription("text/plain", "hello").to_witness())], fee: 50 * COIN_VALUE, - witness: inscription("text/plain", "hello").to_witness(), ..Default::default() }); let second_inscription_id = InscriptionId { @@ -2172,16 +2232,15 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 0, 0)], + inputs: &[(2, 0, 0, inscription("text/plain", "hello").to_witness())], outputs: 2, - witness: inscription("text/plain", "hello").to_witness(), ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; context.mine_blocks(1); context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(3, 1, 1), (3, 1, 0)], + inputs: &[(3, 1, 1, Default::default()), (3, 1, 0, Default::default())], fee: 50 * COIN_VALUE, ..Default::default() }); @@ -2204,9 +2263,8 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], outputs: 2, - witness: inscription("text/plain", "hello").to_witness(), output_values: &[0, 50 * COIN_VALUE], ..Default::default() }); @@ -2230,9 +2288,8 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], fee: 50 * COIN_VALUE, - witness: inscription("text/plain", "hello").to_witness(), ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -2340,8 +2397,7 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); @@ -2366,7 +2422,7 @@ mod tests { ); let send_id = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 1, 0)], + inputs: &[(2, 1, 0, Default::default())], ..Default::default() }); @@ -2399,8 +2455,7 @@ mod tests { context.mine_blocks(1); let first = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); @@ -2435,8 +2490,7 @@ mod tests { ); let second = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 1, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(2, 1, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); @@ -2485,8 +2539,7 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -2512,8 +2565,7 @@ mod tests { for i in 0..103 { let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(i + 1, 0, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(i + 1, 0, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); ids.push(InscriptionId { txid, index: 0 }); @@ -2569,6 +2621,51 @@ mod tests { } } + #[test] + fn unrecognized_even_field_inscriptions_are_cursed_and_unbound() { + for context in Context::configurations() { + context.mine_blocks(1); + + let witness = envelope(&[ + b"ord", + &[1], + b"text/plain;charset=utf-8", + &[2], + b"bar", + &[4], + b"ord", + ]); + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, witness)], + ..Default::default() + }); + + let inscription_id = InscriptionId { txid, index: 0 }; + + context.mine_blocks(1); + + context.index.assert_inscription_location( + inscription_id, + SatPoint { + outpoint: unbound_outpoint(), + offset: 0, + }, + None, + ); + + assert_eq!( + context + .index + .get_inscription_entry(inscription_id) + .unwrap() + .unwrap() + .number, + -1 + ); + } + } + #[test] // https://github.com/ordinals/ord/issues/2062 fn zero_value_transaction_inscription_not_cursed_but_unbound() { @@ -2576,7 +2673,7 @@ mod tests { context.mine_blocks(1); context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], fee: 50 * 100_000_000, ..Default::default() }); @@ -2584,8 +2681,7 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 1, 0)], - witness: inscription("text/plain", "hello").to_witness(), + inputs: &[(2, 1, 0, inscription("text/plain", "hello").to_witness())], ..Default::default() }); @@ -2614,6 +2710,52 @@ mod tests { } } + #[test] + fn transaction_with_inscription_inside_zero_value_2nd_input_should_be_unbound_and_cursed() { + for context in Context::configurations() { + context.mine_blocks(1); + + // create zero value input + context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, Default::default())], + fee: 50 * 100_000_000, + ..Default::default() + }); + + context.mine_blocks(1); + + let witness = inscription("text/plain", "hello").to_witness(); + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(2, 0, 0, witness.clone()), (2, 1, 0, witness.clone())], + ..Default::default() + }); + + let second_inscription_id = InscriptionId { txid, index: 1 }; + + context.mine_blocks(1); + + context.index.assert_inscription_location( + second_inscription_id, + SatPoint { + outpoint: unbound_outpoint(), + offset: 0, + }, + None, + ); + + assert_eq!( + context + .index + .get_inscription_entry(second_inscription_id) + .unwrap() + .unwrap() + .number, + -1 + ); + } + } + #[test] fn multiple_inscriptions_in_same_tx_all_but_first_input_are_cursed() { for context in Context::configurations() { @@ -2624,8 +2766,11 @@ mod tests { let witness = envelope(&[b"ord", &[1], b"text/plain;charset=utf-8", &[], b"bar"]); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0), (2, 0, 0), (3, 0, 0)], - witness, + inputs: &[ + (1, 0, 0, witness.clone()), + (2, 0, 0, witness.clone()), + (3, 0, 0, witness.clone()), + ], ..Default::default() }); @@ -2729,8 +2874,8 @@ mod tests { let witness = Witness::from_slice(&[script.into_bytes(), Vec::new()]); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness, + inputs: &[(1, 0, 0, witness)], + ..Default::default() }); @@ -2836,8 +2981,11 @@ mod tests { let witness = Witness::from_slice(&[script.into_bytes(), Vec::new()]); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0), (2, 0, 0), (3, 0, 0)], - witness, // the witness is replicated over all inputs + inputs: &[ + (1, 0, 0, witness.clone()), + (2, 0, 0, witness.clone()), + (3, 0, 0, witness.clone()), + ], ..Default::default() }); @@ -2941,8 +3089,7 @@ mod tests { let witness = Witness::from_slice(&[script.into_bytes(), Vec::new()]); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness, + inputs: &[(1, 0, 0, witness)], fee: 33, ..Default::default() }); @@ -2983,8 +3130,7 @@ mod tests { let witness = envelope(&[b"ord", &[1], b"text/plain;charset=utf-8", &[], b"bar"]); let cursed_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0), (2, 0, 0)], - witness, + inputs: &[(1, 0, 0, witness.clone()), (2, 0, 0, witness.clone())], outputs: 2, ..Default::default() }); @@ -3027,8 +3173,7 @@ mod tests { ]); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(3, 1, 1)], - witness, + inputs: &[(3, 1, 1, witness)], ..Default::default() }); @@ -3066,8 +3211,7 @@ mod tests { let witness = envelope(&[b"ord", &[1], b"text/plain;charset=utf-8", &[], b"bar"]); let cursed_txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0), (2, 0, 0)], - witness, + inputs: &[(1, 0, 0, witness.clone()), (2, 0, 0, witness.clone())], outputs: 2, ..Default::default() }); @@ -3110,8 +3254,7 @@ mod tests { ]); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(3, 1, 1)], - witness, + inputs: &[(3, 1, 1, witness)], ..Default::default() }); @@ -3147,8 +3290,7 @@ mod tests { ]); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(4, 1, 0)], - witness, + inputs: &[(4, 1, 0, witness)], ..Default::default() }); @@ -3198,8 +3340,12 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 1, + 0, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); @@ -3208,8 +3354,12 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 1, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 2, + 1, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); @@ -3217,8 +3367,12 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(3, 1, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 3, + 1, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); @@ -3249,8 +3403,12 @@ mod tests { let mut inscription_ids = vec![]; for i in 1..=5 { let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(i, if i == 1 { 0 } else { 1 }, 0)], // for the first inscription use coinbase, otherwise use the previous tx - witness: inscription("text/plain;charset=utf-8", &format!("hello {}", i)).to_witness(), + inputs: &[( + i, + if i == 1 { 0 } else { 1 }, + 0, + inscription("text/plain;charset=utf-8", &format!("hello {}", i)).to_witness(), + )], // for the first inscription use coinbase, otherwise use the previous tx ..Default::default() }); @@ -3291,8 +3449,12 @@ mod tests { let mut inscription_ids = vec![]; for i in 1..=21 { let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(i, if i == 1 { 0 } else { 1 }, 0)], // for the first inscription use coinbase, otherwise use the previous tx - witness: inscription("text/plain;charset=utf-8", &format!("hello {}", i)).to_witness(), + inputs: &[( + i, + if i == 1 { 0 } else { 1 }, + 0, + inscription("text/plain;charset=utf-8", &format!("hello {}", i)).to_witness(), + )], // for the first inscription use coinbase, otherwise use the previous tx ..Default::default() }); @@ -3336,8 +3498,12 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 1, + 0, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); let first_id = InscriptionId { txid, index: 0 }; @@ -3353,8 +3519,12 @@ mod tests { .assert_inscription_location(first_id, first_location, Some(50 * COIN_VALUE)); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 0, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 2, + 0, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); let second_id = InscriptionId { txid, index: 0 }; @@ -3388,8 +3558,12 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 1, + 0, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); let first_id = InscriptionId { txid, index: 0 }; @@ -3401,8 +3575,12 @@ mod tests { context.mine_blocks(10); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 0, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 2, + 0, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); let second_id = InscriptionId { txid, index: 0 }; @@ -3443,8 +3621,12 @@ mod tests { context.mine_blocks(1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 1, + 0, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); @@ -3457,8 +3639,12 @@ mod tests { }; let txid = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 0, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 2, + 0, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); @@ -3487,4 +3673,308 @@ mod tests { .assert_inscription_location(first_id, first_location, Some(50 * COIN_VALUE)); } } + + #[test] + fn inscription_without_parent_tag_has_no_parent_entry() { + for context in Context::configurations() { + context.mine_blocks(1); + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], + ..Default::default() + }); + + context.mine_blocks(1); + + let inscription_id = InscriptionId { txid, index: 0 }; + + assert!(context + .index + .get_inscription_entry(inscription_id) + .unwrap() + .unwrap() + .parent + .is_none()); + } + } + + #[test] + fn inscription_with_parent_tag_without_parent_has_no_parent_entry() { + for context in Context::configurations() { + context.mine_blocks(1); + + let parent_txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], + ..Default::default() + }); + + context.mine_blocks(1); + + let parent_inscription_id = InscriptionId { + txid: parent_txid, + index: 0, + }; + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[( + 2, + 0, + 0, + Inscription { + content_type: Some("text/plain".into()), + body: Some("hello".into()), + parent: Some(parent_inscription_id.parent_value()), + unrecognized_even_field: false, + } + .to_witness(), + )], + ..Default::default() + }); + + context.mine_blocks(1); + + let inscription_id = InscriptionId { txid, index: 0 }; + + assert!(context + .index + .get_inscription_entry(inscription_id) + .unwrap() + .unwrap() + .parent + .is_none()); + } + } + + #[test] + fn inscription_with_parent_tag_and_parent_has_parent_entry() { + for context in Context::configurations() { + context.mine_blocks(1); + + let parent_txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], + ..Default::default() + }); + + context.mine_blocks(1); + + let parent_inscription_id = InscriptionId { + txid: parent_txid, + index: 0, + }; + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[( + 2, + 1, + 0, + Inscription { + content_type: Some("text/plain".into()), + body: Some("hello".into()), + parent: Some(parent_inscription_id.parent_value()), + unrecognized_even_field: false, + } + .to_witness(), + )], + ..Default::default() + }); + + context.mine_blocks(1); + + let inscription_id = InscriptionId { txid, index: 0 }; + + assert_eq!( + context + .index + .get_inscription_entry(inscription_id) + .unwrap() + .unwrap() + .parent + .unwrap(), + parent_inscription_id + ); + + assert_eq!( + context + .index + .get_children_by_inscription_id(parent_inscription_id) + .unwrap(), + vec![inscription_id] + ); + } + } + + #[test] + fn parents_can_be_in_preceding_input() { + for context in Context::configurations() { + context.mine_blocks(1); + + let parent_txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], + ..Default::default() + }); + + context.mine_blocks(2); + + let parent_inscription_id = InscriptionId { + txid: parent_txid, + index: 0, + }; + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[ + (2, 1, 0, Default::default()), + ( + 3, + 0, + 0, + Inscription { + content_type: Some("text/plain".into()), + body: Some("hello".into()), + parent: Some(parent_inscription_id.parent_value()), + unrecognized_even_field: false, + } + .to_witness(), + ), + ], + ..Default::default() + }); + + context.mine_blocks(1); + + let inscription_id = InscriptionId { txid, index: 0 }; + + assert_eq!( + context + .index + .get_inscription_entry(inscription_id) + .unwrap() + .unwrap() + .parent + .unwrap(), + parent_inscription_id + ); + + assert_eq!( + context + .index + .get_children_by_inscription_id(parent_inscription_id) + .unwrap(), + vec![inscription_id] + ); + } + } + + #[test] + fn parents_can_be_in_following_input() { + for context in Context::configurations() { + context.mine_blocks(1); + + let parent_txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], + ..Default::default() + }); + + context.mine_blocks(2); + + let parent_inscription_id = InscriptionId { + txid: parent_txid, + index: 0, + }; + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[ + ( + 3, + 0, + 0, + Inscription { + content_type: Some("text/plain".into()), + body: Some("hello".into()), + parent: Some(parent_inscription_id.parent_value()), + unrecognized_even_field: false, + } + .to_witness(), + ), + (2, 1, 0, Default::default()), + ], + ..Default::default() + }); + + context.mine_blocks(1); + + let inscription_id = InscriptionId { txid, index: 0 }; + + assert_eq!( + context + .index + .get_inscription_entry(inscription_id) + .unwrap() + .unwrap() + .parent + .unwrap(), + parent_inscription_id + ); + + assert_eq!( + context + .index + .get_children_by_inscription_id(parent_inscription_id) + .unwrap(), + vec![inscription_id] + ); + } + } + + #[test] + fn inscription_with_invalid_parent_tag_and_parent_has_no_parent_entry() { + for context in Context::configurations() { + context.mine_blocks(1); + + let parent_txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], + ..Default::default() + }); + + context.mine_blocks(1); + + let parent_inscription_id = InscriptionId { + txid: parent_txid, + index: 0, + }; + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[( + 2, + 1, + 0, + Inscription { + content_type: Some("text/plain".into()), + body: Some("hello".into()), + parent: Some( + parent_inscription_id + .parent_value() + .into_iter() + .chain(iter::once(0)) + .collect(), + ), + unrecognized_even_field: false, + } + .to_witness(), + )], + ..Default::default() + }); + + context.mine_blocks(1); + + let inscription_id = InscriptionId { txid, index: 0 }; + + assert!(context + .index + .get_inscription_entry(inscription_id) + .unwrap() + .unwrap() + .parent + .is_none()); + } + } } diff --git a/src/index/block_index.rs b/src/index/block_index.rs deleted file mode 100644 index 5a16928ca2..0000000000 --- a/src/index/block_index.rs +++ /dev/null @@ -1,241 +0,0 @@ -use super::*; - -#[derive(Clone)] -pub struct BlockIndex { - first_inscription_height: u64, - lowest_blessed_by_block: Vec, - lowest_cursed_by_block: Vec, - highest_indexed_blessed: i64, - lowest_indexed_cursed: i64, -} - -impl BlockIndex { - pub(crate) fn new(index: &Index) -> Result { - Ok(BlockIndex { - first_inscription_height: index.options.first_inscription_height(), - lowest_blessed_by_block: Vec::new(), - lowest_cursed_by_block: Vec::new(), - highest_indexed_blessed: i64::MIN, - lowest_indexed_cursed: i64::MAX, - }) - } - - pub(crate) fn update(&mut self, index: &Index) -> Result { - let index_height = index.block_count()?; - let inscribed_block_count = index_height.saturating_sub(self.first_inscription_height); - let indexed_up_to: isize = self - .lowest_blessed_by_block - .len() - .try_into() - .unwrap_or(isize::MAX); - - let gap = inscribed_block_count.try_into().unwrap_or(isize::MAX) - indexed_up_to; - if gap <= 0 { - return Ok(()); - } - - log::debug!( - "Updating block index for {} new blocks ({} to {})", - gap, - indexed_up_to, - inscribed_block_count - ); - - self - .lowest_blessed_by_block - .resize(usize::try_from(inscribed_block_count)?, i64::MAX); - - self - .lowest_cursed_by_block - .resize(usize::try_from(inscribed_block_count)?, i64::MAX); - - let rtx = index.database.begin_read()?; - - // Use a more efficient approach for the initial indexing - since we have - // to traverse all inscriptions, it is most efficient to do so using one table. - if indexed_up_to == 0 { - for result in rtx - .open_table(INSCRIPTION_ID_TO_INSCRIPTION_ENTRY)? - .iter()? - { - let (_, entry) = result?; - let entry = InscriptionEntry::load(entry.value()); - let height_index: usize = entry - .height - .try_into() - .unwrap_or(usize::MAX) - .saturating_sub(self.first_inscription_height.try_into().unwrap()); - - if entry.number < 0 { - self.lowest_cursed_by_block[height_index] = - cmp::min(self.lowest_cursed_by_block[height_index], entry.number); - self.lowest_indexed_cursed = cmp::min(self.lowest_indexed_cursed, entry.number); - } else { - self.lowest_blessed_by_block[height_index] = - cmp::min(self.lowest_blessed_by_block[height_index], entry.number); - self.highest_indexed_blessed = cmp::max(self.highest_indexed_blessed, entry.number); - } - } - } else { - // Use default approach where we iterate in order of inscription number - // so we can easily skip over already indexed inscriptions. - let mut prev_block_height = usize::MAX; - - for result in rtx - .open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)? - .iter()? - { - let (number, id) = result?; - - if number.value() >= self.lowest_indexed_cursed - && number.value() <= self.highest_indexed_blessed - { - continue; - } - - let inscription_id = InscriptionId::load(*id.value()); - - if let Some(entry) = index.get_inscription_entry(inscription_id)? { - let current_height = entry.height.try_into().unwrap_or(usize::MAX); - - if prev_block_height != current_height { - prev_block_height = current_height; - - if number.value() < 0 { - self.lowest_cursed_by_block[prev_block_height - .saturating_sub(usize::try_from(self.first_inscription_height)?)] = number.value(); - self.lowest_indexed_cursed = cmp::min(self.lowest_indexed_cursed, number.value()); - } else { - self.lowest_blessed_by_block[prev_block_height - .saturating_sub(usize::try_from(self.first_inscription_height)?)] = number.value(); - self.highest_indexed_blessed = cmp::max(self.highest_indexed_blessed, number.value()); - } - } - } - } - } - - log::debug!( - "Updated block index for {} new blocks ({} to {})", - gap, - indexed_up_to, - inscribed_block_count - ); - - Ok(()) - } - - // Return all consecutively numbered inscriptions in the block at the given height, starting from the given number - fn get_inscriptions_in_block_from( - &self, - index: &Index, - block_height: u64, - from_number: i64, - cursed: bool, - ) -> Result> { - let mut block_inscriptions = Vec::new(); - - let rtx = index.database.begin_read()?; - let inscription_id_by_number = rtx.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?; - - let highest = if cursed { - -1 - } else { - match inscription_id_by_number.iter()?.next_back() { - Some(Ok((number, _id))) => number.value(), - Some(Err(err)) => return Err(err.into()), - None => i64::MIN, - } - }; - - for number in from_number..=highest { - match inscription_id_by_number.get(number)? { - Some(inscription_id) => { - let inscription_id = InscriptionId::load(*inscription_id.value()); - if let Some(entry) = index.get_inscription_entry(inscription_id)? { - if entry.height != block_height { - break; - } - block_inscriptions.push(inscription_id); - } - } - None => break, - } - } - - Ok(block_inscriptions) - } - - pub(crate) fn get_inscriptions_in_block( - &self, - index: &Index, - block_height: u64, - ) -> Result> { - if index.block_count()? - > self.lowest_blessed_by_block.len() as u64 + self.first_inscription_height - { - return Err(anyhow!( - "Block index not fully indexed ({} indexed of {})", - self.lowest_blessed_by_block.len() as u64 + self.first_inscription_height, - index.block_count()? - )); - } - if block_height >= index.block_count()? || block_height < self.first_inscription_height { - return Ok(Vec::new()); - } - - if self.lowest_blessed_by_block.is_empty() { - return Err(anyhow!("Block index not yet initialized")); - } - - let lowest_cursed = self.lowest_cursed_by_block - [usize::try_from(block_height.saturating_sub(self.first_inscription_height))?]; - let lowest_blessed = self.lowest_blessed_by_block - [usize::try_from(block_height.saturating_sub(self.first_inscription_height))?]; - - let mut inscriptions = - self.get_inscriptions_in_block_from(index, block_height, lowest_cursed, true)?; - inscriptions.extend(self.get_inscriptions_in_block_from( - index, - block_height, - lowest_blessed, - false, - )?); - - log::debug!( - "Got {} inscriptions in block {} ({} - {})", - inscriptions.len(), - block_height, - lowest_cursed, - lowest_blessed - ); - - Ok(inscriptions) - } - - pub(crate) fn get_highest_paying_inscriptions_in_block( - &self, - index: &Index, - block_height: u64, - n: usize, - ) -> Result<(Vec, usize)> { - let inscription_ids = self.get_inscriptions_in_block(index, block_height)?; - - let mut inscription_to_fee: Vec<(InscriptionId, u64)> = Vec::new(); - for id in &inscription_ids { - inscription_to_fee.push((*id, index.get_inscription_entry(*id)?.unwrap().fee)); - } - - inscription_to_fee.sort_by_key(|(_, fee)| *fee); - - Ok(( - inscription_to_fee - .iter() - .map(|(id, _)| *id) - .rev() - .take(n) - .collect(), - inscription_ids.len(), - )) - } -} diff --git a/src/index/entry.rs b/src/index/entry.rs index f7c09ea91f..d857c96b53 100644 --- a/src/index/entry.rs +++ b/src/index/entry.rs @@ -27,20 +27,22 @@ pub(crate) struct InscriptionEntry { pub(crate) fee: u64, pub(crate) height: u64, pub(crate) number: i64, + pub(crate) parent: Option, pub(crate) sat: Option, pub(crate) timestamp: u32, } -pub(crate) type InscriptionEntryValue = (u64, u64, i64, u64, u32); +pub(crate) type InscriptionEntryValue = (u64, u64, i64, ParentValue, u64, u32); impl Entry for InscriptionEntry { type Value = InscriptionEntryValue; - fn load((fee, height, number, sat, timestamp): InscriptionEntryValue) -> Self { + fn load((fee, height, number, parent, sat, timestamp): InscriptionEntryValue) -> Self { Self { fee, height, number, + parent: ParentEntry::load(parent), sat: if sat == u64::MAX { None } else { @@ -55,6 +57,7 @@ impl Entry for InscriptionEntry { self.fee, self.height, self.number, + self.parent.store(), match self.sat { Some(sat) => sat.n(), None => u64::MAX, @@ -86,6 +89,75 @@ impl Entry for InscriptionId { } } +type ParentValue = (u128, u128, u32); +type ParentEntry = Option; + +impl Entry for ParentEntry { + type Value = ParentValue; + + fn load(value: Self::Value) -> Self { + if (0, 0, 0) == value { + None + } else { + let (head, tail, index) = value; + let head_array = head.to_le_bytes(); + let tail_array = tail.to_le_bytes(); + let index_array = index.to_be_bytes(); + let array = [ + head_array[0], + head_array[1], + head_array[2], + head_array[3], + head_array[4], + head_array[5], + head_array[6], + head_array[7], + head_array[8], + head_array[9], + head_array[10], + head_array[11], + head_array[12], + head_array[13], + head_array[14], + head_array[15], + tail_array[0], + tail_array[1], + tail_array[2], + tail_array[3], + tail_array[4], + tail_array[5], + tail_array[6], + tail_array[7], + tail_array[8], + tail_array[9], + tail_array[10], + tail_array[11], + tail_array[12], + tail_array[13], + tail_array[14], + tail_array[15], + index_array[0], + index_array[1], + index_array[2], + index_array[3], + ]; + + Some(InscriptionId::load(array)) + } + } + + fn store(self) -> Self::Value { + if let Some(inscription_id) = self { + let txid_entry = inscription_id.txid.store(); + let little_end = u128::from_le_bytes(txid_entry[..16].try_into().unwrap()); + let big_end = u128::from_le_bytes(txid_entry[16..].try_into().unwrap()); + (little_end, big_end, inscription_id.index) + } else { + (0, 0, 0) + } + } +} + pub(super) type OutPointValue = [u8; 36]; impl Entry for OutPoint { @@ -144,3 +216,100 @@ impl Entry for SatRange { n.to_le_bytes()[0..11].try_into().unwrap() } } + +pub(super) type TxidValue = [u8; 32]; + +impl Entry for Txid { + type Value = TxidValue; + + fn load(value: Self::Value) -> Self { + Txid::from_byte_array(value) + } + + fn store(self) -> Self::Value { + Txid::to_byte_array(self) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parent_entry() { + let inscription_id: Option = None; + + assert_eq!(inscription_id.store(), (0, 0, 0)); + assert_eq!( + as Entry>::load((0, 0, 0)), + inscription_id + ); + + let inscription_id = Some( + "0000000000000000000000000000000000000000000000000000000000000000i1" + .parse::() + .unwrap(), + ); + + assert_eq!(inscription_id.store(), (0, 0, 1)); + assert_eq!( + as Entry>::load((0, 0, 1)), + inscription_id + ); + + let inscription_id = Some( + "ffffffffffffffffffffffffffffffff00000000000000000000000000000000i0" + .parse::() + .unwrap(), + ); + + assert_eq!(inscription_id.store(), (0, u128::MAX, 0)); + assert_eq!( + as Entry>::load((0, u128::MAX, 0)), + inscription_id + ); + } + + #[test] + fn parent_entry_individual_byte_order() { + let inscription_id = Some( + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefi0" + .parse::() + .unwrap(), + ); + + assert_eq!( + inscription_id.store(), + ( + 0x0123456789abcdef0123456789abcdef, + 0x0123456789abcdef0123456789abcdef, + 0 + ) + ); + + assert_eq!( + as Entry>::load(( + 0x0123456789abcdef0123456789abcdef, + 0x0123456789abcdef0123456789abcdef, + 0 + )), + inscription_id + ); + } + + #[test] + fn parent_entry_index() { + let inscription_id = Some( + "0000000000000000000000000000000000000000000000000000000000000000i1" + .parse::() + .unwrap(), + ); + + assert_eq!(inscription_id.store(), (0, 0, 1)); + + assert_eq!( + as Entry>::load((0, 0, 1)), + inscription_id + ); + } +} diff --git a/src/index/updater.rs b/src/index/updater.rs index d053e1bd8e..2800e1b466 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -378,6 +378,8 @@ impl<'index> Updater<'_> { } let mut height_to_block_hash = wtx.open_table(HEIGHT_TO_BLOCK_HASH)?; + let mut height_to_last_inscription_number = + wtx.open_table(HEIGHT_TO_LAST_INSCRIPTION_NUMBER)?; let mut inscription_id_to_inscription_entry = wtx.open_table(INSCRIPTION_ID_TO_INSCRIPTION_ENTRY)?; let mut inscription_id_to_satpoint = wtx.open_table(INSCRIPTION_ID_TO_SATPOINT)?; @@ -385,6 +387,7 @@ impl<'index> Updater<'_> { wtx.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?; let mut reinscription_id_to_seq_num = wtx.open_table(REINSCRIPTION_ID_TO_SEQUENCE_NUMBER)?; let mut sat_to_inscription_id = wtx.open_multimap_table(SAT_TO_INSCRIPTION_ID)?; + let mut inscription_id_to_children = wtx.open_multimap_table(INSCRIPTION_ID_TO_CHILDREN)?; let mut satpoint_to_inscription_id = wtx.open_multimap_table(SATPOINT_TO_INSCRIPTION_ID)?; let mut statistic_to_count = wtx.open_table(STATISTIC_TO_COUNT)?; @@ -400,6 +403,7 @@ impl<'index> Updater<'_> { let mut inscription_updater = InscriptionUpdater::new( self.height, + &mut inscription_id_to_children, &mut inscription_id_to_satpoint, value_receiver, &mut inscription_id_to_inscription_entry, @@ -510,6 +514,12 @@ impl<'index> Updater<'_> { } } + self.index_block_inscription_numbers( + &mut height_to_last_inscription_number, + &inscription_updater, + index_inscriptions, + )?; + statistic_to_count.insert(&Statistic::LostSats.key(), &inscription_updater.lost_sats)?; statistic_to_count.insert( @@ -596,6 +606,27 @@ impl<'index> Updater<'_> { Ok(()) } + fn index_block_inscription_numbers( + &mut self, + height_to_inscription_number: &mut Table, + inscription_updater: &InscriptionUpdater, + index_inscription: bool, + ) -> Result { + if !index_inscription { + return Ok(()); + } + + height_to_inscription_number.insert( + &self.height, + ( + inscription_updater.next_number, + inscription_updater.next_cursed_number, + ), + )?; + + Ok(()) + } + fn commit(&mut self, wtx: WriteTransaction, value_cache: HashMap) -> Result { log::info!( "Committing at block height {}, {} outputs traversed, {} in map, {} cached", diff --git a/src/index/updater/inscription_updater.rs b/src/index/updater/inscription_updater.rs index fce36e608e..ea08ba41f3 100644 --- a/src/index/updater/inscription_updater.rs +++ b/src/index/updater/inscription_updater.rs @@ -10,8 +10,9 @@ pub(super) struct Flotsam { #[derive(Debug, Clone)] enum Origin { New { - fee: u64, cursed: bool, + fee: u64, + parent: Option, unbound: bool, }, Old { @@ -22,12 +23,14 @@ enum Origin { pub(super) struct InscriptionUpdater<'a, 'db, 'tx> { flotsam: Vec, height: u64, + id_to_children: + &'a mut MultimapTable<'db, 'tx, &'static InscriptionIdValue, &'static InscriptionIdValue>, id_to_satpoint: &'a mut Table<'db, 'tx, &'static InscriptionIdValue, &'static SatPointValue>, value_receiver: &'a mut Receiver, id_to_entry: &'a mut Table<'db, 'tx, &'static InscriptionIdValue, InscriptionEntryValue>, pub(super) lost_sats: u64, - next_cursed_number: i64, - next_number: i64, + pub(super) next_cursed_number: i64, + pub(super) next_number: i64, number_to_id: &'a mut Table<'db, 'tx, i64, &'static InscriptionIdValue>, outpoint_to_value: &'a mut Table<'db, 'tx, &'static OutPointValue, u64>, reward: u64, @@ -43,6 +46,12 @@ pub(super) struct InscriptionUpdater<'a, 'db, 'tx> { impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { pub(super) fn new( height: u64, + id_to_children: &'a mut MultimapTable< + 'db, + 'tx, + &'static InscriptionIdValue, + &'static InscriptionIdValue, + >, id_to_satpoint: &'a mut Table<'db, 'tx, &'static InscriptionIdValue, &'static SatPointValue>, value_receiver: &'a mut Receiver, id_to_entry: &'a mut Table<'db, 'tx, &'static InscriptionIdValue, InscriptionEntryValue>, @@ -78,6 +87,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { Ok(Self { flotsam: Vec::new(), height, + id_to_children, id_to_satpoint, value_receiver, id_to_entry, @@ -105,13 +115,13 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { let mut new_inscriptions = Inscription::from_transaction(tx).into_iter().peekable(); let mut floating_inscriptions = Vec::new(); let mut inscribed_offsets = BTreeMap::new(); - let mut input_value = 0; + let mut total_input_value = 0; let mut id_counter = 0; for (input_index, tx_in) in tx.input.iter().enumerate() { // skip subsidy since no inscriptions possible if tx_in.previous_output.is_null() { - input_value += Height(self.height).subsidy(); + total_input_value += Height(self.height).subsidy(); continue; } @@ -121,7 +131,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { self.satpoint_to_id, tx_in.previous_output, )? { - let offset = input_value + old_satpoint.offset; + let offset = total_input_value + old_satpoint.offset; floating_inscriptions.push(Flotsam { offset, inscription_id, @@ -134,10 +144,11 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { .or_insert((inscription_id, 0)); } - let offset = input_value; + let offset = total_input_value; // multi-level cache for UTXO set to get to the input amount - input_value += if let Some(value) = self.value_cache.remove(&tx_in.previous_output) { + let current_input_value = if let Some(value) = self.value_cache.remove(&tx_in.previous_output) + { value } else if let Some(value) = self .outpoint_to_value @@ -153,6 +164,8 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { })? }; + total_input_value += current_input_value; + // go through all inscriptions in this input while let Some(inscription) = new_inscriptions.peek() { if inscription.tx_in_index != u32::try_from(input_index).unwrap() { @@ -164,7 +177,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { index: id_counter, }; - let curse = if inscription.tx_in_index != 0 { + let curse = if inscription.inscription.unrecognized_even_field { + Some(Curse::UnrecognizedEvenField) + } else if inscription.tx_in_index != 0 { Some(Curse::NotInFirstInput) } else if inscription.tx_in_offset != 0 { Some(Curse::NotAtOffsetZero) @@ -214,7 +229,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { curse.is_some() }; - let unbound = input_value == 0 || inscription.tx_in_offset != 0; + let unbound = current_input_value == 0 + || inscription.tx_in_offset != 0 + || curse == Some(Curse::UnrecognizedEvenField); if curse.is_some() || unbound { log::info!( @@ -229,8 +246,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { inscription_id, offset, origin: Origin::New { - fee: 0, cursed, + fee: 0, + parent: inscription.inscription.parent(), unbound, }, }); @@ -240,6 +258,25 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { } } + let potential_parents = floating_inscriptions + .iter() + .map(|flotsam| flotsam.inscription_id) + .collect::>(); + + for flotsam in &mut floating_inscriptions { + if let Flotsam { + origin: Origin::New { parent, .. }, + .. + } = flotsam + { + if let Some(purported_parent) = parent { + if !potential_parents.contains(purported_parent) { + *parent = None; + } + } + } + } + // still have to normalize over inscription size let total_output_value = tx.output.iter().map(|txout| txout.value).sum::(); let mut floating_inscriptions = floating_inscriptions @@ -250,8 +287,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { offset, origin: Origin::New { - fee: _, cursed, + fee: _, + parent, unbound, }, } = flotsam @@ -260,8 +298,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { inscription_id, offset, origin: Origin::New { - fee: (input_value - total_output_value) / u64::from(id_counter), + fee: (total_input_value - total_output_value) / u64::from(id_counter), cursed, + parent, unbound, }, } @@ -334,7 +373,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { offset: self.reward + flotsam.offset - output_value, ..flotsam })); - self.reward += input_value - output_value; + self.reward += total_input_value - output_value; Ok(()) } } @@ -373,8 +412,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { false } Origin::New { - fee, cursed, + fee, + parent, unbound, } => { let number = if cursed { @@ -394,35 +434,32 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { let sat = if unbound { None } else { - let mut sat = None; - if let Some(input_sat_ranges) = input_sat_ranges { - let mut offset = 0; - for (start, end) in input_sat_ranges { - let size = end - start; - if offset + size > flotsam.offset { - let n = start + flotsam.offset - offset; - self.sat_to_inscription_id.insert(&n, &inscription_id)?; - sat = Some(Sat(n)); - break; - } - offset += size; - } - } - sat + Self::calculate_sat(input_sat_ranges, flotsam.offset) }; + if let Some(Sat(n)) = sat { + self.sat_to_inscription_id.insert(&n, &inscription_id)?; + } + self.id_to_entry.insert( &inscription_id, &InscriptionEntry { fee, height: self.height, number, + parent, sat, timestamp: self.timestamp, } .store(), )?; + if let Some(parent) = parent { + self + .id_to_children + .insert(&parent.store(), &inscription_id)?; + } + unbound } }; diff --git a/src/inscription.rs b/src/inscription.rs index a63d4f0d4f..79147ac7cd 100644 --- a/src/inscription.rs +++ b/src/inscription.rs @@ -5,27 +5,31 @@ use { opcodes, script::{self, Instruction, Instructions, PushBytesBuf}, }, - taproot::TAPROOT_ANNEX_PREFIX, ScriptBuf, Witness, }, std::{iter::Peekable, str}, }; const PROTOCOL_ID: [u8; 3] = *b"ord"; + const BODY_TAG: [u8; 0] = []; const CONTENT_TYPE_TAG: [u8; 1] = [1]; +const PARENT_TAG: [u8; 1] = [3]; #[derive(Debug, PartialEq, Clone)] pub(crate) enum Curse { NotInFirstInput, NotAtOffsetZero, Reinscription, + UnrecognizedEvenField, } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Eq, Default)] pub struct Inscription { - body: Option>, - content_type: Option>, + pub body: Option>, + pub content_type: Option>, + pub parent: Option>, + pub unrecognized_even_field: bool, } #[derive(Debug, PartialEq, Clone)] @@ -38,7 +42,12 @@ pub(crate) struct TransactionInscription { impl Inscription { #[cfg(test)] pub(crate) fn new(content_type: Option>, body: Option>) -> Self { - Self { content_type, body } + Self { + content_type, + body, + parent: None, + unrecognized_even_field: false, + } } pub(crate) fn from_transaction(tx: &Transaction) -> Vec { @@ -64,7 +73,11 @@ impl Inscription { result } - pub(crate) fn from_file(chain: Chain, path: impl AsRef) -> Result { + pub(crate) fn from_file( + chain: Chain, + path: impl AsRef, + parent: Option, + ) -> Result { let path = path.as_ref(); let body = fs::read(path).with_context(|| format!("io error reading {}", path.display()))?; @@ -81,6 +94,8 @@ impl Inscription { Ok(Self { body: Some(body), content_type: Some(content_type.into()), + parent: parent.map(|id| id.parent_value()), + unrecognized_even_field: false, }) } @@ -96,6 +111,12 @@ impl Inscription { .push_slice(PushBytesBuf::try_from(content_type).unwrap()); } + if let Some(parent) = self.parent.clone() { + builder = builder + .push_slice(PARENT_TAG) + .push_slice(PushBytesBuf::try_from(parent).unwrap()); + } + if let Some(body) = &self.body { builder = builder.push_slice(BODY_TAG); for chunk in body.chunks(520) { @@ -138,6 +159,39 @@ impl Inscription { str::from_utf8(self.content_type.as_ref()?).ok() } + pub(crate) fn parent(&self) -> Option { + let value = self.parent.as_ref()?; + + if value.len() < Txid::LEN { + return None; + } + + if value.len() > Txid::LEN + 4 { + return None; + } + + let (txid, index) = value.split_at(Txid::LEN); + + if let Some(last) = index.last() { + if *last == 0 { + return None; + } + } + + let txid = Txid::from_slice(txid).unwrap(); + + let index = [ + index.first().copied().unwrap_or(0), + index.get(1).copied().unwrap_or(0), + index.get(2).copied().unwrap_or(0), + index.get(3).copied().unwrap_or(0), + ]; + + let index = u32::from_le_bytes(index); + + Some(InscriptionId { txid, index }) + } + #[cfg(test)] pub(crate) fn to_witness(&self) -> Witness { let builder = script::Builder::new(); @@ -155,12 +209,10 @@ impl Inscription { #[derive(Debug, PartialEq)] pub(crate) enum InscriptionError { - EmptyWitness, InvalidInscription, - KeyPathSpend, NoInscription, + NoTapscript, Script(script::Error), - UnrecognizedEvenField, } type Result = std::result::Result; @@ -172,34 +224,12 @@ struct InscriptionParser<'a> { impl<'a> InscriptionParser<'a> { fn parse(witness: &Witness) -> Result> { - if witness.is_empty() { - return Err(InscriptionError::EmptyWitness); - } - - if witness.len() == 1 { - return Err(InscriptionError::KeyPathSpend); - } - - let annex = witness - .last() - .and_then(|element| element.first().map(|byte| *byte == TAPROOT_ANNEX_PREFIX)) - .unwrap_or(false); - - if witness.len() == 2 && annex { - return Err(InscriptionError::KeyPathSpend); - } - - let script = witness - .iter() - .nth(if annex { - witness.len() - 1 - } else { - witness.len() - 2 - }) - .unwrap(); + let Some(tapscript) = witness.tapscript() else { + return Err(InscriptionError::NoTapscript); + }; InscriptionParser { - instructions: ScriptBuf::from(Vec::from(script)).instructions().peekable(), + instructions: tapscript.instructions().peekable(), } .parse_inscriptions() .into_iter() @@ -246,16 +276,23 @@ impl<'a> InscriptionParser<'a> { let body = fields.remove(BODY_TAG.as_slice()); let content_type = fields.remove(CONTENT_TYPE_TAG.as_slice()); + let parent = fields.remove(PARENT_TAG.as_slice()); + let mut unrecognized_even_field = false; for tag in fields.keys() { if let Some(lsb) = tag.first() { if lsb % 2 == 0 { - return Err(InscriptionError::UnrecognizedEvenField); + unrecognized_even_field = true; } } } - Ok(Inscription { body, content_type }) + Ok(Inscription { + body, + content_type, + parent, + unrecognized_even_field, + }) } fn advance(&mut self) -> Result> { @@ -321,7 +358,7 @@ mod tests { fn empty() { assert_eq!( InscriptionParser::parse(&Witness::new()), - Err(InscriptionError::EmptyWitness) + Err(InscriptionError::NoTapscript) ); } @@ -329,7 +366,7 @@ mod tests { fn ignore_key_path_spends() { assert_eq!( InscriptionParser::parse(&Witness::from_slice(&[Vec::new()])), - Err(InscriptionError::KeyPathSpend), + Err(InscriptionError::NoTapscript), ); } @@ -337,7 +374,7 @@ mod tests { fn ignore_key_path_spends_with_annex() { assert_eq!( InscriptionParser::parse(&Witness::from_slice(&[Vec::new(), vec![0x50]])), - Err(InscriptionError::KeyPathSpend), + Err(InscriptionError::NoTapscript), ); } @@ -397,7 +434,7 @@ mod tests { b"ord", &[1], b"text/plain;charset=utf-8", - &[3], + &[5], b"bar", &[], b"ord", @@ -413,6 +450,8 @@ mod tests { Ok(vec![Inscription { content_type: Some(b"text/plain;charset=utf-8".to_vec()), body: None, + parent: None, + unrecognized_even_field: false, }]), ); } @@ -423,7 +462,9 @@ mod tests { InscriptionParser::parse(&envelope(&[b"ord", &[], b"foo"])), Ok(vec![Inscription { content_type: None, + parent: None, body: Some(b"foo".to_vec()), + unrecognized_even_field: false, }]), ); } @@ -752,8 +793,10 @@ mod tests { witness.push( &Inscription { - content_type: None, body: None, + content_type: None, + parent: None, + unrecognized_even_field: false, } .append_reveal_script(script::Builder::new()), ); @@ -764,7 +807,9 @@ mod tests { InscriptionParser::parse(&witness).unwrap(), vec![Inscription { content_type: None, + parent: None, body: None, + unrecognized_even_field: false, }] ); } @@ -772,19 +817,176 @@ mod tests { #[test] fn unknown_odd_fields_are_ignored() { assert_eq!( - InscriptionParser::parse(&envelope(&[b"ord", &[3], &[0]])), + InscriptionParser::parse(&envelope(&[b"ord", &[5], &[0]])), Ok(vec![Inscription { content_type: None, + parent: None, body: None, + unrecognized_even_field: false, }]), ); } #[test] - fn unknown_even_fields_are_invalid() { + fn unknown_even_fields() { assert_eq!( InscriptionParser::parse(&envelope(&[b"ord", &[2], &[0]])), - Err(InscriptionError::UnrecognizedEvenField), + Ok(vec![Inscription { + content_type: None, + body: None, + parent: None, + unrecognized_even_field: true, + }]), + ); + } + + #[test] + fn inscription_with_no_parent_field_has_no_parent() { + assert!(Inscription { + parent: None, + ..Default::default() + } + .parent() + .is_none()); + } + + #[test] + fn inscription_with_parent_field_shorter_than_txid_length_has_no_parent() { + assert!(Inscription { + parent: Some(vec![]), + ..Default::default() + } + .parent() + .is_none()); + } + + #[test] + fn inscription_with_parent_field_longer_than_txid_and_index_has_no_parent() { + assert!(Inscription { + parent: Some(vec![1; 37]), + ..Default::default() + } + .parent() + .is_none()); + } + + #[test] + fn inscription_with_parent_field_index_with_trailing_zeroes_has_no_parent() { + let mut parent = vec![1; 36]; + + parent[35] = 0; + + assert!(Inscription { + parent: Some(parent), + ..Default::default() + } + .parent() + .is_none()); + } + + #[test] + fn inscription_parent_txid_is_deserialized_correctly() { + assert_eq!( + Inscription { + parent: Some(vec![ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, + ]), + ..Default::default() + } + .parent() + .unwrap() + .txid, + "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100" + .parse() + .unwrap() + ); + } + + #[test] + fn inscription_parent_with_zero_byte_index_field_is_deserialized_correctly() { + assert_eq!( + Inscription { + parent: Some(vec![1; 32]), + ..Default::default() + } + .parent() + .unwrap() + .index, + 0 + ); + } + + #[test] + fn inscription_parent_with_one_byte_index_field_is_deserialized_correctly() { + assert_eq!( + Inscription { + parent: Some(vec![ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01 + ]), + ..Default::default() + } + .parent() + .unwrap() + .index, + 1 + ); + } + + #[test] + fn inscription_parent_with_two_byte_index_field_is_deserialized_correctly() { + assert_eq!( + Inscription { + parent: Some(vec![ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x02 + ]), + ..Default::default() + } + .parent() + .unwrap() + .index, + 0x0201, + ); + } + + #[test] + fn inscription_parent_with_three_byte_index_field_is_deserialized_correctly() { + assert_eq!( + Inscription { + parent: Some(vec![ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x02, 0x03 + ]), + ..Default::default() + } + .parent() + .unwrap() + .index, + 0x030201, + ); + } + + #[test] + fn inscription_parent_with_four_byte_index_field_is_deserialized_correctly() { + assert_eq!( + Inscription { + parent: Some(vec![ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x02, 0x03, 0x04, + ]), + ..Default::default() + } + .parent() + .unwrap() + .index, + 0x04030201, ); } } diff --git a/src/inscription_id.rs b/src/inscription_id.rs index cb70b4baa1..7ea91939a8 100644 --- a/src/inscription_id.rs +++ b/src/inscription_id.rs @@ -6,6 +6,25 @@ pub struct InscriptionId { pub index: u32, } +impl InscriptionId { + pub(crate) fn parent_value(self) -> Vec { + let index = self.index.to_le_bytes(); + let mut index_slice = index.as_slice(); + + while index_slice.last().copied() == Some(0) { + index_slice = &index_slice[0..index_slice.len() - 1]; + } + + self + .txid + .to_byte_array() + .iter() + .chain(index_slice) + .copied() + .collect() + } +} + impl<'de> Deserialize<'de> for InscriptionId { fn deserialize(deserializer: D) -> Result where diff --git a/src/lib.rs b/src/lib.rs index a05274a6d4..5677a23aac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,7 +21,6 @@ use { epoch::Epoch, height::Height, index::{Index, List}, - inscription::Inscription, inscription_id::InscriptionId, media::Media, options::Options, @@ -75,8 +74,8 @@ use { }; pub use crate::{ - fee_rate::FeeRate, object::Object, rarity::Rarity, sat::Sat, sat_point::SatPoint, - subcommand::wallet::transaction_builder::TransactionBuilder, + fee_rate::FeeRate, inscription::Inscription, object::Object, rarity::Rarity, sat::Sat, + sat_point::SatPoint, subcommand::wallet::transaction_builder::TransactionBuilder, }; #[cfg(test)] diff --git a/src/media.rs b/src/media.rs index ff43ba40a2..7f4647b8a3 100644 --- a/src/media.rs +++ b/src/media.rs @@ -21,6 +21,7 @@ impl Media { ("application/json", Media::Text, &["json"]), ("application/pdf", Media::Pdf, &["pdf"]), ("application/pgp-signature", Media::Text, &["asc"]), + ("application/protobuf", Media::Unknown, &["binpb"]), ("application/yaml", Media::Text, &["yaml", "yml"]), ("audio/flac", Media::Audio, &["flac"]), ("audio/mpeg", Media::Audio, &["mp3"]), diff --git a/src/object.rs b/src/object.rs index f70f331e57..e684a33589 100644 --- a/src/object.rs +++ b/src/object.rs @@ -1,6 +1,6 @@ use super::*; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Object { Address(Address), Hash([u8; 32]), diff --git a/src/options.rs b/src/options.rs index 38d4190d38..d23b68e335 100644 --- a/src/options.rs +++ b/src/options.rs @@ -1,60 +1,60 @@ use {super::*, bitcoincore_rpc::Auth}; #[derive(Clone, Default, Debug, Parser)] -#[clap(group( +#[command(group( ArgGroup::new("chains") .required(false) - .args(&["chain-argument", "signet", "regtest", "testnet"]), + .args(&["chain_argument", "signet", "regtest", "testnet"]), ))] pub(crate) struct Options { - #[clap(long, help = "Load Litecoin Core data dir from .")] + #[arg(long, help = "Load Litecoin Core data dir from .")] pub(crate) litecoin_data_dir: Option, - #[clap(long, help = "Authenticate to Bitcoin Core RPC with .")] + #[arg(long, help = "Authenticate to Bitcoin Core RPC with .")] pub(crate) bitcoin_rpc_pass: Option, - #[clap(long, help = "Authenticate to Bitcoin Core RPC as .")] + #[arg(long, help = "Authenticate to Bitcoin Core RPC as .")] pub(crate) bitcoin_rpc_user: Option, - #[clap( + #[arg( long = "chain", - arg_enum, + value_enum, default_value = "mainnet", help = "Use ." )] pub(crate) chain_argument: Chain, - #[clap(long, help = "Load configuration from .")] + #[arg(long, help = "Load configuration from .")] pub(crate) config: Option, - #[clap(long, help = "Load configuration from .")] + #[arg(long, help = "Load configuration from .")] pub(crate) config_dir: Option, - #[clap(long, help = "Load Litecoin Core RPC cookie file from .")] + #[arg(long, help = "Load Litecoin Core RPC cookie file from .")] pub(crate) cookie_file: Option, - #[clap(long, help = "Store index in .")] + #[arg(long, help = "Store index in .")] pub(crate) data_dir: Option, - #[clap( + #[arg( long, help = "Set index cache to bytes. By default takes 1/4 of available RAM." )] pub(crate) db_cache_size: Option, - #[clap( + #[arg( long, help = "Don't look for inscriptions below ." )] pub(crate) first_inscription_height: Option, - #[clap(long, help = "Limit index to blocks.")] + #[arg(long, help = "Limit index to blocks.")] pub(crate) height_limit: Option, - #[clap(long, help = "Use index at .")] + #[arg(long, help = "Use index at .")] pub(crate) index: Option, - #[clap(long, help = "Track location of all satoshis.")] + #[arg(long, help = "Track location of all satoshis.")] pub(crate) index_sats: bool, - #[clap(long, short, help = "Use regtest. Equivalent to `--chain regtest`.")] + #[arg(long, short, help = "Use regtest. Equivalent to `--chain regtest`.")] pub(crate) regtest: bool, - #[clap(long, help = "Connect to Litecoin Core RPC at .")] + #[arg(long, help = "Connect to Litecoin Core RPC at .")] pub(crate) rpc_url: Option, - #[clap(long, short, help = "Use signet. Equivalent to `--chain signet`.")] + #[arg(long, short, help = "Use signet. Equivalent to `--chain signet`.")] pub(crate) signet: bool, - #[clap(long, short, help = "Use testnet. Equivalent to `--chain testnet`.")] + #[arg(long, short, help = "Use testnet. Equivalent to `--chain testnet`.")] pub(crate) testnet: bool, - #[clap(long, default_value = "ord", help = "Use wallet named .")] + #[arg(long, default_value = "ord", help = "Use wallet named .")] pub(crate) wallet: String, - #[clap(long, short, help = "Enable JSON API.")] + #[arg(long, short, help = "Enable JSON API.")] pub(crate) enable_json_api: bool, } diff --git a/src/outgoing.rs b/src/outgoing.rs index 614209c6d3..a8265f042d 100644 --- a/src/outgoing.rs +++ b/src/outgoing.rs @@ -1,6 +1,6 @@ use super::*; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub(crate) enum Outgoing { Amount(Amount), InscriptionId(InscriptionId), diff --git a/src/subcommand.rs b/src/subcommand.rs index 1f8036c4ed..e8afe4967c 100644 --- a/src/subcommand.rs +++ b/src/subcommand.rs @@ -1,5 +1,6 @@ use super::*; +pub mod decode; pub mod epochs; pub mod find; mod index; @@ -15,35 +16,38 @@ pub mod wallet; #[derive(Debug, Parser)] pub(crate) enum Subcommand { - #[clap(about = "List the first litoshis of each reward epoch")] + #[command(about = "Decode a transaction")] + Decode(decode::Decode), + #[command(about = "List the first litoshis of each reward epoch")] Epochs, - #[clap(about = "Run an explorer server populated with inscriptions")] + #[command(about = "Run an explorer server populated with inscriptions")] Preview(preview::Preview), - #[clap(about = "Find a litoshi's current location")] + #[command(about = "Find a litoshi's current location")] Find(find::Find), - #[clap(subcommand, about = "Index commands")] + #[command(subcommand, about = "Index commands")] Index(index::IndexSubcommand), - #[clap(about = "Display index statistics")] + #[command(about = "Display index statistics")] Info(info::Info), - #[clap(about = "List the litoshi in an output")] + #[command(about = "List the litoshi in an output")] List(list::List), - #[clap(about = "Parse a litoshi from ordinal notation")] + #[command(about = "Parse a litoshi from ordinal notation")] Parse(parse::Parse), - #[clap(about = "Display information about a block's subsidy")] + #[command(about = "Display information about a block's subsidy")] Subsidy(subsidy::Subsidy), - #[clap(about = "Run the explorer server")] + #[command(about = "Run the explorer server")] Server(server::Server), - #[clap(about = "Display Litecoin supply information")] + #[command(about = "Display Litecoin supply information")] Supply, - #[clap(about = "Display litoshi traits")] + #[command(about = "Display litoshi traits")] Traits(traits::Traits), - #[clap(subcommand, about = "Wallet commands")] + #[command(subcommand, about = "Wallet commands")] Wallet(wallet::Wallet), } impl Subcommand { pub(crate) fn run(self, options: Options) -> SubcommandResult { match self { + Self::Decode(decode) => decode.run(), Self::Epochs => epochs::run(), Self::Preview(preview) => preview.run(), Self::Find(find) => find.run(options), diff --git a/src/subcommand/decode.rs b/src/subcommand/decode.rs new file mode 100644 index 0000000000..9523657bb7 --- /dev/null +++ b/src/subcommand/decode.rs @@ -0,0 +1,30 @@ +use super::*; + +#[derive(Serialize, Eq, PartialEq, Deserialize, Debug)] +pub struct Output { + pub inscriptions: Vec, +} + +#[derive(Debug, Parser)] +pub(crate) struct Decode { + transaction: Option, +} + +impl Decode { + pub(crate) fn run(self) -> SubcommandResult { + let transaction = if let Some(path) = self.transaction { + Transaction::consensus_decode(&mut File::open(path)?)? + } else { + Transaction::consensus_decode(&mut io::stdin())? + }; + + let inscriptions = Inscription::from_transaction(&transaction); + + Ok(Box::new(Output { + inscriptions: inscriptions + .into_iter() + .map(|inscription| inscription.inscription) + .collect(), + })) + } +} diff --git a/src/subcommand/find.rs b/src/subcommand/find.rs index fb81e19b33..cdc69084b2 100644 --- a/src/subcommand/find.rs +++ b/src/subcommand/find.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Debug, Parser)] pub(crate) struct Find { - #[clap(help = "Find output and offset of .")] + #[arg(help = "Find output and offset of .")] sat: Sat, } diff --git a/src/subcommand/index.rs b/src/subcommand/index.rs index aea938a8a3..dca19d34ea 100644 --- a/src/subcommand/index.rs +++ b/src/subcommand/index.rs @@ -2,9 +2,9 @@ use super::*; #[derive(Debug, Parser)] pub(crate) enum IndexSubcommand { - #[clap(about = "Write inscription numbers and ids to a tab-separated file")] + #[command(about = "Write inscription numbers and ids to a tab-separated file")] Export(Export), - #[clap(about = "Update the index")] + #[command(about = "Update the index")] Run, } @@ -19,13 +19,13 @@ impl IndexSubcommand { #[derive(Debug, Parser)] pub(crate) struct Export { - #[clap( + #[arg( long, default_value = "inscription_number_to_id.tsv", help = " file to write to" )] tsv: String, - #[clap(long, help = "Whether to include addresses in export")] + #[arg(long, help = "Whether to include addresses in export")] include_addresses: bool, } diff --git a/src/subcommand/info.rs b/src/subcommand/info.rs index 737cdd2228..692c375b56 100644 --- a/src/subcommand/info.rs +++ b/src/subcommand/info.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Debug, Parser)] pub(crate) struct Info { - #[clap(long)] + #[arg(long)] transactions: bool, } diff --git a/src/subcommand/list.rs b/src/subcommand/list.rs index d406e39357..a306a02036 100644 --- a/src/subcommand/list.rs +++ b/src/subcommand/list.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Debug, Parser)] pub(crate) struct List { - #[clap(help = "List sats in .")] + #[arg(help = "List sats in .")] outpoint: OutPoint, } diff --git a/src/subcommand/parse.rs b/src/subcommand/parse.rs index 40854b9b73..2430abd185 100644 --- a/src/subcommand/parse.rs +++ b/src/subcommand/parse.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Debug, Parser)] pub(crate) struct Parse { - #[clap(help = "Parse .")] + #[arg(help = "Parse .")] object: Object, } diff --git a/src/subcommand/preview.rs b/src/subcommand/preview.rs index 66b058a5ac..0791669620 100644 --- a/src/subcommand/preview.rs +++ b/src/subcommand/preview.rs @@ -2,7 +2,7 @@ use {super::*, fee_rate::FeeRate}; #[derive(Debug, Parser)] pub(crate) struct Preview { - #[clap(flatten)] + #[command(flatten)] server: super::server::Server, inscriptions: Vec, } @@ -86,7 +86,9 @@ impl Preview { satpoint: None, dry_run: false, no_limit: false, + reinscribe: false, destination: None, + parent: None, postage: Some(TransactionBuilder::TARGET_POSTAGE), }, )), diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index ee8a2b623a..25576c05da 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -5,7 +5,6 @@ use { error::{OptionExt, ServerError, ServerResult}, }, super::*, - crate::index::block_index::BlockIndex, crate::page_config::PageConfig, crate::templates::{ BlockHtml, ClockSvg, HomeHtml, InputHtml, InscriptionHtml, InscriptionJson, @@ -31,7 +30,7 @@ use { caches::DirCache, AcmeConfig, }, - std::{cmp::Ordering, str, sync::Arc, sync::RwLock}, + std::{cmp::Ordering, str, sync::Arc}, tokio_stream::StreamExt, tower_http::{ compression::CompressionLayer, @@ -48,10 +47,6 @@ pub struct ServerConfig { pub is_json_api_enabled: bool, } -struct BlockIndexState { - block_index: RwLock, -} - enum BlockQuery { Height(u64), Hash(BlockHash), @@ -103,51 +98,44 @@ impl Display for StaticHtml { #[derive(Debug, Parser)] pub(crate) struct Server { - #[clap( + #[arg( long, default_value = "0.0.0.0", help = "Listen on
for incoming requests." )] address: String, - #[clap( + #[arg( long, help = "Request ACME TLS certificate for . This ord instance must be reachable at :443 to respond to Let's Encrypt ACME challenges." )] acme_domain: Vec, - #[clap( + #[arg( long, help = "Listen on for incoming HTTP requests. [default: 80]." )] http_port: Option, - #[clap( + #[arg( long, group = "port", help = "Listen on for incoming HTTPS requests. [default: 443]." )] https_port: Option, - #[clap(long, help = "Store ACME TLS certificates in .")] + #[arg(long, help = "Store ACME TLS certificates in .")] acme_cache: Option, - #[clap(long, help = "Provide ACME contact .")] + #[arg(long, help = "Provide ACME contact .")] acme_contact: Vec, - #[clap(long, help = "Serve HTTP traffic on .")] + #[arg(long, help = "Serve HTTP traffic on .")] http: bool, - #[clap(long, help = "Serve HTTPS traffic on .")] + #[arg(long, help = "Serve HTTPS traffic on .")] https: bool, - #[clap(long, help = "Redirect HTTP traffic to HTTPS.")] + #[arg(long, help = "Redirect HTTP traffic to HTTPS.")] redirect_http_to_https: bool, } impl Server { pub(crate) fn run(self, options: Options, index: Arc, handle: Handle) -> SubcommandResult { Runtime::new()?.block_on(async { - let block_index_state = BlockIndexState { - block_index: RwLock::new(BlockIndex::new(&index)?), - }; - - let block_index_state = Arc::new(block_index_state); - let index_clone = index.clone(); - let block_index_clone = block_index_state.clone(); let index_thread = thread::spawn(move || loop { if SHUTTING_DOWN.load(atomic::Ordering::Relaxed) { @@ -156,14 +144,6 @@ impl Server { if let Err(error) = index_clone.update() { log::warn!("Updating index: {error}"); } - if let Err(error) = block_index_clone - .block_index - .write() - .unwrap() - .update(&index_clone) - { - log::warn!("Updating block index: {error}"); - } thread::sleep(Duration::from_millis(5000)); }); INDEXER.lock().unwrap().replace(index_thread); @@ -222,7 +202,6 @@ impl Server { .layer(Extension(index)) .layer(Extension(page_config)) .layer(Extension(Arc::new(config))) - .layer(Extension(block_index_state)) .layer(SetResponseHeaderLayer::if_not_present( header::CONTENT_SECURITY_POLICY, HeaderValue::from_static("default-src 'self'"), @@ -560,16 +539,13 @@ impl Server { async fn home( Extension(page_config): Extension>, Extension(index): Extension>, - Extension(block_index_state): Extension>, ) -> ServerResult> { let blocks = index.blocks(100)?; let mut featured_blocks = BTreeMap::new(); for (height, hash) in blocks.iter().take(5) { - let (inscriptions, _total_num) = block_index_state - .block_index - .read() - .map_err(|err| anyhow!("block index RwLock poisoned: {}", err))? - .get_highest_paying_inscriptions_in_block(&index, *height, 8)?; + let (inscriptions, _total_num) = + index.get_highest_paying_inscriptions_in_block(*height, 8)?; + featured_blocks.insert(*hash, inscriptions); } @@ -583,7 +559,6 @@ impl Server { async fn block( Extension(page_config): Extension>, Extension(index): Extension>, - Extension(block_index_state): Extension>, Path(DeserializeFromStr(query)): Path>, ) -> ServerResult> { let (block, height) = match query { @@ -607,11 +582,8 @@ impl Server { } }; - let (featured_inscriptions, total_num) = block_index_state - .block_index - .read() - .map_err(|err| anyhow!("block index RwLock poisoned: {}", err))? - .get_highest_paying_inscriptions_in_block(&index, height, 8)?; + let (featured_inscriptions, total_num) = + index.get_highest_paying_inscriptions_in_block(height, 8)?; Ok( BlockHtml::new( @@ -905,18 +877,12 @@ impl Server { header::CONTENT_SECURITY_POLICY, HeaderValue::from_static("default-src *:*/content/ *:*/blockheight *:*/blockhash *:*/blockhash/ *:*/blocktime 'unsafe-eval' 'unsafe-inline' data: blob:"), ); - - let body = inscription.into_body(); - let cache_control = match body { - Some(_) => "max-age=31536000, immutable", - None => "max-age=600", - }; headers.insert( header::CACHE_CONTROL, - HeaderValue::from_str(cache_control).unwrap(), + HeaderValue::from_static("max-age=31536000, immutable"), ); - Some((headers, body?)) + Some((headers, inscription.into_body()?)) } async fn preview( @@ -1022,13 +988,17 @@ impl Server { let next = index.get_inscription_id_by_inscription_number(entry.number + 1)?; + let children = index.get_children_by_inscription_id(inscription_id)?; + Ok(if accept_json.0 { Json(InscriptionJson::new( page_config.chain, + children, entry.fee, entry.height, inscription, inscription_id, + entry.parent, next, entry.number, output, @@ -1043,11 +1013,13 @@ impl Server { chain: page_config.chain, genesis_fee: entry.fee, genesis_height: entry.height, + children, inscription, inscription_id, next, number: entry.number, output, + parent: entry.parent, previous, sat: entry.sat, satpoint, @@ -1069,14 +1041,12 @@ impl Server { async fn inscriptions_in_block( Extension(page_config): Extension>, Extension(index): Extension>, - Extension(block_index_state): Extension>, Path(block_height): Path, accept_json: AcceptJson, ) -> ServerResult { Self::inscriptions_in_block_from_page( Extension(page_config), Extension(index), - Extension(block_index_state), Path((block_height, 0)), accept_json, ) @@ -1086,18 +1056,10 @@ impl Server { async fn inscriptions_in_block_from_page( Extension(page_config): Extension>, Extension(index): Extension>, - Extension(block_index_state): Extension>, Path((block_height, page_index)): Path<(u64, usize)>, accept_json: AcceptJson, ) -> ServerResult { - let block_index = block_index_state - .block_index - .read() - .map_err(|err| anyhow!("block index RwLock poisoned: {}", err))?; - - let inscriptions = index - .get_inscriptions_in_block(&block_index, block_height) - .map_err(|e| ServerError::NotFound(format!("Failed to get inscriptions in block: {}", e)))?; + let inscriptions = index.get_inscriptions_in_block(block_height)?; Ok(if accept_json.0 { Json(InscriptionsJson::new(inscriptions, None, None, None, None)).into_response() @@ -1107,13 +1069,7 @@ impl Server { index.block_height()?.unwrap_or(Height(0)).n(), inscriptions, page_index, - ) - .map_err(|e| { - ServerError::NotFound(format!( - "Failed to get inscriptions in inscriptions block page: {}", - e - )) - })? + )? .page(page_config, index.has_sat_index()?) .into_response() }) @@ -1180,7 +1136,7 @@ impl Server { #[cfg(test)] mod tests { - use {super::*, reqwest::Url, std::net::TcpListener}; + use {super::*, reqwest::Url, serde::de::DeserializeOwned, std::net::TcpListener}; struct TestServer { bitcoin_rpc_server: test_bitcoincore_rpc::Handle, @@ -1215,6 +1171,17 @@ mod tests { ) } + fn new_with_regtest_with_json_api() -> Self { + Self::new_server( + test_bitcoincore_rpc::builder() + .network(bitcoin::network::constants::Network::Regtest) + .build(), + None, + &["--chain", "regtest", "--enable-json-api"], + &[], + ) + } + fn new_with_regtest_with_index_sats() -> Self { Self::new_server( test_bitcoincore_rpc::builder() @@ -1319,6 +1286,24 @@ mod tests { reqwest::blocking::get(self.join_url(path.as_ref())).unwrap() } + pub(crate) fn get_json(&self, path: impl AsRef) -> T { + if let Err(error) = self.index.update() { + log::error!("{error}"); + } + + let client = reqwest::blocking::Client::new(); + + let response = client + .get(self.join_url(path.as_ref())) + .header(reqwest::header::ACCEPT, "application/json") + .send() + .unwrap(); + + assert_eq!(response.status(), StatusCode::OK); + + response.json().unwrap() + } + fn join_url(&self, url: &str) -> Url { self.url.join(url).unwrap() } @@ -1928,7 +1913,7 @@ mod tests { server.mine_blocks(1); server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], fee: 50 * 100_000_000, ..Default::default() }); @@ -1936,8 +1921,12 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 1, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 2, + 1, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); @@ -2079,7 +2068,7 @@ mod tests { test_server.mine_blocks(1); let transaction = TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], fee: 0, ..Default::default() }; @@ -2321,7 +2310,7 @@ mod tests { server.mine_blocks(1); server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], outputs: 2, fee: 0, ..Default::default() @@ -2345,7 +2334,7 @@ mod tests { server.mine_blocks(1); server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], + inputs: &[(1, 0, 0, Default::default())], outputs: 2, fee: 2, ..Default::default() @@ -2408,8 +2397,12 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 1, + 0, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); @@ -2429,8 +2422,12 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain;charset=utf-8", b"\xc3\x28").to_witness(), + inputs: &[( + 1, + 0, + 0, + inscription("text/plain;charset=utf-8", b"\xc3\x28").to_witness(), + )], ..Default::default() }); @@ -2449,12 +2446,16 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription( - "text/plain;charset=utf-8", - "", - ) - .to_witness(), + inputs: &[( + 1, + 0, + 0, + inscription( + "text/plain;charset=utf-8", + "", + ) + .to_witness(), + )], ..Default::default() }); @@ -2474,8 +2475,7 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("audio/flac", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("audio/flac", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -2495,8 +2495,12 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("application/pdf", "hello").to_witness(), + inputs: &[( + 1, + 0, + 0, + inscription("application/pdf", "hello").to_witness(), + )], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -2516,8 +2520,7 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("image/png", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("image/png", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -2538,8 +2541,12 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/html;charset=utf-8", "hello").to_witness(), + inputs: &[( + 1, + 0, + 0, + inscription("text/html;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); @@ -2559,8 +2566,7 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/foo", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/foo", "hello").to_witness())], ..Default::default() }); @@ -2580,8 +2586,7 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("video/webm", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("video/webm", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; @@ -2601,8 +2606,7 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/foo", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/foo", "hello").to_witness())], ..Default::default() }); @@ -2621,8 +2625,7 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/foo", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/foo", "hello").to_witness())], ..Default::default() }); @@ -2641,8 +2644,7 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/foo", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/foo", "hello").to_witness())], ..Default::default() }); @@ -2673,8 +2675,7 @@ mod tests { server.mine_blocks(1); server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/foo", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/foo", "hello").to_witness())], ..Default::default() }); @@ -2693,8 +2694,12 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: Inscription::new(Some("foo/bar".as_bytes().to_vec()), None).to_witness(), + inputs: &[( + 1, + 0, + 0, + Inscription::new(Some("foo/bar".as_bytes().to_vec()), None).to_witness(), + )], ..Default::default() }); @@ -2715,8 +2720,12 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: Inscription::new(Some("image/png".as_bytes().to_vec()), None).to_witness(), + inputs: &[( + 1, + 0, + 0, + Inscription::new(Some("image/png".as_bytes().to_vec()), None).to_witness(), + )], ..Default::default() }); @@ -2737,8 +2746,7 @@ mod tests { server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/foo", "hello").to_witness(), + inputs: &[(1, 0, 0, inscription("text/foo", "hello").to_witness())], ..Default::default() }); @@ -2769,8 +2777,7 @@ mod tests { for i in 0..101 { server.mine_blocks(1); server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(i + 1, 0, 0)], - witness: inscription("text/foo", "hello").to_witness(), + inputs: &[(i + 1, 0, 0, inscription("text/foo", "hello").to_witness())], ..Default::default() }); } @@ -2791,8 +2798,7 @@ mod tests { for i in 0..101 { server.mine_blocks(1); server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(i + 1, 0, 0)], - witness: inscription("text/foo", "hello").to_witness(), + inputs: &[(i + 1, 0, 0, inscription("text/foo", "hello").to_witness())], ..Default::default() }); } @@ -2855,8 +2861,12 @@ mod tests { let bitcoin_rpc_server = test_bitcoincore_rpc::spawn(); bitcoin_rpc_server.mine_blocks(1); let txid = bitcoin_rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0)], - witness: inscription("text/plain;charset=utf-8", "hello").to_witness(), + inputs: &[( + 1, + 0, + 0, + inscription("text/plain;charset=utf-8", "hello").to_witness(), + )], ..Default::default() }); let inscription = InscriptionId { txid, index: 0 }; @@ -2879,4 +2889,71 @@ mod tests { &fs::read_to_string("templates/preview-unknown.html").unwrap(), ); } + + #[test] + fn inscription_links_to_parent() { + let server = TestServer::new_with_regtest_with_json_api(); + server.mine_blocks(1); + + let parent_txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], + ..Default::default() + }); + + server.mine_blocks(1); + + let parent_inscription_id = InscriptionId { + txid: parent_txid, + index: 0, + }; + + let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[ + ( + 2, + 0, + 0, + Inscription { + content_type: Some("text/plain".into()), + body: Some("hello".into()), + parent: Some(parent_inscription_id.parent_value()), + unrecognized_even_field: false, + } + .to_witness(), + ), + (2, 1, 0, Default::default()), + ], + ..Default::default() + }); + + server.mine_blocks(1); + + let inscription_id = InscriptionId { txid, index: 0 }; + + server.assert_response_regex( + format!("/inscription/{inscription_id}"), + StatusCode::OK, + format!(".*Inscription 1.*
parent
.*
{parent_inscription_id}
.*"), + ); + + server.assert_response_regex( + format!("/inscription/{parent_inscription_id}"), + StatusCode::OK, + format!(".*Inscription 0.*
children
.*.*.*"), + ); + + assert_eq!( + server + .get_json::(format!("/inscription/{inscription_id}")) + .parent, + Some(parent_inscription_id), + ); + + assert_eq!( + server + .get_json::(format!("/inscription/{parent_inscription_id}")) + .children, + [inscription_id], + ); + } } diff --git a/src/subcommand/subsidy.rs b/src/subcommand/subsidy.rs index 0a7fbb54ce..9f0db8a981 100644 --- a/src/subcommand/subsidy.rs +++ b/src/subcommand/subsidy.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Debug, Parser)] pub(crate) struct Subsidy { - #[clap(help = "List sats in subsidy at .")] + #[arg(help = "List sats in subsidy at .")] height: Height, } diff --git a/src/subcommand/traits.rs b/src/subcommand/traits.rs index 9ef2726655..2b9a18de17 100644 --- a/src/subcommand/traits.rs +++ b/src/subcommand/traits.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Debug, Parser)] pub(crate) struct Traits { - #[clap(help = "Show traits for .")] + #[arg(help = "Show traits for .")] sat: Sat, } diff --git a/src/subcommand/wallet.rs b/src/subcommand/wallet.rs index 376e55631e..772afc419e 100644 --- a/src/subcommand/wallet.rs +++ b/src/subcommand/wallet.rs @@ -29,27 +29,27 @@ pub mod transactions; #[derive(Debug, Parser)] pub(crate) enum Wallet { - #[clap(about = "Get wallet balance")] + #[command(about = "Get wallet balance")] Balance, - #[clap(about = "Create new wallet")] + #[command(about = "Create new wallet")] Create(create::Create), - #[clap(about = "Create inscription")] + #[command(about = "Create inscription")] Inscribe(inscribe::Inscribe), - #[clap(about = "List wallet inscriptions")] + #[command(about = "List wallet inscriptions")] Inscriptions, - #[clap(about = "Generate receive address")] + #[command(about = "Generate receive address")] Receive, - #[clap(about = "Restore wallet")] + #[command(about = "Restore wallet")] Restore(restore::Restore), - #[clap(about = "List wallet satoshis")] + #[command(about = "List wallet satoshis")] Sats(sats::Sats), - #[clap(about = "Send sat or inscription")] + #[command(about = "Send sat or inscription")] Send(send::Send), - #[clap(about = "See wallet transactions")] + #[command(about = "See wallet transactions")] Transactions(transactions::Transactions), - #[clap(about = "List all unspent outputs in wallet")] + #[command(about = "List all unspent outputs in wallet")] Outputs, - #[clap(about = "List unspent cardinal outputs in wallet")] + #[command(about = "List unspent cardinal outputs in wallet")] Cardinals, } diff --git a/src/subcommand/wallet/create.rs b/src/subcommand/wallet/create.rs index d3a98b6e03..a715151e9e 100644 --- a/src/subcommand/wallet/create.rs +++ b/src/subcommand/wallet/create.rs @@ -9,7 +9,7 @@ pub struct Output { #[derive(Debug, Parser)] pub(crate) struct Create { - #[clap( + #[arg( long, default_value = "", help = "Use to derive wallet seed." diff --git a/src/subcommand/wallet/inscribe.rs b/src/subcommand/wallet/inscribe.rs index a75480bed6..72ef8f42c6 100644 --- a/src/subcommand/wallet/inscribe.rs +++ b/src/subcommand/wallet/inscribe.rs @@ -7,14 +7,13 @@ use { key::{TapTweak, TweakedKeyPair, TweakedPublicKey, UntweakedKeyPair}, locktime::absolute::LockTime, policy::MAX_STANDARD_TX_WEIGHT, - secp256k1::{ - self, constants::SCHNORR_SIGNATURE_SIZE, rand, schnorr::Signature, Secp256k1, XOnlyPublicKey, - }, + secp256k1::{self, constants::SCHNORR_SIGNATURE_SIZE, rand, Secp256k1, XOnlyPublicKey}, sighash::{Prevouts, SighashCache, TapSighashType}, + taproot::Signature, taproot::{ControlBlock, LeafVersion, TapLeafHash, TaprootBuilder}, ScriptBuf, Witness, }, - bitcoincore_rpc::bitcoincore_rpc_json::{ImportDescriptors, Timestamp}, + bitcoincore_rpc::bitcoincore_rpc_json::{ImportDescriptors, SignRawTransactionInput, Timestamp}, bitcoincore_rpc::Client, std::collections::BTreeSet, }; @@ -23,51 +22,63 @@ use { pub struct Output { pub commit: Txid, pub inscription: InscriptionId, + pub parent: Option, pub reveal: Txid, - pub fees: u64, + pub total_fees: u64, +} + +#[derive(Clone)] +struct ParentInfo { + destination: Address, + location: SatPoint, + tx_out: TxOut, } #[derive(Debug, Parser)] pub(crate) struct Inscribe { - #[clap(long, help = "Inscribe ")] + #[arg(long, help = "Inscribe .")] pub(crate) satpoint: Option, - #[clap(long, help = "Use fee rate of sats/vB")] + #[arg(long, help = "Use fee rate of sats/vB.")] pub(crate) fee_rate: FeeRate, - #[clap( + #[arg( long, help = "Use sats/vbyte for commit transaction.\nDefaults to if unset." )] pub(crate) commit_fee_rate: Option, - #[clap(help = "Inscribe sat with contents of ")] + #[arg(help = "Inscribe sat with contents of .")] pub(crate) file: PathBuf, - #[clap(long, help = "Do not back up recovery key.")] + #[arg(long, help = "Do not back up recovery key.")] pub(crate) no_backup: bool, - #[clap( + #[arg( long, help = "Do not check that transactions are equal to or below the MAX_STANDARD_TX_WEIGHT of 400,000 weight units. Transactions over this limit are currently nonstandard and will not be relayed by bitcoind in its default configuration. Do not use this flag unless you understand the implications." )] pub(crate) no_limit: bool, - #[clap(long, help = "Don't sign or broadcast transactions.")] + #[arg(long, help = "Don't sign or broadcast transactions.")] pub(crate) dry_run: bool, - #[clap(long, help = "Send inscription to .")] + #[arg(long, help = "Send inscription to .")] pub(crate) destination: Option>, - #[clap( + #[arg( long, - help = "Amount of postage to include in the inscription. Default `10000sat`" + help = "Amount of postage to include in the inscription. Default `10000sat`." )] pub(crate) postage: Option, + #[clap(long, help = "Make inscription a child of .")] + pub(crate) parent: Option, + #[clap(long, help = "Allow reinscription.")] + pub(crate) reinscribe: bool, } impl Inscribe { pub(crate) fn run(self, options: Options) -> SubcommandResult { - let inscription = Inscription::from_file(options.chain(), &self.file)?; + let inscription = Inscription::from_file(options.chain(), &self.file, self.parent)?; let index = Index::open(&options)?; index.update()?; let client = options.bitcoin_rpc_client_for_wallet_command(false)?; - let mut utxos = index.get_unspent_outputs(Wallet::load(&options)?)?; + let utxos = index.get_unspent_outputs(Wallet::load(&options)?)?; let inscriptions = index.get_inscriptions(utxos.clone())?; @@ -81,96 +92,130 @@ impl Inscribe { None => get_change_address(&client, &options)?, }; - let (unsigned_commit_tx, reveal_tx, _recovery_key_pair) = + let parent_info = if let Some(parent_id) = self.parent { + if let Some(satpoint) = index.get_inscription_satpoint_by_id(parent_id)? { + if !utxos.contains_key(&satpoint.outpoint) { + return Err(anyhow!(format!("parent {parent_id} not in wallet"))); + } + + Some(ParentInfo { + destination: get_change_address(&client, &options)?, + location: satpoint, + tx_out: index + .get_transaction(satpoint.outpoint.txid)? + .expect("parent transaction not found in index") + .output + .into_iter() + .nth(satpoint.outpoint.vout.try_into().unwrap()) + .expect("current transaction output"), + }) + } else { + return Err(anyhow!(format!("parent {parent_id} does not exist"))); + } + } else { + None + }; + + let (commit_tx, reveal_tx, _recovery_key_pair, total_fees) = Inscribe::create_inscription_transactions( self.satpoint, + parent_info, inscription, inscriptions, options.chain().network(), - utxos.clone(), + utxos, commit_tx_change, reveal_tx_destination, self.commit_fee_rate.unwrap_or(self.fee_rate), self.fee_rate, self.no_limit, + self.reinscribe, match self.postage { Some(postage) => postage, _ => TransactionBuilder::TARGET_POSTAGE, }, )?; - utxos.insert( - reveal_tx.input[0].previous_output, - Amount::from_sat( - unsigned_commit_tx.output[reveal_tx.input[0].previous_output.vout as usize].value, - ), - ); - - let fees = - Self::calculate_fee(&unsigned_commit_tx, &utxos) + Self::calculate_fee(&reveal_tx, &utxos); - if self.dry_run { - Ok(Box::new(Output { - commit: unsigned_commit_tx.txid(), + return Ok(Box::new(Output { + commit: commit_tx.txid(), reveal: reveal_tx.txid(), inscription: InscriptionId { txid: reveal_tx.txid(), index: 0, }, - fees, - })) - } else { - // Litecoin does not support this functionality - // if !self.no_backup { - // Inscribe::backup_recovery_key(&client, recovery_key_pair, options.chain().network())?; - // } - - let signed_raw_commit_tx = client - .sign_raw_transaction_with_wallet(&unsigned_commit_tx, None, None)? - .hex; - - let commit = client - .send_raw_transaction(&signed_raw_commit_tx) - .context("Failed to send commit transaction")?; - - let reveal = client - .send_raw_transaction(&reveal_tx) - .context("Failed to send reveal transaction")?; - - Ok(Box::new(Output { - commit, - reveal, - inscription: InscriptionId { - txid: reveal, - index: 0, - }, - fees, - })) + parent: self.parent, + total_fees, + })); } - } - fn calculate_fee(tx: &Transaction, utxos: &BTreeMap) -> u64 { - tx.input - .iter() - .map(|txin| utxos.get(&txin.previous_output).unwrap().to_sat()) - .sum::() - .checked_sub(tx.output.iter().map(|txout| txout.value).sum::()) - .unwrap() + let signed_commit_tx = client + .sign_raw_transaction_with_wallet(&commit_tx, None, None)? + .hex; + + let signed_reveal_tx = if self.parent.is_some() { + client + .sign_raw_transaction_with_wallet( + &reveal_tx, + Some( + &commit_tx + .output + .iter() + .enumerate() + .map(|(vout, output)| SignRawTransactionInput { + txid: commit_tx.txid(), + vout: vout.try_into().unwrap(), + script_pub_key: output.script_pubkey.clone(), + redeem_script: None, + amount: Some(Amount::from_sat(output.value)), + }) + .collect::>(), + ), + None, + )? + .hex + } else { + bitcoin::consensus::encode::serialize(&reveal_tx) + }; + + // TODO: Litecoin core does not support descriptor wallets + // if !self.no_backup { + // Inscribe::backup_recovery_key(&client, recovery_key_pair, options.chain().network())?; + // } + + let commit = client.send_raw_transaction(&signed_commit_tx)?; + + let reveal = client + .send_raw_transaction(&signed_reveal_tx) + .context("Failed to send reveal transaction")?; + + Ok(Box::new(Output { + commit, + reveal, + parent: self.parent, + inscription: InscriptionId { + txid: reveal, + index: 0, + }, + total_fees, + })) } fn create_inscription_transactions( satpoint: Option, + parent_info: Option, inscription: Inscription, inscriptions: BTreeMap, network: Network, - utxos: BTreeMap, + mut utxos: BTreeMap, change: [Address; 2], destination: Address, commit_fee_rate: FeeRate, reveal_fee_rate: FeeRate, no_limit: bool, + reinscribe: bool, postage: Amount, - ) -> Result<(Transaction, Transaction, TweakedKeyPair)> { + ) -> Result<(Transaction, Transaction, TweakedKeyPair, u64)> { let satpoint = if let Some(satpoint) = satpoint { satpoint } else { @@ -189,9 +234,16 @@ impl Inscribe { .ok_or_else(|| anyhow!("wallet contains no cardinal utxos"))? }; + let mut reinscription = false; + for (inscribed_satpoint, inscription_id) in &inscriptions { - if inscribed_satpoint == &satpoint { - return Err(anyhow!("sat at {} already inscribed", satpoint)); + if *inscribed_satpoint == satpoint { + reinscription = true; + if reinscribe { + continue; + } else { + return Err(anyhow!("sat at {} already inscribed", satpoint)); + } } if inscribed_satpoint.outpoint == satpoint.outpoint { @@ -202,6 +254,12 @@ impl Inscribe { } } + if reinscribe && !reinscription { + return Err(anyhow!( + "reinscribe flag set but this would not be a reinscription" + )); + } + let secp256k1 = Secp256k1::new(); let key_pair = UntweakedKeyPair::new(&secp256k1, &mut rand::thread_rng()); let (public_key, _parity) = XOnlyPublicKey::from_keypair(&key_pair); @@ -224,21 +282,43 @@ impl Inscribe { let commit_tx_address = Address::p2tr_tweaked(taproot_spend_info.output_key(), network); + let mut inputs = vec![OutPoint::null()]; + let mut outputs = vec![TxOut { + script_pubkey: destination.script_pubkey(), + value: 0, + }]; + + if let Some(ParentInfo { + location, + destination, + tx_out, + }) = parent_info.clone() + { + inputs.insert(0, location.outpoint); + outputs.insert( + 0, + TxOut { + script_pubkey: destination.script_pubkey(), + value: tx_out.value, + }, + ); + } + + let commit_input = if parent_info.is_some() { 1 } else { 0 }; + let (_, reveal_fee) = Self::build_reveal_transaction( &control_block, reveal_fee_rate, - OutPoint::null(), - TxOut { - script_pubkey: destination.script_pubkey(), - value: 0, - }, + inputs.clone(), + commit_input, + outputs.clone(), &reveal_script, ); let unsigned_commit_tx = TransactionBuilder::new( satpoint, inscriptions, - utxos, + utxos.clone(), commit_tx_address.clone(), change, commit_fee_rate, @@ -253,50 +333,74 @@ impl Inscribe { .find(|(_vout, output)| output.script_pubkey == commit_tx_address.script_pubkey()) .expect("should find sat commit/inscription output"); + inputs[commit_input] = OutPoint { + txid: unsigned_commit_tx.txid(), + vout: vout.try_into().unwrap(), + }; + + outputs[commit_input] = TxOut { + script_pubkey: destination.script_pubkey(), + value: output.value, + }; + let (mut reveal_tx, fee) = Self::build_reveal_transaction( &control_block, reveal_fee_rate, - OutPoint { - txid: unsigned_commit_tx.txid(), - vout: vout.try_into().unwrap(), - }, - TxOut { - script_pubkey: destination.script_pubkey(), - value: output.value, - }, + inputs, + commit_input, + outputs.clone(), &reveal_script, ); - reveal_tx.output[0].value = reveal_tx.output[0] + reveal_tx.output[commit_input].value = reveal_tx.output[commit_input] .value .checked_sub(fee.to_sat()) .context("commit transaction output value insufficient to pay transaction fee")?; - if reveal_tx.output[0].value < reveal_tx.output[0].script_pubkey.dust_value().to_sat() { + if reveal_tx.output[commit_input].value + < reveal_tx.output[commit_input] + .script_pubkey + .dust_value() + .to_sat() + { bail!("commit transaction output would be dust"); } + let mut prevouts = vec![unsigned_commit_tx.output[0].clone()]; + + if let Some(parent_info) = parent_info { + prevouts.insert(0, parent_info.tx_out); + } + let mut sighash_cache = SighashCache::new(&mut reveal_tx); - let signature_hash = sighash_cache + let sighash = sighash_cache .taproot_script_spend_signature_hash( - 0, - &Prevouts::All(&[output]), + commit_input, + &Prevouts::All(&prevouts), TapLeafHash::from_script(&reveal_script, LeafVersion::TapScript), TapSighashType::Default, ) .expect("signature hash should compute"); - let signature = secp256k1.sign_schnorr( - &secp256k1::Message::from_slice(signature_hash.as_ref()) + let sig = secp256k1.sign_schnorr( + &secp256k1::Message::from_slice(sighash.as_ref()) .expect("should be cryptographically secure hash"), &key_pair, ); let witness = sighash_cache - .witness_mut(0) + .witness_mut(commit_input) .expect("getting mutable witness reference should work"); - witness.push(signature.as_ref()); + + witness.push( + Signature { + sig, + hash_ty: TapSighashType::Default, + } + .to_vec(), + ); + witness.push(reveal_script); witness.push(&control_block.serialize()); @@ -319,7 +423,74 @@ impl Inscribe { ); } - Ok((unsigned_commit_tx, reveal_tx, recovery_key_pair)) + utxos.insert( + reveal_tx.input[commit_input].previous_output, + Amount::from_sat( + unsigned_commit_tx.output[reveal_tx.input[commit_input].previous_output.vout as usize] + .value, + ), + ); + + let total_fees = + Self::calculate_fee(&unsigned_commit_tx, &utxos) + Self::calculate_fee(&reveal_tx, &utxos); + + Ok((unsigned_commit_tx, reveal_tx, recovery_key_pair, total_fees)) + } + + fn build_reveal_transaction( + control_block: &ControlBlock, + fee_rate: FeeRate, + inputs: Vec, + commit_input_index: usize, + outputs: Vec, + script: &Script, + ) -> (Transaction, Amount) { + let reveal_tx = Transaction { + input: inputs + .iter() + .map(|outpoint| TxIn { + previous_output: *outpoint, + script_sig: script::Builder::new().into_script(), + witness: Witness::new(), + sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, + }) + .collect(), + output: outputs, + lock_time: LockTime::ZERO, + version: 1, + }; + + let fee = { + let mut reveal_tx = reveal_tx.clone(); + + for (current_index, txin) in reveal_tx.input.iter_mut().enumerate() { + // add dummy inscription witness for reveal input/commit output + if current_index == commit_input_index { + txin.witness.push( + Signature::from_slice(&[0; SCHNORR_SIGNATURE_SIZE]) + .unwrap() + .to_vec(), + ); + txin.witness.push(script); + txin.witness.push(&control_block.serialize()); + } else { + txin.witness = Witness::from_slice(&[&[0; SCHNORR_SIGNATURE_SIZE]]); + } + } + + fee_rate.fee(reveal_tx.vsize()) + }; + + (reveal_tx, fee) + } + + fn calculate_fee(tx: &Transaction, utxos: &BTreeMap) -> u64 { + tx.input + .iter() + .map(|txin| utxos.get(&txin.previous_output).unwrap().to_sat()) + .sum::() + .checked_sub(tx.output.iter().map(|txout| txout.value).sum::()) + .unwrap() } #[allow(dead_code)] @@ -350,42 +521,6 @@ impl Inscribe { Ok(()) } - - fn build_reveal_transaction( - control_block: &ControlBlock, - fee_rate: FeeRate, - input: OutPoint, - output: TxOut, - script: &Script, - ) -> (Transaction, Amount) { - let reveal_tx = Transaction { - input: vec![TxIn { - previous_output: input, - script_sig: script::Builder::new().into_script(), - witness: Witness::new(), - sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, - }], - output: vec![output], - lock_time: LockTime::ZERO, - version: 1, - }; - - let fee = { - let mut reveal_tx = reveal_tx.clone(); - - reveal_tx.input[0].witness.push( - Signature::from_slice(&[0; SCHNORR_SIGNATURE_SIZE]) - .unwrap() - .as_ref(), - ); - reveal_tx.input[0].witness.push(script); - reveal_tx.input[0].witness.push(&control_block.serialize()); - - fee_rate.fee(reveal_tx.vsize()) - }; - - (reveal_tx, fee) - } } #[cfg(test)] @@ -399,8 +534,9 @@ mod tests { let commit_address = change(0); let reveal_address = recipient(); - let (commit_tx, reveal_tx, _private_key) = Inscribe::create_inscription_transactions( + let (commit_tx, reveal_tx, _private_key, _) = Inscribe::create_inscription_transactions( Some(satpoint(1, 0)), + None, inscription, BTreeMap::new(), Network::Bitcoin, @@ -410,6 +546,7 @@ mod tests { FeeRate::try_from(1.0).unwrap(), FeeRate::try_from(1.0).unwrap(), false, + false, TransactionBuilder::TARGET_POSTAGE, ) .unwrap(); @@ -425,14 +562,15 @@ mod tests { } #[test] - fn inscript_tansactions_opt_in_to_rbf() { + fn inscribe_tansactions_opt_in_to_rbf() { let utxos = vec![(outpoint(1), Amount::from_sat(20000))]; let inscription = inscription("text/plain", "ord"); let commit_address = change(0); let reveal_address = recipient(); - let (commit_tx, reveal_tx, _) = Inscribe::create_inscription_transactions( + let (commit_tx, reveal_tx, _, _) = Inscribe::create_inscription_transactions( Some(satpoint(1, 0)), + None, inscription, BTreeMap::new(), Network::Bitcoin, @@ -442,6 +580,7 @@ mod tests { FeeRate::try_from(1.0).unwrap(), FeeRate::try_from(1.0).unwrap(), false, + false, TransactionBuilder::TARGET_POSTAGE, ) .unwrap(); @@ -469,6 +608,7 @@ mod tests { let error = Inscribe::create_inscription_transactions( satpoint, + None, inscription, inscriptions, Network::Bitcoin, @@ -478,6 +618,7 @@ mod tests { FeeRate::try_from(1.0).unwrap(), FeeRate::try_from(1.0).unwrap(), false, + false, TransactionBuilder::TARGET_POSTAGE, ) .unwrap_err() @@ -512,6 +653,7 @@ mod tests { assert!(Inscribe::create_inscription_transactions( satpoint, + None, inscription, inscriptions, Network::Bitcoin, @@ -521,6 +663,7 @@ mod tests { FeeRate::try_from(1.0).unwrap(), FeeRate::try_from(1.0).unwrap(), false, + false, TransactionBuilder::TARGET_POSTAGE, ) .is_ok()) @@ -547,8 +690,9 @@ mod tests { let reveal_address = recipient(); let fee_rate = 3.3; - let (commit_tx, reveal_tx, _private_key) = Inscribe::create_inscription_transactions( + let (commit_tx, reveal_tx, _private_key, _) = Inscribe::create_inscription_transactions( satpoint, + None, inscription, inscriptions, bitcoin::Network::Signet, @@ -558,6 +702,7 @@ mod tests { FeeRate::try_from(fee_rate).unwrap(), FeeRate::try_from(fee_rate).unwrap(), false, + false, TransactionBuilder::TARGET_POSTAGE, ) .unwrap(); @@ -588,6 +733,89 @@ mod tests { ); } + #[test] + fn inscribe_with_parent() { + let utxos = vec![ + (outpoint(1), Amount::from_sat(10_000)), + (outpoint(2), Amount::from_sat(20_000)), + ]; + + let mut inscriptions = BTreeMap::new(); + let parent_inscription = inscription_id(1); + let parent_info = ParentInfo { + destination: change(3), + location: SatPoint { + outpoint: outpoint(1), + offset: 0, + }, + tx_out: TxOut { + script_pubkey: change(0).script_pubkey(), + value: 10000, + }, + }; + + inscriptions.insert(parent_info.location, parent_inscription); + + let child_inscription = inscription("text/plain", [b'O'; 100]); + + let commit_address = change(1); + let reveal_address = recipient(); + let fee_rate = 4.0; + + let (commit_tx, reveal_tx, _private_key, _) = Inscribe::create_inscription_transactions( + None, + Some(parent_info.clone()), + child_inscription, + inscriptions, + bitcoin::Network::Signet, + utxos.into_iter().collect(), + [commit_address, change(2)], + reveal_address, + FeeRate::try_from(fee_rate).unwrap(), + FeeRate::try_from(fee_rate).unwrap(), + false, + false, + TransactionBuilder::TARGET_POSTAGE, + ) + .unwrap(); + + let sig_vbytes = 17; + let fee = FeeRate::try_from(fee_rate) + .unwrap() + .fee(commit_tx.vsize() + sig_vbytes) + .to_sat(); + + let reveal_value = commit_tx + .output + .iter() + .map(|o| o.value) + .reduce(|acc, i| acc + i) + .unwrap(); + + assert_eq!(reveal_value, 20_000 - fee); + + let sig_vbytes = 16; + let fee = FeeRate::try_from(fee_rate) + .unwrap() + .fee(reveal_tx.vsize() + sig_vbytes) + .to_sat(); + + assert_eq!(fee, commit_tx.output[0].value - reveal_tx.output[1].value,); + assert_eq!( + reveal_tx.output[0].script_pubkey, + parent_info.destination.script_pubkey() + ); + assert_eq!(reveal_tx.output[0].value, parent_info.tx_out.value); + pretty_assert_eq!( + reveal_tx.input[0], + TxIn { + previous_output: parent_info.location.outpoint, + sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, + ..Default::default() + } + ); + } + #[test] fn inscribe_with_commit_fee_rate() { let utxos = vec![ @@ -610,8 +838,9 @@ mod tests { let commit_fee_rate = 3.3; let fee_rate = 1.0; - let (commit_tx, reveal_tx, _private_key) = Inscribe::create_inscription_transactions( + let (commit_tx, reveal_tx, _private_key, _) = Inscribe::create_inscription_transactions( satpoint, + None, inscription, inscriptions, bitcoin::Network::Signet, @@ -621,6 +850,7 @@ mod tests { FeeRate::try_from(commit_fee_rate).unwrap(), FeeRate::try_from(fee_rate).unwrap(), false, + false, TransactionBuilder::TARGET_POSTAGE, ) .unwrap(); @@ -662,6 +892,7 @@ mod tests { let error = Inscribe::create_inscription_transactions( satpoint, + None, inscription, BTreeMap::new(), Network::Bitcoin, @@ -671,6 +902,7 @@ mod tests { FeeRate::try_from(1.0).unwrap(), FeeRate::try_from(1.0).unwrap(), false, + false, TransactionBuilder::TARGET_POSTAGE, ) .unwrap_err() @@ -692,8 +924,9 @@ mod tests { let commit_address = change(0); let reveal_address = recipient(); - let (_commit_tx, reveal_tx, _private_key) = Inscribe::create_inscription_transactions( + let (_commit_tx, reveal_tx, _private_key, _) = Inscribe::create_inscription_transactions( satpoint, + None, inscription, BTreeMap::new(), Network::Bitcoin, @@ -703,6 +936,7 @@ mod tests { FeeRate::try_from(1.0).unwrap(), FeeRate::try_from(1.0).unwrap(), true, + false, TransactionBuilder::TARGET_POSTAGE, ) .unwrap(); diff --git a/src/subcommand/wallet/restore.rs b/src/subcommand/wallet/restore.rs index 578e22c7a4..5dedf8cf7c 100644 --- a/src/subcommand/wallet/restore.rs +++ b/src/subcommand/wallet/restore.rs @@ -2,9 +2,9 @@ use super::*; #[derive(Debug, Parser)] pub(crate) struct Restore { - #[clap(help = "Restore wallet from ")] + #[arg(help = "Restore wallet from ")] mnemonic: Mnemonic, - #[clap( + #[arg( long, default_value = "", help = "Use when deriving wallet" diff --git a/src/subcommand/wallet/sats.rs b/src/subcommand/wallet/sats.rs index 7ddf829519..cd55f8c00b 100644 --- a/src/subcommand/wallet/sats.rs +++ b/src/subcommand/wallet/sats.rs @@ -2,7 +2,7 @@ use {super::*, crate::wallet::Wallet}; #[derive(Debug, Parser)] pub(crate) struct Sats { - #[clap( + #[arg( long, help = "Find satoshis listed in first column of tab-separated value file ." )] diff --git a/src/subcommand/wallet/send.rs b/src/subcommand/wallet/send.rs index 8aa015a297..22b214c2da 100644 --- a/src/subcommand/wallet/send.rs +++ b/src/subcommand/wallet/send.rs @@ -1,12 +1,12 @@ use {super::*, crate::subcommand::wallet::transaction_builder::Target, crate::wallet::Wallet}; -#[derive(Debug, Parser)] +#[derive(Debug, Parser, Clone)] pub(crate) struct Send { address: Address, outgoing: Outgoing, - #[clap(long, help = "Use fee rate of sats/vB")] + #[arg(long, help = "Use fee rate of sats/vB")] fee_rate: FeeRate, - #[clap( + #[arg( long, help = "Target amount of postage to include with sent inscriptions. Default `10000sat`" )] diff --git a/src/subcommand/wallet/transaction_builder.rs b/src/subcommand/wallet/transaction_builder.rs index 87a12e624a..4e7c549640 100644 --- a/src/subcommand/wallet/transaction_builder.rs +++ b/src/subcommand/wallet/transaction_builder.rs @@ -8,18 +8,17 @@ //! constructing ordinal-aware transactions that take these additional //! conditions into account. //! -//! The external interfaces are -//! `TransactionBuilder::build_transaction_with_postage`, and -//! `TransactionBuilder::build_transaction_with_value`. Both return a -//! constructed transaction given the arguments, which include the outgoing sat +//! The external interface is +//! `TransactionBuilder::new`, which returns a +//! constructed transaction given the `Target`, which include the outgoing sat //! to send, the wallets current UTXOs and their sat ranges, and the -//! recipient's address. +//! recipient's address. To build the transaction call `Transaction::build_transaction`. //! -//! `TransactionBuilder::build_transaction_with_postage` ensures that the +//! `Target::Postage` ensures that the //! outgoing value is at most 20,000 sats, reducing it to 10,000 sats if coin //! selection requires adding excess value. //! -//! `TransactionBuilder::build_transaction_with_value` ensures that the +//! `Target::Value(Amount)` ensures that the //! outgoing value is exactly the requested amount, //! //! Internally, `TransactionBuilder` calls multiple methods that implement @@ -28,7 +27,7 @@ //! //! This module is heavily tested. For all features of transaction //! construction, there should be a positive test that checks that the feature -//! is implemented correctly, an assertion in the final `Transaction::build` +//! is implemented correctly, an assertion in the final `Transaction::build_transaction` //! method that the built transaction is correct with respect to the feature, //! and a test that the assertion fires as expected. diff --git a/src/subcommand/wallet/transactions.rs b/src/subcommand/wallet/transactions.rs index 942315be53..f2466db39e 100644 --- a/src/subcommand/wallet/transactions.rs +++ b/src/subcommand/wallet/transactions.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Debug, Parser)] pub(crate) struct Transactions { - #[clap(long, help = "Fetch at most transactions.")] + #[arg(long, help = "Fetch at most transactions.")] limit: Option, } diff --git a/src/templates/inscription.rs b/src/templates/inscription.rs index 3589ccac60..854a21ace9 100644 --- a/src/templates/inscription.rs +++ b/src/templates/inscription.rs @@ -3,6 +3,7 @@ use super::*; #[derive(Boilerplate)] pub(crate) struct InscriptionHtml { pub(crate) chain: Chain, + pub(crate) children: Vec, pub(crate) genesis_fee: u64, pub(crate) genesis_height: u64, pub(crate) inscription: Inscription, @@ -10,6 +11,7 @@ pub(crate) struct InscriptionHtml { pub(crate) next: Option, pub(crate) number: i64, pub(crate) output: Option, + pub(crate) parent: Option, pub(crate) previous: Option, pub(crate) sat: Option, pub(crate) satpoint: SatPoint, @@ -18,28 +20,32 @@ pub(crate) struct InscriptionHtml { #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct InscriptionJson { + pub address: Option, + pub children: Vec, + pub content_length: Option, + pub content_type: Option, + pub genesis_fee: u64, + pub genesis_height: u64, pub inscription_id: InscriptionId, + pub next: Option, pub number: i64, - pub genesis_height: u64, - pub genesis_fee: u64, pub output_value: Option, - pub address: Option, + pub parent: Option, + pub previous: Option, pub sat: Option, pub satpoint: SatPoint, - pub content_type: Option, - pub content_length: Option, pub timestamp: i64, - pub previous: Option, - pub next: Option, } impl InscriptionJson { pub fn new( chain: Chain, + children: Vec, genesis_fee: u64, genesis_height: u64, inscription: Inscription, inscription_id: InscriptionId, + parent: Option, next: Option, number: i64, output: Option, @@ -50,8 +56,10 @@ impl InscriptionJson { ) -> Self { Self { inscription_id, + children, number, genesis_height, + parent, genesis_fee, output_value: output.as_ref().map(|o| o.value), address: output @@ -87,6 +95,8 @@ mod tests { fn without_sat_nav_links_or_output() { assert_regex_match!( InscriptionHtml { + children: Vec::new(), + parent: None, chain: Chain::Mainnet, genesis_fee: 1, genesis_height: 0, @@ -142,6 +152,8 @@ mod tests { fn with_output() { assert_regex_match!( InscriptionHtml { + children: Vec::new(), + parent: None, chain: Chain::Mainnet, genesis_fee: 1, genesis_height: 0, @@ -179,6 +191,8 @@ mod tests { fn with_sat() { assert_regex_match!( InscriptionHtml { + children: Vec::new(), + parent: None, chain: Chain::Mainnet, genesis_fee: 1, genesis_height: 0, @@ -211,6 +225,8 @@ mod tests { fn with_prev_and_next() { assert_regex_match!( InscriptionHtml { + children: Vec::new(), + parent: None, chain: Chain::Mainnet, genesis_fee: 1, genesis_height: 0, @@ -241,6 +257,8 @@ mod tests { fn with_cursed_and_unbound() { assert_regex_match!( InscriptionHtml { + children: Vec::new(), + parent: None, chain: Chain::Mainnet, genesis_fee: 1, genesis_height: 0, @@ -272,4 +290,127 @@ mod tests { .unindent() ); } + + #[test] + fn with_parent() { + assert_regex_match!( + InscriptionHtml { + children: Vec::new(), + parent: Some(inscription_id(2)), + chain: Chain::Mainnet, + genesis_fee: 1, + genesis_height: 0, + inscription: inscription("text/plain;charset=utf-8", "HELLOWORLD"), + inscription_id: inscription_id(1), + next: None, + number: 1, + output: None, + previous: None, + sat: None, + satpoint: satpoint(1, 0), + timestamp: timestamp(0), + }, + " +

Inscription 1

+
+
+ +
+
+
+
id
+
1{64}i1
+
parent
+
2{64}i2
+
preview
+
link
+
content
+
link
+
content length
+
10 bytes
+
content type
+
text/plain;charset=utf-8
+
timestamp
+
+
genesis height
+
0
+
genesis fee
+
1
+
genesis transaction
+
1{64}
+
location
+
1{64}:1:0
+
output
+
1{64}:1
+
offset
+
0
+
+ " + .unindent() + ); + } + + #[test] + fn with_children() { + assert_regex_match!( + InscriptionHtml { + children: vec![inscription_id(2), inscription_id(3)], + parent: None, + chain: Chain::Mainnet, + genesis_fee: 1, + genesis_height: 0, + inscription: inscription("text/plain;charset=utf-8", "HELLOWORLD"), + inscription_id: inscription_id(1), + next: None, + number: 1, + output: None, + previous: None, + sat: None, + satpoint: satpoint(1, 0), + timestamp: timestamp(0), + }, + " +

Inscription 1

+
+
+ +
+
+
+
id
+
1{64}i1
+
preview
+
link
+
content
+
link
+
content length
+
10 bytes
+
content type
+
text/plain;charset=utf-8
+
timestamp
+
+
genesis height
+
0
+
genesis fee
+
1
+
genesis transaction
+
1{64}
+
location
+
1{64}:1:0
+
output
+
1{64}:1
+
offset
+
0
+
children
+
+
+ + +
+
+
+ " + .unindent() + ); + } } diff --git a/src/test.rs b/src/test.rs index 43fd74e927..cdc70671ce 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,9 +1,10 @@ pub(crate) use { super::*, crate::inscription::TransactionInscription, - bitcoin::blockdata::script::PushBytesBuf, - bitcoin::blockdata::{opcodes, script}, - bitcoin::{ScriptBuf, Witness}, + bitcoin::{ + blockdata::{opcodes, script, script::PushBytesBuf}, + ScriptBuf, Witness, + }, pretty_assertions::assert_eq as pretty_assert_eq, std::iter, test_bitcoincore_rpc::TransactionTemplate, @@ -87,6 +88,7 @@ pub(crate) fn change(n: u64) -> Address { 0 => "tb1qjsv26lap3ffssj6hfy8mzn0lg5vte6a42j75ww", 1 => "tb1qakxxzv9n7706kc3xdcycrtfv8cqv62hnwexc0l", 2 => "tb1qxz9yk0td0yye009gt6ayn7jthz5p07a75luryg", + 3 => "tb1qe62s57n77pfhlw2vtqlhm87dwj75l6fguavjjq", _ => panic!(), } .parse::>() diff --git a/static/index.js b/static/index.js index 2c6632f9d4..e3153179b7 100644 --- a/static/index.js +++ b/static/index.js @@ -23,3 +23,12 @@ window.addEventListener('keydown', e => { return; } }); + +const search = document.querySelector('form[action="/search"]'); +const query = search.querySelector('input[name="query"]'); + +search.addEventListener('submit', (e) => { + if (!query.value) { + e.preventDefault(); + } +}); diff --git a/templates/inscription.html b/templates/inscription.html index 11b7542ac5..1b272941c5 100644 --- a/templates/inscription.html +++ b/templates/inscription.html @@ -19,6 +19,10 @@

Inscription {{ self.number }} (unstable)

id
{{ self.inscription_id }}
+%% if let Some(parent) = &self.parent { +
parent
+
{{ parent }}
+%% } %% if let Some(output) = &self.output { %% if let Ok(address) = self.chain.address_from_script(&output.script_pubkey ) {
address
@@ -63,4 +67,14 @@

Inscription {{ self.number }} (unstable)

%% }
offset
{{ self.satpoint.offset }}
+%% if !self.children.is_empty() { +
children
+
+
+%% for id in &self.children { + {{Iframe::thumbnail(*id)}} +%% } +
+
+%% }
diff --git a/test-bitcoincore-rpc/src/api.rs b/test-bitcoincore-rpc/src/api.rs index 8c1226ebcc..3477faa0e7 100644 --- a/test-bitcoincore-rpc/src/api.rs +++ b/test-bitcoincore-rpc/src/api.rs @@ -54,7 +54,7 @@ pub trait Api { fn sign_raw_transaction_with_wallet( &self, tx: String, - utxos: Option<()>, + utxos: Option>, sighash_type: Option<()>, ) -> Result; diff --git a/test-bitcoincore-rpc/src/lib.rs b/test-bitcoincore-rpc/src/lib.rs index 60de3d90ca..bbae7d788e 100644 --- a/test-bitcoincore-rpc/src/lib.rs +++ b/test-bitcoincore-rpc/src/lib.rs @@ -22,7 +22,8 @@ use { GetNetworkInfoResult, GetRawTransactionResult, GetTransactionResult, GetTransactionResultDetail, GetTransactionResultDetailCategory, GetWalletInfoResult, ImportDescriptors, ImportMultiResult, ListDescriptorsResult, ListTransactionResult, - ListUnspentResultEntry, LoadWalletResult, SignRawTransactionResult, Timestamp, WalletTxInfo, + ListUnspentResultEntry, LoadWalletResult, SignRawTransactionInput, SignRawTransactionResult, + Timestamp, WalletTxInfo, }, jsonrpc_core::{IoHandler, Value}, jsonrpc_http_server::{CloseHandle, ServerBuilder}, @@ -119,10 +120,9 @@ pub fn spawn() -> Handle { #[derive(Clone)] pub struct TransactionTemplate<'a> { pub fee: u64, - pub inputs: &'a [(usize, usize, usize)], + pub inputs: &'a [(usize, usize, usize, Witness)], pub output_values: &'a [u64], pub outputs: usize, - pub witness: Witness, } #[derive(Clone, Debug, PartialEq)] @@ -154,7 +154,6 @@ impl<'a> Default for TransactionTemplate<'a> { inputs: &[], output_values: &[], outputs: 1, - witness: Witness::default(), } } } diff --git a/test-bitcoincore-rpc/src/server.rs b/test-bitcoincore-rpc/src/server.rs index 04b27f6c16..591ce3b562 100644 --- a/test-bitcoincore-rpc/src/server.rs +++ b/test-bitcoincore-rpc/src/server.rs @@ -241,15 +241,16 @@ impl Api for Server { fn sign_raw_transaction_with_wallet( &self, tx: String, - utxos: Option<()>, + _utxos: Option>, sighash_type: Option<()>, ) -> Result { - assert_eq!(utxos, None, "utxos param not supported"); assert_eq!(sighash_type, None, "sighash_type param not supported"); let mut transaction: Transaction = deserialize(&hex::decode(tx).unwrap()).unwrap(); for input in &mut transaction.input { - input.witness = Witness::from_slice(&[&[0; 64]]); + if input.witness.is_empty() { + input.witness = Witness::from_slice(&[&[0; 64]]); + } } Ok( @@ -293,13 +294,15 @@ impl Api for Server { assert_eq!(verbose, None); let mut state = self.state.lock().unwrap(); - let locked = state.locked.iter().cloned().collect(); + let locked = state.locked.iter().cloned().collect::>(); let value = Amount::from_btc(amount).expect("error converting amount to sat"); - let utxo = state.utxos.first_entry().expect("failed to get a utxo"); - let outpoint = utxo.key(); - let utxo_amount = utxo.get(); + let (outpoint, utxo_amount) = state + .utxos + .iter() + .find(|(outpoint, amount)| *amount >= &value && !locked.contains(outpoint)) + .expect("failed to get a utxo"); let mut transaction = Transaction { version: 1, diff --git a/test-bitcoincore-rpc/src/state.rs b/test-bitcoincore-rpc/src/state.rs index 0a05039aa5..9d1a6c8d4d 100644 --- a/test-bitcoincore-rpc/src/state.rs +++ b/test-bitcoincore-rpc/src/state.rs @@ -131,14 +131,14 @@ impl State { pub(crate) fn broadcast_tx(&mut self, template: TransactionTemplate) -> Txid { let mut total_value = 0; let mut input = Vec::new(); - for (height, tx, vout) in template.inputs.iter() { + for (height, tx, vout, witness) in template.inputs.iter() { let tx = &self.blocks.get(&self.hashes[*height]).unwrap().txdata[*tx]; total_value += tx.output[*vout].value; input.push(TxIn { previous_output: OutPoint::new(tx.txid(), *vout as u32), script_sig: ScriptBuf::new(), sequence: Sequence::MAX, - witness: template.witness.clone(), + witness: witness.clone(), }); } diff --git a/tests/command_builder.rs b/tests/command_builder.rs index c2e9dadd53..d6b354a1fd 100644 --- a/tests/command_builder.rs +++ b/tests/command_builder.rs @@ -34,6 +34,7 @@ pub(crate) struct CommandBuilder { expected_stderr: Expected, expected_stdout: Expected, rpc_server_url: Option, + stdin: Vec, tempdir: TempDir, } @@ -45,6 +46,7 @@ impl CommandBuilder { expected_stderr: Expected::String(String::new()), expected_stdout: Expected::String(String::new()), rpc_server_url: None, + stdin: Vec::new(), tempdir: TempDir::new().unwrap(), } } @@ -61,6 +63,10 @@ impl CommandBuilder { } } + pub(crate) fn stdin(self, stdin: Vec) -> Self { + Self { stdin, ..self } + } + pub(crate) fn stdout_regex(self, expected_stdout: impl AsRef) -> Self { Self { expected_stdout: Expected::regex(expected_stdout.as_ref()), @@ -109,7 +115,7 @@ impl CommandBuilder { command .env("ORD_INTEGRATION_TEST", "1") - .stdin(Stdio::null()) + .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .current_dir(&self.tempdir) @@ -120,25 +126,18 @@ impl CommandBuilder { command } - pub(crate) fn run_and_extract_file(self, path: impl AsRef) -> String { - let output = self.command().output().unwrap(); - let stdout = str::from_utf8(&output.stdout).unwrap(); - let stderr = str::from_utf8(&output.stderr).unwrap(); - if output.status.code() != Some(self.expected_exit_code) { - panic!( - "Test failed: {}\nstdout:\n{}\nstderr:\n{}", - output.status, stdout, stderr - ); - } + fn run(self) -> (TempDir, String) { + let child = self.command().spawn().unwrap(); - self.expected_stderr.assert_match(stderr); - self.expected_stdout.assert_match(stdout); + child + .stdin + .as_ref() + .unwrap() + .write_all(&self.stdin) + .unwrap(); - fs::read_to_string(self.tempdir.path().join(path)).unwrap() - } + let output = child.wait_with_output().unwrap(); - pub(crate) fn run_and_extract_stdout(self) -> String { - let output = self.command().output().unwrap(); let stdout = str::from_utf8(&output.stdout).unwrap(); let stderr = str::from_utf8(&output.stderr).unwrap(); if output.status.code() != Some(self.expected_exit_code) { @@ -151,7 +150,16 @@ impl CommandBuilder { self.expected_stderr.assert_match(stderr); self.expected_stdout.assert_match(stdout); - stdout.into() + (self.tempdir, stdout.into()) + } + + pub(crate) fn run_and_extract_file(self, path: impl AsRef) -> String { + let tempdir = self.run().0; + fs::read_to_string(tempdir.path().join(path)).unwrap() + } + + pub(crate) fn run_and_extract_stdout(self) -> String { + self.run().1 } pub(crate) fn run_and_deserialize_output(self) -> T { diff --git a/tests/decode.rs b/tests/decode.rs new file mode 100644 index 0000000000..a11adb751f --- /dev/null +++ b/tests/decode.rs @@ -0,0 +1,78 @@ +use { + super::*, + bitcoin::{ + absolute::LockTime, consensus::Encodable, opcodes, script, ScriptBuf, Sequence, Transaction, + TxIn, Witness, + }, + ord::{subcommand::decode::Output, Inscription}, +}; + +fn transaction() -> Vec { + let script = script::Builder::new() + .push_opcode(opcodes::OP_FALSE) + .push_opcode(opcodes::all::OP_IF) + .push_slice(b"ord") + .push_slice([1]) + .push_slice(b"text/plain;charset=utf-8") + .push_slice([]) + .push_slice([0, 1, 2, 3]) + .push_opcode(opcodes::all::OP_ENDIF) + .into_script(); + + let mut witness = Witness::new(); + + witness.push(script); + witness.push([]); + + let transaction = Transaction { + version: 0, + lock_time: LockTime::ZERO, + input: vec![TxIn { + previous_output: OutPoint::null(), + script_sig: ScriptBuf::new(), + sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, + witness, + }], + output: Vec::new(), + }; + + let mut buffer = Vec::new(); + + transaction.consensus_encode(&mut buffer).unwrap(); + + buffer +} + +#[test] +fn from_file() { + assert_eq!( + CommandBuilder::new("decode transaction.bin") + .write("transaction.bin", transaction()) + .run_and_deserialize_output::(), + Output { + inscriptions: vec![Inscription { + body: Some(vec![0, 1, 2, 3]), + content_type: Some(b"text/plain;charset=utf-8".to_vec()), + unrecognized_even_field: false, + parent: None, + }], + } + ); +} + +#[test] +fn from_stdin() { + assert_eq!( + CommandBuilder::new("decode") + .stdin(transaction()) + .run_and_deserialize_output::(), + Output { + inscriptions: vec![Inscription { + body: Some(vec![0, 1, 2, 3]), + content_type: Some(b"text/plain;charset=utf-8".to_vec()), + unrecognized_even_field: false, + parent: None, + }], + } + ); +} diff --git a/tests/json_api.rs b/tests/json_api.rs index 059bbe4e8b..e123667ac2 100644 --- a/tests/json_api.rs +++ b/tests/json_api.rs @@ -152,6 +152,8 @@ fn get_inscription() { pretty_assert_eq!( inscription_json, InscriptionJson { + parent: None, + children: Vec::new(), inscription_id, number: 0, genesis_height: 2, @@ -184,8 +186,11 @@ fn create_210_inscriptions( rpc_server.mine_blocks(1); let txid = rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(i * 3 + 1, 0, 0), (i * 3 + 2, 0, 0), (i * 3 + 3, 0, 0)], - witness: witness.clone(), + inputs: &[ + (i * 3 + 1, 0, 0, witness.clone()), + (i * 3 + 2, 0, 0, witness.clone()), + (i * 3 + 3, 0, 0, witness.clone()), + ], ..Default::default() }); @@ -316,11 +321,17 @@ fn get_inscriptions_in_block() { create_wallet(&rpc_server); rpc_server.mine_blocks(10); + let envelope = envelope(&[b"ord", &[1], b"text/plain;charset=utf-8", &[], b"bar"]); + let txid = rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0), (2, 0, 0), (3, 0, 0)], - witness: envelope(&[b"ord", &[1], b"text/plain;charset=utf-8", &[], b"bar"]), + inputs: &[ + (1, 0, 0, envelope.clone()), + (2, 0, 0, envelope.clone()), + (3, 0, 0, envelope.clone()), + ], ..Default::default() }); + rpc_server.mine_blocks(1); for _ in 0..10 { @@ -362,9 +373,14 @@ fn get_output() { create_wallet(&rpc_server); rpc_server.mine_blocks(3); + let envelope = envelope(&[b"ord", &[1], b"text/plain;charset=utf-8", &[], b"bar"]); + let txid = rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0), (2, 0, 0), (3, 0, 0)], - witness: envelope(&[b"ord", &[1], b"text/plain;charset=utf-8", &[], b"bar"]), + inputs: &[ + (1, 0, 0, envelope.clone()), + (2, 0, 0, envelope.clone()), + (3, 0, 0, envelope.clone()), + ], ..Default::default() }); rpc_server.mine_blocks(1); diff --git a/tests/lib.rs b/tests/lib.rs index 3e2eda203f..84b056ac21 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -23,6 +23,7 @@ use { serde::de::DeserializeOwned, std::{ fs, + io::Write, net::TcpListener, path::Path, process::{Child, Command, Stdio}, @@ -92,6 +93,7 @@ mod expected; mod test_server; mod core; +mod decode; mod epochs; mod find; mod index; diff --git a/tests/wallet/inscribe.rs b/tests/wallet/inscribe.rs index ce00ae1923..c4a10257f4 100644 --- a/tests/wallet/inscribe.rs +++ b/tests/wallet/inscribe.rs @@ -226,7 +226,7 @@ fn inscribe_with_fee_rate() { create_wallet(&rpc_server); rpc_server.mine_blocks(1); - CommandBuilder::new("--index-sats wallet inscribe degenerate.png --fee-rate 2.0") + let output = CommandBuilder::new("--index-sats wallet inscribe degenerate.png --fee-rate 2.0") .write("degenerate.png", [1; 520]) .rpc_server(&rpc_server) .run_and_deserialize_output::(); @@ -259,6 +259,13 @@ fn inscribe_with_fee_rate() { let fee_rate = fee as f64 / tx2.vsize() as f64; pretty_assert_eq!(fee_rate, 2.0); + assert_eq!( + ord::FeeRate::try_from(2.0) + .unwrap() + .fee(tx1.vsize() + tx2.vsize()) + .to_sat(), + output.total_fees + ); } #[test] @@ -352,14 +359,14 @@ fn inscribe_with_dry_run_flag_fees_inscrease() { .write("degenerate.png", [1; 520]) .rpc_server(&rpc_server) .run_and_deserialize_output::() - .fees; + .total_fees; let total_fee_normal = CommandBuilder::new("wallet inscribe --dry-run degenerate.png --fee-rate 1.1") .write("degenerate.png", [1; 520]) .rpc_server(&rpc_server) .run_and_deserialize_output::() - .fees; + .total_fees; assert!(total_fee_dry_run < total_fee_normal); } @@ -440,3 +447,192 @@ fn inscribe_works_with_postage() { pretty_assert_eq!(inscriptions[0].postage, 5 * COIN_VALUE); } + +#[test] +fn inscribe_with_non_existent_parent_inscription() { + let rpc_server = test_bitcoincore_rpc::spawn(); + create_wallet(&rpc_server); + rpc_server.mine_blocks(1); + + let parent_id = "0000000000000000000000000000000000000000000000000000000000000000i0"; + + CommandBuilder::new(format!( + "wallet inscribe --fee-rate 1.0 --parent {parent_id} child.png" + )) + .write("child.png", [1; 520]) + .rpc_server(&rpc_server) + .expected_stderr(format!("error: parent {parent_id} does not exist\n")) + .expected_exit_code(1) + .run_and_extract_stdout(); +} + +#[test] +fn inscribe_with_parent_inscription_and_fee_rate() { + let rpc_server = test_bitcoincore_rpc::spawn(); + create_wallet(&rpc_server); + rpc_server.mine_blocks(1); + + let parent_output = CommandBuilder::new("wallet inscribe --fee-rate 5.0 parent.png") + .write("parent.png", [1; 520]) + .rpc_server(&rpc_server) + .run_and_deserialize_output::(); + + assert_eq!(rpc_server.descriptors().len(), 3); + let parent_id = parent_output.inscription; + + let commit_tx = &rpc_server.mempool()[0]; + let reveal_tx = &rpc_server.mempool()[1]; + + assert_eq!( + ord::FeeRate::try_from(5.0) + .unwrap() + .fee(commit_tx.vsize() + reveal_tx.vsize()) + .to_sat(), + parent_output.total_fees + ); + + rpc_server.mine_blocks(1); + + let child_output = CommandBuilder::new(format!( + "wallet inscribe --fee-rate 7.3 --parent {parent_id} child.png" + )) + .write("child.png", [1; 520]) + .rpc_server(&rpc_server) + .run_and_deserialize_output::(); + + assert_eq!(rpc_server.descriptors().len(), 4); + assert_eq!(parent_id, child_output.parent.unwrap()); + + let commit_tx = &rpc_server.mempool()[0]; + let reveal_tx = &rpc_server.mempool()[1]; + + assert_eq!( + ord::FeeRate::try_from(7.3) + .unwrap() + .fee(commit_tx.vsize() + reveal_tx.vsize()) + .to_sat(), + child_output.total_fees + ); + + rpc_server.mine_blocks(1); + + let ord_server = TestServer::spawn_with_args(&rpc_server, &[]); + + ord_server.assert_response_regex( + format!("/inscription/{}", child_output.parent.unwrap()), + format!( + ".*
children
.*.*", + child_output.inscription + ), + ); + + ord_server.assert_response_regex( + format!("/inscription/{}", child_output.inscription), + format!( + ".*
parent
.*
.*", + child_output.parent.unwrap() + ), + ); +} + +#[test] +fn reinscribe_with_flag() { + let rpc_server = test_bitcoincore_rpc::spawn(); + rpc_server.mine_blocks(1); + + assert_eq!(rpc_server.descriptors().len(), 0); + + create_wallet(&rpc_server); + + let inscribe = CommandBuilder::new("wallet inscribe tulip.png --fee-rate 5.0 ") + .write("tulip.png", [1; 520]) + .rpc_server(&rpc_server) + .run_and_deserialize_output::(); + + assert_eq!(rpc_server.descriptors().len(), 3); + + let txid = rpc_server.mine_blocks(1)[0].txdata[2].txid(); + + let ord_server = TestServer::spawn_with_args(&rpc_server, &[]); + let request = ord_server.request(format!("/content/{}", inscribe.inscription)); + + assert_eq!(request.status(), 200); + + let reinscribe = CommandBuilder::new(format!( + "wallet inscribe orchid.png --fee-rate 1.1 --reinscribe --satpoint {txid}:0:0" + )) + .write("orchid.png", [1; 520]) + .rpc_server(&rpc_server) + .run_and_deserialize_output::(); + + rpc_server.mine_blocks(1); + + let ord_server = TestServer::spawn_with_args(&rpc_server, &["--index-sats"]); + let request = ord_server.request(format!("/content/{}", reinscribe.inscription)); + + assert_eq!(request.status(), 200); + ord_server.assert_response_regex( + format!("/sat/{}", 50 * COIN_VALUE), + format!( + ".*
inscriptions
.*
.*.*", + inscribe.inscription, reinscribe.inscription + ), + ); +} + +#[test] +fn with_reinscribe_flag_but_not_actually_a_reinscription() { + let rpc_server = test_bitcoincore_rpc::spawn(); + rpc_server.mine_blocks(1); + + assert_eq!(rpc_server.descriptors().len(), 0); + + create_wallet(&rpc_server); + + CommandBuilder::new("wallet inscribe tulip.png --fee-rate 5.0 ") + .write("tulip.png", [1; 520]) + .rpc_server(&rpc_server) + .run_and_deserialize_output::(); + + let coinbase = rpc_server.mine_blocks(1)[0].txdata[0].txid(); + + CommandBuilder::new(format!( + "wallet inscribe orchid.png --fee-rate 1.1 --reinscribe --satpoint {coinbase}:0:0" + )) + .write("orchid.png", [1; 520]) + .rpc_server(&rpc_server) + .expected_exit_code(1) + .stderr_regex("error: reinscribe flag set but this would not be a reinscription.*") + .run_and_extract_stdout(); +} + +#[test] +fn try_reinscribe_without_flag() { + let rpc_server = test_bitcoincore_rpc::spawn(); + rpc_server.mine_blocks(1); + + assert_eq!(rpc_server.descriptors().len(), 0); + + create_wallet(&rpc_server); + + let reveal_txid = CommandBuilder::new("wallet inscribe tulip.png --fee-rate 5.0 ") + .write("tulip.png", [1; 520]) + .rpc_server(&rpc_server) + .run_and_deserialize_output::() + .reveal; + + assert_eq!(rpc_server.descriptors().len(), 3); + + rpc_server.mine_blocks(1); + + CommandBuilder::new(format!( + "wallet inscribe orchid.png --fee-rate 1.1 --satpoint {reveal_txid}:0:0" + )) + .write("orchid.png", [1; 520]) + .rpc_server(&rpc_server) + .expected_exit_code(1) + .stderr_regex(format!( + "error: sat at {reveal_txid}:0:0 already inscribed.*" + )) + .run_and_extract_stdout(); +} diff --git a/tests/wallet/send.rs b/tests/wallet/send.rs index d3a135b8dc..d47c8e0549 100644 --- a/tests/wallet/send.rs +++ b/tests/wallet/send.rs @@ -215,10 +215,15 @@ fn splitting_merged_inscriptions_is_possible() { create_wallet(&rpc_server); rpc_server.mine_blocks(3); + let inscription = envelope(&[b"ord", &[1], b"text/plain;charset=utf-8", &[], b"bar"]); + // merging 3 inscriptions into one utxo let reveal_txid = rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0), (2, 0, 0), (3, 0, 0)], - witness: envelope(&[b"ord", &[1], b"text/plain;charset=utf-8", &[], b"bar"]), + inputs: &[ + (1, 0, 0, inscription.clone()), + (2, 0, 0, inscription.clone()), + (3, 0, 0, inscription.clone()), + ], outputs: 1, ..Default::default() }); @@ -467,7 +472,7 @@ fn user_must_provide_fee_rate_to_send() { .rpc_server(&rpc_server) .expected_exit_code(2) .stderr_regex( - ".*error: The following required arguments were not provided: + ".*error: the following required arguments were not provided: .*--fee-rate .*", ) .run_and_extract_stdout();