🆔
MetaID
English
English
  • ℹ️Overview
    • Overview
    • Terms
  • 📑MetaID Specification
    • Protocol Spec
    • MetaID Tree
      • MetaID Tree
      • Info Node
      • File Node
      • FT Node
      • NFT Node
      • Protocols Node
      • Follow Node
    • MetaID Envelope
    • Privacy Model
    • About PIN
    • About PoP
    • Host
    • MetaAccess
    • MetaName
    • Examples
  • 💻MetaID App Node
    • Introduction
    • Compile and Run
    • JSON API
    • Browser
    • MetaID PIN Conventions
    • PIN Data Structure
  • ⚙️MetaID SDK
    • Get Started
    • Core API
    • Quick Example
  • ⛓️Cross-chain
    • Cross-chain
    • Unified UTXO Chain
  • 🪪About MetaID
    • History About MetaID
    • FAQ
    • MetaID Philosophy
    • MetaID Resources
  • 📃FT & NFT Protocols
    • MRC-20
    • MRC-721
Powered by GitBook
On this page
  • Overview
  • Calculation Method
  • PoP Level (Difficulty Classification)
  • PoP Score (PoP分数)
  1. MetaID Specification

About PoP

Overview

Proof of PIN (PoP) is an interesting concept in MetaID. We have developed the PoP mechanism with reference to the mining principle of Bitcoin. The PoP value reflects the user's "proof of work" in the MetaID world. In the MetaID world, the minimum "work" of a user is to send a PIN, so each PIN has a hash value that combines the user's PIN with the difficulty of the block it is in. The PoP value reflects the following two dimensions:

  1. Overview of the amount of MetaID data created by the user: The more MetaID PINs created, the higher the probability of obtaining a high-difficulty PoP value.

  2. Hashrate consumption of the user's MetaID data creation: The PoP value is linked to the hashrate of the blockchain where the MetaID data is located. The higher the hashrate, the easier it is to obtain a high-difficulty PoP value.

PIN is similar to SHA256 hashrate, while PoP is similar to difficulty hash. The higher the hashrate, the greater the probability of obtaining a high-difficulty hash value.

By verifying the user's related PoP value, we can quickly evaluate a user's contribution in the MetaID world and give the concept of level and rarity to PINs.

Calculation Method

PoP is calculated by performing a SHA256 joint hash on the MerkleRoot and PINID, and then multiplying it by the BlockHash to generate a new value. The specific formula is:

PoP = hash(PIN_ID + Merkle_Root) * Block_Hash

The resulting original hash value is then converted to octal, and the converted result is the PoP.

Here is the code:

package pop

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"math/big"
	"strconv"
)

func CalculateHash(pinid string, merkleRoot string) string {
	h := sha256.New()
	h.Write([]byte(pinid + merkleRoot))
	return hex.EncodeToString(h.Sum(nil))
}

func CalculateProductToHexStr(blockhash string, pinHash string) string {
	blockhashByte, _ := hex.DecodeString(blockhash)
	blockhashInt, _ := new(big.Int).SetString(blockhash, 16)
	pinHashByte, _ := hex.DecodeString(pinHash)
	pinHashInt, _ := new(big.Int).SetString(pinHash, 16)
	popByte := new(big.Int).Mul(blockhashInt, pinHashInt).Bytes()
	// Calculate total length: 32+32=64
	totalLen := len(blockhashByte) + len(pinHashByte)
	// Number of leading zeros needed
	remainingLen := totalLen - len(popByte)
	for i := 0; i < remainingLen; i++ {
		popByte = append([]byte{0}, popByte...)
	}
	return hex.EncodeToString(popByte)
}

func ConvertToOctalHex(productHex string) (string, int64) {
	productByte, _ := hex.DecodeString(productHex)
	
	// Convert to binary
	bList := make([]string, 0)
	for _, b := range productByte {
		binaryB := fmt.Sprintf("%b", b)
		bList = append(bList, fmt.Sprintf("%08s", binaryB))
	}
	productBinaryStr := ""
	for _, b := range bList {
		productBinaryStr += b
	}
	productBinaryStr = productBinaryStr[:510]

	bCount := int64(0)
	for _, b := range productBinaryStr {
		if b == '0' {
			bCount++
		} else {
			break
		}
	}

	// Convert binary string to octal string
	octal := ""
	for i := 0; i < len(productBinaryStr); i += 3 {
		binaryStr := productBinaryStr[i : i+3]
		num, err := strconv.ParseInt(binaryStr, 2, 64)
		if err != nil {
			fmt.Println("ParseInt error:", err)
			return "", 0
		}
		octal += strconv.FormatInt(num, 8)
	}
	return octal, bCount
}

func GenPop(pinid, merkleRoot, blockHash string) (string, int64) {
	// Calculate pinHash
	pinHash := CalculateHash(pinid, merkleRoot)
	// Multiply blockhash by pinHash
	productHexStr := CalculateProductToHexStr(blockHash, pinHash)
	// Convert to octal
	octal, bCount := ConvertToOctalHex(productHexStr)
	
	return octal, bCount
}

PoP calculation test case:

func Test_pop(t *testing.T) {
	pinid := "77aac2ae323748dee3b8b1ae6b7c33c1c4466f568c572ea488f584f041f0de4ei0"    // 64 char hash
	merkleRoot := "e56011a241cb196fc4efbeafef051ca901761ffb569a43146582f9133bfd41d2" // 64 char hash
	blockhash := "000000000000000004c2db0441a47fd3574992d508b8d9d866a789d371aa5060"  // real block hash
	pop, bCountZero := GenPop(mockPinId, merkleRoot, blockHash)

	fmt.Println("POP:", pop)
	fmt.Println("POP-0:", bCountZero)
}

PoP Level (Difficulty Classification)

In the MetaID system, the difficulty level of a PoP value is defined similarly to the prefix-zero count in block hash calculations. Specifically, the greater the number of leading "0"s in the prefix of a PoP value, the higher its corresponding difficulty level (PoP Level). The system mandates that any valid PoP value must contain at least 21 leading "0"s as a baseline standard.

To efficiently evaluate and quantify the rarity and difficulty of a PoP, MetaID introduces the concept of the PoP Level. PoP Level is an integer metric, currently ranging from Level 1 to Level 13, and is primarily used for quick rarity assessment of PINs, asset minting in MRC20 scenarios, and similar applications. The initial threshold for PoP Level varies across different mainchain environments; for instance, MVC commonly adopts Level 1 as the entry standard, whereas BTC typically begins at Level 6.

The specific difficulty demarcation is as follows: for PoP Level 1, a PoP value must have 22 leading "0"s; for PoP Level 2, 23 leading "0"s are required; and for each subsequent level, the number of mandatory leading "0"s increases by one. The greater the number of prefix "0"s, the rarer the PoP value and the higher the algorithmic challenge involved in its generation.

Moreover, the difficulty between adjacent PoP Levels follows an exponential progression; each incremental level results in an eightfold (8x) increase in mining difficulty compared to the previous level. This mechanism significantly enhances both the security and scarcity of higher-level PoP values.

PoP Score (PoP分数)

Definition and Application Scenarios of PoP Score

PoP Score is a numerical metric designed for a more granular assessment of PIN rarity compared to PoP Level. It is particularly useful in scenarios requiring fine-grained differentiation of PoP difficulty, such as PEV values in the MetaSo system or MDV values, enabling precise scoring and ranking of each PIN. Every PIN is assigned a unique PoP Score, which is recorded within the MetaID system.

Calculation Methodology of PoP Score

a. Determining the Integer Part (PoP Level)

Take the PoP value associated with a certain PIN as an example:

0000000000000000000000215206653161113226643512614250403542335511435340330664252463510373257440244542222437344512355773452022004517474440724217350505346711227665150775715

First, count the number of consecutive leading "0"s in the prefix. Suppose there are 22 "0"s, then the corresponding PoP Level is 1, which becomes the integer part.

b. Calculating the PoP Sub Octal

Remove all the leading "0"s from the prefix, then take the first four non-zero digits as the fractional part after the decimal point. For example, in the sequence above, these four digits are "2152". Record this as the PoP Sub Octal, so PoPSubOctal = 0.2152.

Note: The PoP Sub Octal is a special octal (base-8) fraction.

c. Octal Fraction Normalization

To ensure even value distribution, the octal fraction PoPSubOctal is converted to a uniformly distributed decimal in the range [0,1]. This uses the "Octal Fraction To Uniform Decimal" conversion method.

d. Calculating the PoP Sub Decimal

The final normalized decimal is denoted as PoP Sub Decimal, with the following correction applied:

PoP Sub Decimal = 1 - octalFractionToUniformDecimal(PoPSubOctal)

This ensures that the closer the decimal value is to 0, the higher the resulting PoP Level Decimal, aligning with the intended difficulty design.

e. Calculating the PoP Level Decimal

Add the integer level and the sub-decimal component:

PoP Level Decimal = PoP Level + PoP Sub Decimal

For this example, PoP Level Decimal is approximately 1.72.

f. Calculating PoP Score

Take the base 8 to the power of PoP Level Decimal to determine the final PoP Score:

PoP Score = 8 ^ PoP Level Decimal

For example, 8 to the power of 1.72 yields approximately 35.7531 (rounded to four decimal places).

Calculation Summary

For the given example:

0000000000000000000000215206653161113226643512614250403542335511435340330664252463510373257440244542222437344512355773452022004517474440724217350505346711227665150775715
  • PoP Level: Lv.1

  • PoP Score: 35.7531

PreviousAbout PINNextHost

Last updated 16 days ago

📑