Skip to main content

3 posts tagged with "NoteProtocol"

View All Tags

Turing completeness & Halting Problem

· 3 min read

If we say the native Bitcoin scripting language is Turing complete, many people will criticize us.

Turing Completeness refers to a programming language that can implement any computation a Turing machine is capable of. This concept comes from Alan Turing, who proposed the Turing Machine model. It’s an abstract machine that performs calculations by reading and writing symbols on an infinitely long tape.

If a programming language is Turing complete, it means it can simulate all computational functions of a Turing machine. Typically, this requires the language to support conditional branching (like if/else statements) and loops (or recursion) to make decisions based on data and repeatedly perform certain actions until a specific condition is met.

Is it reasonable that a program in an infinite loop could run indefinitely on an infinitely long tape? Is it reasonable to say that a program that can implement an infinite loop is Turing complete?

In fact, simple infinite loops can be implemented with a very basic set of instructions, but if there's insufficient control structure (like conditional branches) and data handling capabilities, such systems cannot be considered Turing complete. Turing completeness requires the ability to express any complex algorithmic logic, including but not limited to loop structures. Furthermore, infinite loops introduce another issue: the Halting Problem.

The Halting Problem, proposed by Alan Turing in the 1930s, is a well-known problem in computation theory. It explores whether there exists an algorithm that can determine whether any given program and its input will eventually stop executing.

Turing proved the Halting Problem is unsolvable. Turing-complete systems can express and execute all possible programs, including those that never halt. The unsolvability of the Halting Problem arises directly from the capabilities of these systems. In short, the robust computational power of Turing-complete systems introduces uncertainty because we cannot predict in advance whether a program will stop in all cases.

Now let’s see why some claim Bitcoin's script is not Turing complete. Because it lacks loop commands in its opcode, some argue it's not Turing complete. However, assembly language also lacks loop commands, yet no one disputes its Turing completeness. Assembly language provides the necessary tools to implement loops primarily through conditional jump instructions. Bitcoin script is similar to assembly in that loops can be unrolled. For example, to sum from 1 to 100, you could keep adding: 1+2=3, 3+3=6, 6+4=10, and so on until 100. This approach has a benefit—it addresses the Halting Problem. We know that Bitcoin transactions and blocks are limited in size, from 1MB to 4MB, potentially larger. Therefore, an unrolled script will eventually hit this size limit and force the program to stop.

Image1

One might say: Bitcoin script language is Turing complete and also solves the Halting Problem.

In Ethereum, the Halting Problem is addressed by charging a fee (gas) for each operation. Theoretically, a wealthy Ethereum user could pay to run a program for a year, potentially clogging the EVM.

However, on Bitcoin , no amount of money can infinitely increase block size, ensuring programs must stop. This is part of the consensus.

In the computing field, there’s an important principle: the KISS principle (Keep It Simple, Stupid). Satoshi Nakamoto adhered to this principle.

Maintaining simplicity in a system is a crucial consideration for designers. In environments like Note Protocol, script size is still controlled, currently providing about 2.5K of script JSON storage space. In the future, it could expand to between 1MB and 4MB.

Continuous Upgrades to the NOTE Protocol

· 6 min read

Since the public release of its Proof of Concept indexer in February 2024, the NOTE protocol has garnered widespread attention. Following feedback and demands from users, the protocol has been continuously upgraded.

As of April 4th, the following upgrades have been implemented:

  • The Payload data area has been fully expanded, meaning that Payload data can now be stored either in the unlocking script or in the redemption script.
  • Added a Burn method to N20. Tokens can now be burned.
  • The off-chain contract execution environment has been enriched with a plethora of environmental variables, including block information such as block time, block hash, block height, as well as transaction information like transaction hash, all inputs and outputs. Ticker information, such as the total mint amount, etc., has also been included.

The indexer code has undergone extensive refactoring.

One of the goals of this upgrade is to enable anyone to participate in the development of NOTE smart contracts. This allows for the creation of unique smart contracts that can be published to the NOTE indexer, facilitating the issuance of digital assets. A comprehensive tutorial on contract creation is currently being developed.

The capabilities of the NOTE protocol can be seen in the POW mining contract released in February.

We've added some comments to help everyone understand:

// Each contract is a subclass of SmartContract, and its member variables are read-only and need to be decorated with @prop().
export class N20_Pow extends SmartContract {
@prop()
readonly tick: ByteString

@prop()
readonly max: bigint

@prop()
readonly lim: bigint

@prop()
readonly dec: bigint

@prop()
readonly bitwork: ByteString

@prop()
readonly start: bigint

// If the contract includes member variables, they need to be initialized using a constructor.
constructor(tick: ByteString, max: bigint, lim: bigint, dec: bigint, bitwork: ByteString, start: bigint) {
super(...arguments)
// The identifier of the digital asset, its name.
this.tick = tick
// The maximum issuance of the digital asset, if there is no limit, it can be specified as 0.
this.max = max
// The mining limit per transaction, it cannot exceed the maximum value.
this.lim = lim
// The decimal unit of the digital asset, for example, if dec=8, then 1 token should be followed by 8 zeros, all quantity values amt, including max and lim, are affected by this. 100000000 represents 1.00000000.
this.dec = dec
// Mining difficulty, the required leading characters of each transaction's hash256.
this.bitwork = bitwork
// The starting height of the mining contract, used to prevent pre-mining.
this.start = start
}

// The block limit algorithm for mining, needs to be decorated with @method().
@method()
getBlockLimit(height: bigint): bigint {
assert(height >= this.start, 'Block height is too low')
// Halving occurs every 1000 blocks, the number of halvings is determined by the block height minus the starting height.
let halvings = (height - this.start) / 1000n
// A maximum of 7 halvings.
halvings = halvings > 7n ? 7n : halvings
// The mining quantity limit is halved with each halving. Here, the binary rshift operator is used to perform the division by 2 operation.
const subsidy = rshift(this.lim, halvings)
return subsidy
}

// The quantity limit algorithm for mining, needs to be decorated with @method().
@method()
getAmountLimit(currentMined: bigint): bigint {
// The quantity limit starts from how much of the total amount has already been mined.
let miningAmount = this.lim
let threshold = this.max / 2n

// Loop 7 times, each loop, if the current mined amount reaches the threshold, then the mining amount is halved, and the threshold is updated.
for (let halving = 0n; halving < 7n; halving++) {
if (currentMined >= threshold) {
miningAmount /= 2n // Halve the mining amount
threshold += rshift(this.max, halving + 2n) // Update the next threshold
}
}

return miningAmount
}

@method()
public mint(tick: ByteString, amt: bigint, total: bigint, height: bigint, tx: ByteString) {
// Check if the transaction's hash256 leading characters match the mining contract's difficulty requirement.
const txid = hash256(tx)
assert(slice(txid, 0n, len(this.bitwork)) == this.bitwork, 'not match target')
// Check if the total mining amount exceeds the maximum issuance.
assert(this.max == 0n || total <= this.max, 'Over max')
assert(tick == this.tick, 'Tick does not match')
// Check if the mining amount exceeds the block limit and the total halving limit.
const limit1 = this.getBlockLimit(height)
const limit2 = this.getAmountLimit(total)
const limit = limit1 > limit2 ? limit2 : limit1
assert(amt <= limit && amt <= this.max - total, 'Amount check failed')
}

// The method for transferring Tokens, needs to be decorated with @method().
@method()
public transfer(tick: ByteString) {
assert(tick == this.tick, 'Tick does not match')
}
}

there is a bug in the above code about max=0. if you want to use it in your assets, please DONT set max=0.

This upgrade added the Burn method, allowing for the burning of Tokens. A new example is as follows.

// This example does not use a constructor but instead uses a static setting of parameters, because the values are entirely within the contract and cannot be reused for other digital assets.
export class N20_Joss extends SmartContract {
// Joss paper: A type of paper made to resemble money and burned in front of deities.
@prop()
static tick: ByteString = toByteString('JOSS', true)

// No issuance limit.
@prop()
static max: bigint = 0n

// Can issue 10,000 at a time.
@prop()
static lim: bigint = 10000n

// No decimal places.
@prop()
static dec: bigint = 0n

@method()
public mint(tick: ByteString, amt: bigint) {
assert(tick == N20_Joss.tick, 'Tick does not match')
// The issuance amount cannot exceed the limit of 10,000.
assert(amt == N20_Joss.lim, 'Limit does not match')
}

@method()
public transfer() {
// Cannot transfer.
assert(false)
}

@method()
public burn(tick: ByteString) {
// Can be burned.
assert(tick == N20_Joss.tick, 'Tick does not match')
}
}

The N20_Joss contract was released at https://mempool.space/tx/c2cda4c9da3a91bd245d9f6250b5ca8f2ec81d50c14821e87a033fde1f3b5561

Support for smart contracts is the biggest difference between the NOTE protocol and other protocols. The NOTE wallet and indexer create an execution environment for smart contracts, allowing users to write their own smart contracts. For basic knowledge about smart contracts, you can refer to:

Why Bitcoin smart contracts are Turing complete:

A tutorial on smart contract development for the NOTE protocol is being created, so stay tuned.

NoteProtocol v2.0 Draft is out

· One min read

🚀 Exciting update from our team: We’ve crafted a #Bitcoin protocol, tailored for #UTXO-based blockchains. This protocol not only allows for the creation of tokens and NFTs but also integrates optional data #encryption, #SmartContracts, and #DID definitions, all under the MIT License.

🔬 The first segment has been successfully tested on #BTC, #RXD, and #BSV networks. The #NFT/#Token/Indexer features are nearing completion, with a January release following thorough validation to ensure a high-security standard.

🌍 As we move forward, we’re inviting the community to contribute to this evolving project. Our goal is to establish a protocol committee of contributors, dedicated to promoting and enhancing the protocol, ensuring it serves the global Bitcoin community effectively.

🔧 Your input is vital in this journey of innovation and collaboration. We’re here to support projects leveraging this protocol, fostering a secure and dynamic blockchain ecosystem.

🔔 Stay connected for detailed updates and be part of shaping the future of blockchain technology. #BlockchainEngineering #BitcoinProtocol #DecentralizedInnovation #OpenSourceFuture

Happy New Year everyone!