Skip to content

Commit

Permalink
translate to english
Browse files Browse the repository at this point in the history
  • Loading branch information
pause125 committed May 16, 2024
1 parent e421b84 commit 5dd16c3
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,125 @@ Rooch incorporates the [bitcoin-move](https://github.com/rooch-network/rooch/tre

## Reading Bitcoin Blocks and Transactions in Contracts

In Rooch, Bitcoin blocks and transactions are written into the global state of Rooch by a Relayer. All states are stored in `0x4::bitcoin::BitcoinBlockStore`. Developers can read Bitcoin block and transaction data through the interfaces provided by the `0x4::bitcoin` module.

### 1. `BitcoinBlockStore` Structure and Reading Interfaces

The `BitcoinBlockStore` structure stores all block headers and transaction data. Its fields are as follows:

- `latest_block_height`: Optional `u64`, representing the height of the latest block.
- `blocks`: `Table<address, Header>`, storing the mapping from block hash to block header. Developers can read the corresponding block header by block hash.
- `height_to_hash`: `Table<u64, address>`, storing the mapping from block height to block hash.
- `hash_to_height`: `Table<address, u64>`, storing the mapping from block hash to block height.
- `txs`: `Table<address, Transaction>`, storing the mapping from transaction hash to transaction.
- `tx_ids`: `TableVec<address>`, storing all transaction hashes.

The `BitcoinBlockStore` is stored in a shared object, and anyone can read the block and transaction data stored in the `BitcoinBlockStore` object through the interfaces provided in the `0x4::bitcoin` module.

The specific interfaces are as follows:

- `get_tx`: Get the transaction with the specified transaction hash.

- Parameters

- `txid`: `address`, representing the transaction hash.

- Return Value

- `Option<Transaction>`: If the transaction exists, return the transaction; otherwise, return none.

- `get_block`: Get the block header with the specified block hash.

- Parameters

- `block_hash`: `address`, representing the block hash.

- Return Value

- `Option<Header>`: If the block exists, return the block header; otherwise, return none.

- `get_block_height`: Get the block height with the specified block hash.

- Parameters

- `block_hash`: `address`, representing the block hash.

- Return Value

- `Option<u64>`: If the block exists, return its block height; otherwise, return none.

- `get_block_by_height`: Get the block header with the specified block height.

- Parameters

- `block_height`: `u64`, representing the block height.

- Return Value

- `Option<Header>`: If the block exists, return the block header; otherwise, return none.

- `get_latest_block_height`: Get the height of the latest block.

- Return Value

- `Option<u64>`: If the latest block exists, return the block height; otherwise, return none.

### 2. `Header` Structure and Reading Interfaces

The `Header` structure represents the Bitcoin block header, used to store the metadata of the block, including the version number, the hash of the previous block, the root hash of the Merkle tree, the timestamp, the target value, and the nonce. In Rooch, the Header can be read through the `0x4::bitcoin::get_block` and `0x4::bitcoin::get_block_by_height` interfaces.

Its field definitions are as follows:

- `version`: `u32`, representing the version number of the block, currently used for signaling soft forks.
- `prev_blockhash`: `address`, representing the hash of the previous block.
- `merkle_root`: `address`, representing the root hash of the Merkle tree of transactions in the block.
- `time`: `u32`, representing the timestamp of the block, provided by the miner.
- `bits`: `u32`, representing the target value of the block, the block hash must be lower than this value.
- `nonce`: `u32`, representing the chosen nonce to obtain a sufficiently low block hash.

The corresponding reading interfaces are defined in the `0x4::types` module.

### 3. `Transaction` Structure and Reading Interfaces

The `Transaction` structure represents a Bitcoin transaction, used to store the metadata of the transaction, including the version number, inputs, outputs, lock time, and transaction hash. In Rooch, the Transaction can be read through the `0x4::bitcoin::get_tx` interface.

Its field definitions are as follows:

- `id`: `address`, representing the unique identifier (txid) of the transaction.
- `version`: `u32`, representing the protocol version of the transaction, currently expected to be 1 or 2 (BIP 68).
- `lock_time`: `u32`, representing the locked block height or timestamp, before which the transaction cannot be included in a block.
- `input`: `vector<TxIn>`, representing the list of transaction inputs.
- `output`: `vector<TxOut>`, representing the list of transaction outputs.

`TxIn` represents an input in a Bitcoin transaction. It contains a reference to an output of a previous transaction, a script signature, a sequence number, and witness data. The fields are as follows:

- `previous_output`: `OutPoint`, representing a reference to the output of a previous transaction.
- `script_sig`: `vector<u8>`, representing the script signature, which pushes values onto the stack to make the referenced output script be accepted.
- `sequence`: `u32`, representing the sequence number, which suggests to miners which of two conflicting transactions to choose, or set to 0xFFFFFFFF to ignore this feature. This feature is usually not used because miner behavior cannot be enforced.
- `witness`: `Witness`, representing the witness data, which is an array of byte arrays.

The `TxIn` structure is a key component of Bitcoin transactions, defining the source of transaction inputs. The `previous_output` field references an output of a previous transaction, the `script_sig` field contains data for verifying the referenced output script, the `sequence` field is used to specify the order of transactions, and the `witness` field contains witness data supporting certain types of transactions.

`TxOut` represents an output in a Bitcoin transaction. It contains the amount of the output and the script. The fields are as follows:

- `value`: `u64`, representing the amount of the output, in satoshis.
- `script_pubkey`: `vector<u8>`, representing the output script, which defines how the recipient proves they own the funds.
- `recipient_address`: `BitcoinAddress`, representing the recipient address of the output. If known, this will be a valid Bitcoin address; if unknown, the address bytes will be empty.

The reading interfaces for the fields of `Transaction`, `TxIn`, and `TxOut` are defined in the `0x4::types` module.

<Callout>
TODO: This section of the document needs improvement

1. How to read transactions, including explanations of transaction fields.
2. How to read blocks, including explanations of block fields.
3. An explanation of how Bitcoin hashes are expressed and differ in Move is required.
1. An explanation of how Bitcoin hashes are expressed and differ in Move is required.
</Callout>

## Application Scenarios

1. Use a Bitcoin hash as a random number seed to implement a random number generator. Note, this scenario requires using the hash of future blocks to prevent predictability.
2. Embed application data in Bitcoin via OP_RETURN, then read the OP_RETURN data from the transaction using a Move contract for processing.
3. Validate Bitcoin transaction scripts in Move to enable mixed programming with Move and Bitcoin Script. This feature is still in development, and progress can be tracked at [Issue #1651](https://github.com/rooch-network/rooch/issues/1651).
3. Validate Bitcoin transaction scripts in Move to enable mixed programming with Move and Bitcoin Script. This feature is still in development, and progress can be tracked at [Issue #1651](https://github.com/rooch-network/rooch/issues/1651).

## Example
1. [btc_blind_box](https://github.com/rooch-network/rooch/blob/main/examples/btc_blind_box)
A simple blind box opening example that uses Bitcoin block hashes as the random number seed, implementing the functionality of opening blind boxes. The process of claiming a blind box is divided into two stages: 1. Application stage; 2. Claiming stage. During the application stage, players can apply for a blind box and receive a random magic number. After the application period ends, all players' magic numbers become unchangeable. Then, after a certain interval, the claiming stage begins, where the latest Bitcoin block header is used as the random seed, combined with the player's magic number to generate a random number, determining the rarity of the blind box the player receives. This ensures sufficient randomness; at the same time, during the application stage, players cannot predict the information of future block headers, thus ensuring unpredictability.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Rooch 内置了 [bitcoin-move](https://github.com/rooch-network/rooch/tree/main/

## 在合约中读取 Bitcoin 区块和交易

在 Rooch 中,Bitcoin 区块和交易被中继器(Relayer)读取并写入到 Rooch 的全局状态中,所有状态都储存在 `0x4::bitcoin::BitcoinBlockStore` 中。开发者可以通过 `0x4::bitcoin` 模块提供的接口来读取 Bitcoin 区块和交易数据。
在 Rooch 中,Bitcoin 区块和交易被中继器(Relayer)写入到 Rooch 的全局状态中,所有状态都储存在 `0x4::bitcoin::BitcoinBlockStore` 中。开发者可以通过 `0x4::bitcoin` 模块提供的接口来读取 Bitcoin 区块和交易数据。

### 1. `BitcoinBlockStore` 结构体与读取接口

Expand Down Expand Up @@ -127,4 +127,5 @@ TODO: 这部分文档需要改进
3. 在 Move 中校验 Bitcoin 交易的 Script,实现 Move 和 Bitcoin Script 混合编程。这个特性尚在开发中,可以跟踪 [Issue #1651](https://github.com/rooch-network/rooch/issues/1651)

## 示例
1. [btc_blind_box](https://github.com/rooch-network/rooch/blob/main/examples/btc_blind_box):一个简单的开盲盒示例,使用 Bitcoin 区块哈希作为随机数种子,实现了开盲盒的功能。
1. [btc_blind_box](https://github.com/rooch-network/rooch/blob/main/examples/btc_blind_box)
一个简单的开盲盒示例,使用 Bitcoin 区块哈希作为随机数种子,实现了开盲盒的功能。领取盲盒分两个阶段:1. 申请阶段;2.领取阶段。在申请阶段,玩家可以申请一个盲盒,得到一个随机的 magic number,申请期结束后,所有玩家的 magic number 不可变更。然后经过一定间隔后,进入领取阶段,领取阶段以 Bitcoin 最新的区块头为随机种子,结合玩家的 magic number 得到一个随机数,从而确定玩家得到的盲盒等级,这保证了充分的随机性;同时,在申请阶段,玩家无法预测未来区块头的信息,因此也保证了不可预测性。
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,65 @@ As shown above, this represents a Bitcoin blockchain state in Move, such as an O

## Programming with UTXO

<Callout>
TODO: This section of the document needs improvement
### 1. Description of UTXO Fields

1. Explanation of UTXO fields
2. How to accept UTXO as method parameters
3. How to store data in the UTXO's temporary area
</Callout>
UTXO (Unspent Transaction Output) is a core concept in the Bitcoin system, representing unspent transaction outputs. In the Rooch Bitcoin framework, the `UTXO` structure defines several key fields of a UTXO:

- `txid`: `address`, Represents the hash value of the transaction that generated this UTXO.
- `vout`: `u32`, Represents the index position of this UTXO within its transaction.
- `value`: `u64`, Represents the value of this UTXO, i.e., the amount of Bitcoin it contains.
- `seals`: Represents protocol inscriptions associated with this UTXO, stored using the `SimpleMultiMap` structure, mapping protocol names (`String` type) to object IDs (`ObjectID` type).

### 2. How to Accept UTXO as Method Parameters

In Rooch, UTXOs are stored as Objects in the global state. Developers can obtain a (mutable) reference to `Object<UTXO>` via `ObjectID`. The (mutable) reference to `Object<UTXO>` can be passed as a parameter to a function. Here are some examples:

- Passing an immutable reference: `fun some_function(utxo: &UTXO)`
- Passing a mutable reference: `fun some_function(utxo: &mut UTXO)`

`UTXO` objects are created and destroyed by MoveVM in real-time when parsing Bitcoin transactions, and developers cannot obtain ownership of them. They can only read the state of `UTXO` through references or store state in the temporary state area of `UTXO` through a mutable reference.

### 3. How to Store Data in the Temporary Area of UTXO

The temporary area is a field of `Object<UTXO>` and can be used to store some state. Once the UTXO is spent on Bitcoin, the MoveVM will promptly destroy the `UTXO` object on Rooch, and the state in its temporary state area will also be cleared.

The `Temporary Area` in the code is used to store temporary state data related to `UTXO`. Here are the interfaces for adding, modifying, and deleting state in the temporary area of `UTXO`:

- Use the `add_temp_state` function to add state data to the temporary area of `UTXO`. The function accepts an `UTXO` object and the state data to be stored.
- Use the `contains_temp_state` function to check if the temporary area of `UTXO` contains state data of a specific type.
- Use the `borrow_temp_state` function to borrow an immutable reference to state data of a specific type in the temporary area.
- Use the `borrow_mut_temp_state` function to borrow a mutable reference to state data of a specific type in the temporary area to modify it.
- Use the `remove_temp_state` function to remove state data of a specific type from the temporary area of `UTXO` and obtain its value.

Here are some example codes:

```move
struct TempState has store, copy, drop {
value: u64,
}
// Add temporary state data
add_temp_state(&mut utxo, TempState{value: 10});
// Check if temporary state data exists
if contains_temp_state::<TempState>(&utxo) {
// ...
}
// Borrow an immutable reference to temporary state data
let state_ref = borrow_temp_state::<TempState>(&utxo);
// Borrow a mutable reference to temporary state data and modify it
{
let state_mut = borrow_mut_temp_state::<TempState>(&mut utxo);
state_mut.value = 20;
};
// Remove temporary state data and obtain its value
let removed_state = remove_temp_state::<TempState>(&mut utxo);
```

In the above code, `TempState` is an example state structure, which should be replaced with the specific data type in actual use.

### Examples

Expand All @@ -33,12 +85,75 @@ TODO: This section of the document needs improvement

## Programming with Inscription

<Callout>
TODO: This section of the document needs improvement
1. Explanation of Inscription fields
2. How to accept Inscription as method parameters
3. How to store data in the Inscription's temporary and permanent areas
</Callout>
### 1. Description of Inscription Fields

The Inscription structure is defined in the `ord.move` file and represents an ordered record on the Rooch network.

The Inscription structure includes the following fields:

- `txid`: Transaction ID, of type `address`.
- `index`: Index, of type `u32`.
- `input`: Transaction input index, of type `u32`.
- `offset`: Offset, of type `u64`.
- `body`: Content body, of type `vector<u8>`.
- `content_encoding`: Content encoding, of type `Option<String>`.
- `content_type`: Content type, of type `Option<String>`.
- `metadata`: Metadata, of type `vector<u8>`.
- `metaprotocol`: Meta-protocol, of type `Option<String>`.
- `parent`: Parent object ID, of type `Option<ObjectID>`.
- `pointer`: Pointer, of type `Option<u64>`.

### 2. How to Accept Inscription as Method Parameters

In Rooch, `Inscription` is stored as an `Object<Inscription>` in the global state. Developers can accept the structure as a parameter by using a reference (`&`) or a mutable reference (`&mut`) to read data contained in the Inscription or to save temporary or permanent state in the Inscription object.

For example, you can define a method to accept a mutable reference to an `Inscription` as follows:

```move
public entry fun plant(seed: &mut Object<Inscription>) {
// ...
}
```

### 3. How to Store Data in the Temporary and Permanent Areas of Inscription

Similar to the temporary area of `UTXO`, the `Object<Inscription>` object also has a temporary area that is cleared once the `Object<Inscription>` is transferred. Additionally, `Object<Inscription>` has a permanent area where state can be stored permanently and will be transferred along with the `Object<Inscription>`.

In the `plants.move` example, it demonstrates how to store data in the permanent and temporary areas of Inscription:

- **Permanent Area**: Use the `ord::add_permanent_state` function to store data. This data will remain in the Inscription until explicitly removed. For example, planting information and plant status are stored in the permanent area:

```move
ord::add_permanent_state(seed, plant);
```

- **Temporary Area**: Use the `ord::add_temp_state` function to store data. This data is temporary and can be cleaned up after certain operations. For example, planting actions are stored in the temporary area:

```move
ord::add_temp_state(seed, actions);
```

In addition, there are corresponding functions for reading and removing data from these areas:

- `ord::borrow_mut_permanent_state<T>` is used to obtain a mutable reference to data of a specific type stored in the permanent area.
- `ord::borrow_mut_temp_state<T>` is used to obtain a mutable reference to data of a specific type stored in the temporary area.
- `ord::remove_permanent_state<T>` is used to remove data of a specific type from the permanent area.

Interfaces for adding, modifying, and deleting state in the temporary area:

- Use the `add_temp_state` function to add state data to the temporary area of `Inscription`. The function accepts an `Inscription` object and the state data to be stored.
- Use the `contains_temp_state` function to check if the temporary area of `Inscription` contains state data of a specific type.
- Use the `borrow_temp_state` function to borrow an immutable reference to state data of a specific type in the temporary area.
- Use the `borrow_mut_temp_state` function to borrow a mutable reference to state data of a specific type in the temporary area to modify it.
- Use the `remove_temp_state` function to remove state data of a specific type from the temporary area of `Inscription` and obtain its value.

Interfaces for adding, modifying, and deleting state in the permanent area:

- Use the `add_permanent_state` function to add state data to the permanent area of `Inscription`. The function accepts an `Inscription` object and the state data to be stored.
- Use the `contains_permanent_state` function to check if the permanent area of `Inscription` contains state data of a specific type.
- Use the `borrow_permanent_state` function to borrow an immutable reference to state data of a specific type in the permanent area.
- Use the `borrow_mut_permanent_state` function to borrow a mutable reference to state data of a specific type in the permanent area to modify it.
- Use the `remove_permanent_state` function to remove state data of a specific type from the permanent area of `Inscription` and obtain its value.

### Examples

Expand Down
Loading

0 comments on commit 5dd16c3

Please sign in to comment.