assert_eq!(parse("0°1680′0″0‴").unwrap(), 1054200000000000); assert_eq!( Sat(1914226250000000).degree().to_string(), "0°122762′794″0‴" ); assert_eq!(parse("0°122762′794″0‴").unwrap(), 1914226250000000); } #[test] fn period() { assert_eq!(Sat(0).period(), 0); assert_eq!(Sat(10080000000000).period(), 1); assert_eq!(Sat(2099999997689999).period(), 3437); assert_eq!(Sat(10075000000000).period(), 0); assert_eq!(Sat(10080000000000 - 1).period(), 0); assert_eq!(Sat(10080000000000).period(), 1); assert_eq!(Sat(10080000000000 + 1).period(), 1); assert_eq!(Sat(10085000000000).period(), 1); assert_eq!(Sat(2099999997689999).period(), 3437); } #[test] fn epoch() { assert_eq!(Sat(0).epoch(), 0); assert_eq!(Sat(1).epoch(), 0); assert_eq!( Sat(50 * COIN_VALUE * u64::from(SUBSIDY_HALVING_INTERVAL)).epoch(), 1 ); assert_eq!(Sat(2099999997689999).epoch(), 32); } #[test] fn epoch_position() { assert_eq!(Epoch(0).starting_sat().epoch_position(), 0); #44,988,857text- Update changelog - 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/i18n-helpers/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), #44,988,856text match config { SpawnConfig::Https(_) => "https", _ => "http", } ); } Ok(tokio::spawn(async move { match config { SpawnConfig::Https(acceptor) => { axum_server::Server::bind(addr) .handle(handle) .acceptor(acceptor) .serve(router.into_make_service()) .await } SpawnConfig::Redirect(destination) => { axum_server::Server::bind(addr) .handle(handle) .serve( Router::new() .fallback(Self::redirect_http_to_https) .layer(Extension(destination)) .into_make_service(), ) .await } SpawnConfig::Http => { axum_server::Server::bind(addr) .handle(handle) .serve(router.into_make_service()) .await } } })) } fn acme_cache(acme_cache: Option<&PathBuf>, options: &Options) -> Result<PathBuf> { #44,988,849text assert!(parse("0°2016′0″0‴").is_ok()); assert!(parse("0°2016′1″0‴").is_err()); assert!(parse("0°0′336″0‴").is_ok()); } #[test] fn from_str_degree_post_distribution() { assert!(parse("5°209999′1007″0‴").is_ok()); assert!(parse("5°0′1008″0‴").is_err()); } #[test] fn from_str_name() { assert_eq!(parse("nvtdijuwxlp").unwrap(), 0); assert_eq!(parse("a").unwrap(), 2099999997689999); assert!(parse("(").is_err()); assert!(parse("").is_err()); assert!(parse("nvtdijuwxlq").is_err()); assert!(parse("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").is_err()); } #[test] fn cycle() { assert_eq!( SUBSIDY_HALVING_INTERVAL * CYCLE_EPOCHS % DIFFCHANGE_INTERVAL, 0 ); for i in 1..CYCLE_EPOCHS { assert_ne!(i * SUBSIDY_HALVING_INTERVAL % DIFFCHANGE_INTERVAL, 0); } assert_eq!( CYCLE_EPOCHS * SUBSIDY_HALVING_INTERVAL % DIFFCHANGE_INTERVAL, 0 ); assert_eq!(Sat(0).cycle(), 0); assert_eq!(Sat(2067187500000000 - 1).cycle(), 0); #44,988,838textuse {super::*, fee_rate::FeeRate}; #[derive(Debug, Parser)] pub(crate) struct Preview { #[command(flatten)] server: super::server::Server, inscriptions: Vec<PathBuf>, } struct KillOnDrop(process::Child); impl Drop for KillOnDrop { fn drop(&mut self) { self.0.kill().unwrap() } } impl Preview { pub(crate) fn run(self) -> SubcommandResult { let tmpdir = TempDir::new()?; let rpc_port = TcpListener::bind("127.0.0.1:0")?.local_addr()?.port(); let bitcoin_data_dir = tmpdir.path().join("bitcoin"); fs::create_dir(&bitcoin_data_dir)?; let _bitcoind = KillOnDrop( Command::new("bitcoind") .arg({ let mut arg = OsString::from("-datadir="); arg.push(&bitcoin_data_dir); arg }) .arg("-regtest") .arg("-txindex") .arg("-listen=0") .arg(format!("-rpcport={rpc_port}")) .spawn() .context("failed to spawn `bitcoind`")?, ); let options = Options { chain_argument: Chain::Regtest, #44,988,826text Ok(Updater { range_cache: HashMap::new(), height: index.block_count()?, index, sat_ranges_since_flush: 0, outputs_cached: 0, outputs_inserted_since_flush: 0, outputs_traversed: 0, }) } pub(crate) fn update_index(&mut self) -> Result { let mut wtx = self.index.begin_write()?; let starting_height = u32::try_from(self.index.client.get_block_count()?).unwrap() + 1; wtx .open_table(WRITE_TRANSACTION_STARTING_BLOCK_COUNT_TO_TIMESTAMP)? .insert( &self.height, &SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .map(|duration| duration.as_millis()) .unwrap_or(0), )?; let mut progress_bar = if cfg!(test) || log_enabled!(log::Level::Info) || starting_height <= self.height || integration_test() { None } else { let progress_bar = ProgressBar::new(starting_height.into()); progress_bar.set_position(self.height.into()); progress_bar.set_style( #44,983,934textuse super::*; #[derive(Serialize, Deserialize)] pub struct Output { pub mnemonic: Mnemonic, pub passphrase: Option<String>, } #[derive(Debug, Parser)] pub(crate) struct Create { #[arg( long, default_value = "", help = "Use <PASSPHRASE> to derive wallet seed." )] pub(crate) passphrase: String, } impl Create { pub(crate) fn run(self, options: Options) -> SubcommandResult { let mut entropy = [0; 16]; rand::thread_rng().fill_bytes(&mut entropy); let mnemonic = Mnemonic::from_entropy(&entropy)?; initialize_wallet(&options, mnemonic.to_seed(self.passphrase.clone()))?; Ok(Box::new(Output { mnemonic, passphrase: Some(self.passphrase), })) } } #44,981,448text TransactionHtml::new(transaction, Some(blockhash(0)), None, Chain::Mainnet, None), " <h1>Transaction <span class=monospace>[[:xdigit:]]{64}</span></h1> <dl> <dt>block</dt> <dd><a href=/block/0{64} class=monospace>0{64}</a></dd> </dl> .* " .unindent() ); } } #44,981,436text <dt>witness</dt><dd class=monospace>010101</dd> <dt>script sig</dt><dd class=monospace>OP_PUSHBYTES_3 666f6f</dd> <dt>text</dt><dd>\x03foo</dd> </dl> " .unindent() ); } #[test] fn skip_empty_items() { pretty_assert_eq!( InputHtml { path: (1, 2, 3), input: TxIn { previous_output: OutPoint::null(), script_sig: script::Builder::new().into_script(), sequence: Sequence::MAX, witness: Witness::new(), } } .to_string(), " <h1>Input /1/2/3</h1> <dl> </dl> " .unindent() ); } } #44,981,427textsat satpoint %% for (sat, satpoint) in &self.0 { {{sat}} {{satpoint}} %% } #44,981,280textmsgid "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?" #44,979,340text"OP_FALSE\n" "OP_IF\n" " OP_PUSH \"ord\"\n" " OP_PUSH 1\n" " OP_PUSH \"text/plain;charset=utf-8\"\n" " OP_PUSH 2\n" " OP_PUSH 0xff\n" " OP_PUSH 0\n" " OP_PUSH \"Hello, world!\"\n" "OP_ENDIF\n" "```" msgstr "" #: src/inscriptions/pointer.md:36 #, fuzzy msgid "An inscription with pointer 256:" msgstr "一个带有256指针的铭文" #: src/inscriptions/pointer.md:38 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 2\n" " OP_PUSH 0x0001\n" " OP_PUSH 0\n" " OP_PUSH \"Hello, world!\"\n" "OP_ENDIF\n" "```" msgstr "" #: src/inscriptions/pointer.md:51 msgid "" "An inscription with pointer 256, with trailing zeroes, which are ignored:" msgstr "" "带有指针256的铭文,尾随零被忽略:" #: src/inscriptions/pointer.md:53 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 2\n" " OP_PUSH 0x000100\n" " OP_PUSH 0\n" " OP_PUSH \"Hello, world!\"\n" "OP_ENDIF\n" "```" msgstr "" #: src/faq.md:1 #44,979,328text"inscription is made as usual. The value of the pointer field is a little " "endian integer, with trailing zeroes ignored." msgstr "" "为了在输入的第一个以外的sat上进行铭刻," "可以提供一个以0为基础的整数,称作 \"指针\",并配以标签 `2`, " "这将导致铭文被做在给定位置的输出的sat上。 " "如果指针等于或大于铭文交易输出中的总sat数,那么它将被忽略, " "而铭文将像往常一样被铭刻。指针字段的值是一个小端整数,尾随零将被忽略。 " #: src/inscriptions/pointer.md:12 msgid "" "An even tag is used, so that old versions of `ord` consider the inscription " "to be unbound, instead of assigning it, incorrectly, to the first sat." msgstr "" "使用了偶数标签,所以旧版本的 `ord` 会把铭文视为无约束,而不是错误地将其分配到第一个sat。" #: src/inscriptions/pointer.md:15 msgid "" "This can be used to create multiple inscriptions in a single transaction on " "different sats, when otherwise they would be made on the same sat." msgstr "" "这可以用于一次性在不同的sat上创建多个铭文,否则它们将被制成在同一个sat上" #: src/inscriptions/pointer.md:18 #, fuzzy msgid "Examples" msgstr "示例" #: src/inscriptions/pointer.md:21 #, fuzzy msgid "An inscription with pointer 255:" msgstr "一个带有255指针的铭文" #: src/inscriptions/pointer.md:23 msgid "" "```\n" #44,979,327text