example_test.go raw

   1  package blockchain_test
   2  
   3  import (
   4  	"fmt"
   5  	bits2 "github.com/p9c/p9/pkg/bits"
   6  	"github.com/p9c/p9/pkg/block"
   7  	"log"
   8  	"math/big"
   9  	"os"
  10  	"path/filepath"
  11  	
  12  	"github.com/p9c/p9/pkg/blockchain"
  13  	"github.com/p9c/p9/pkg/chaincfg"
  14  	"github.com/p9c/p9/pkg/database"
  15  	_ "github.com/p9c/p9/pkg/database/ffldb"
  16  )
  17  
  18  // This example demonstrates how to create a new chain instance and use ProcessBlock to attempt to add a block to the
  19  // chain. As the package overview documentation describes, this includes all of the Bitcoin consensus rules. This
  20  // example intentionally attempts to insert a duplicate genesis block to illustrate how an invalid block is handled.
  21  func ExampleBlockChain_ProcessBlock() {
  22  	// Create a new database to store the accepted blocks into. Typically this would be opening an existing database and
  23  	// would not be deleting and creating a new database like this, but it is done here so this is a complete working
  24  	// example and does not leave temporary files laying around.
  25  	dbPath := filepath.Join(os.TempDir(), "exampleprocessblock")
  26  	_ = os.RemoveAll(dbPath)
  27  	db, e := database.Create("ffldb", dbPath, chaincfg.MainNetParams.Net)
  28  	if e != nil {
  29  		log.Printf("Failed to create database: %v\n", e)
  30  		return
  31  	}
  32  	defer func() {
  33  		if e = os.RemoveAll(dbPath); E.Chk(e) {
  34  		}
  35  	}()
  36  	defer func() {
  37  		if e = db.Close(); E.Chk(e) {
  38  		}
  39  	}()
  40  	// Create a new BlockChain instance using the underlying database for the main bitcoin network. This example does
  41  	// not demonstrate some of the other available configuration options such as specifying a notification callback and
  42  	// signature cache. Also, the caller would ordinarily keep a reference to the median time source and add time values
  43  	// obtained from other peers on the network so the local time is adjusted to be in agreement with other peers.
  44  	chain, e := blockchain.New(
  45  		&blockchain.Config{
  46  			DB:          db,
  47  			ChainParams: &chaincfg.MainNetParams,
  48  			TimeSource:  blockchain.NewMedianTime(),
  49  		},
  50  	)
  51  	if e != nil {
  52  		log.Printf("Failed to create chain instance: %v\n", e)
  53  		return
  54  	}
  55  	// Process a block. For this example, we are going to intentionally cause an error by trying to process the genesis
  56  	// block which already exists.
  57  	genesisBlock := block.NewBlock(chaincfg.MainNetParams.GenesisBlock)
  58  	var isMainChain bool
  59  	var isOrphan bool
  60  	isMainChain, isOrphan, e = chain.ProcessBlock(
  61  		0, genesisBlock,
  62  		blockchain.BFNone, 0,
  63  	)
  64  	if e != nil {
  65  		log.Printf("Failed to process block: %v\n", e)
  66  		return
  67  	}
  68  	log.Printf("Block accepted. Is it on the main chain?: %v", isMainChain)
  69  	log.Printf("Block accepted. Is it an orphan?: %v", isOrphan)
  70  	// Output:
  71  	// Failed to process block: already have block 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
  72  }
  73  
  74  // This example demonstrates how to convert the compact "bits" in a block header which represent the target difficulty
  75  // to a big integer and display it using the typical hex notation.
  76  func ExampleCompactToBig() {
  77  	// Convert the bits from block 300000 in the main block chain.
  78  	bits := uint32(419465580)
  79  	targetDifficulty := bits2.CompactToBig(bits)
  80  	// Display it in hex.
  81  	fmt.Printf("%064x\n", targetDifficulty.Bytes())
  82  	// Output:
  83  	// 0000000000000000896c00000000000000000000000000000000000000000000
  84  }
  85  
  86  // This example demonstrates how to convert a target difficulty into the compact "bits" in a block header which
  87  // represent that target difficulty .
  88  func ExampleBigToCompact() {
  89  	// Convert the target difficulty from block 300000 in the main block
  90  	// chain to compact form.
  91  	t := "0000000000000000896c00000000000000000000000000000000000000000000"
  92  	targetDifficulty, success := new(big.Int).SetString(t, 16)
  93  	if !success {
  94  		fmt.Println("invalid target difficulty")
  95  		return
  96  	}
  97  	bits := bits2.BigToCompact(targetDifficulty)
  98  	fmt.Println(bits)
  99  	// Output:
 100  	// 419465580
 101  }
 102