Пример #1
0
// This function is called from a net conn thread
func netBlockReceived(conn *OneConnection, b []byte) {
	bl, e := btc.NewBlock(b)
	if e != nil {
		conn.DoS("BrokenBlock")
		println("NewBlock:", e.Error())
		return
	}

	idx := bl.Hash.BIdx()
	MutexRcv.Lock()
	if rb, got := ReceivedBlocks[idx]; got {
		rb.Cnt++
		MutexRcv.Unlock()
		common.CountSafe("BlockSameRcvd")
		return
	}
	orb := &OneReceivedBlock{Time: time.Now()}
	if bip, ok := conn.GetBlockInProgress[idx]; ok {
		orb.TmDownload = orb.Time.Sub(bip.start)
		conn.Mutex.Lock()
		delete(conn.GetBlockInProgress, idx)
		conn.Mutex.Unlock()
	} else {
		common.CountSafe("UnxpectedBlockRcvd")
	}
	ReceivedBlocks[idx] = orb
	MutexRcv.Unlock()

	NetBlocks <- &BlockRcvd{Conn: conn, Block: bl}
}
Пример #2
0
func (c *one_net_conn) headers(d []byte) {
	var hdr [81]byte
	b := bytes.NewReader(d)
	cnt, er := btc.ReadVLen(b)
	if er != nil {
		return
	}
	if cnt == 0 /*|| LastBlock.node.Height>=10e3*/ {
		SetAllHeadersDone(true)
		return
	}
	for i := uint64(0); i < cnt; i++ {
		if _, er = b.Read(hdr[:]); er != nil {
			return
		}
		if hdr[80] != 0 {
			fmt.Println(LastBlock.node.Height, "Unexpected value of txn_count")
			continue
		}
		bl, er := btc.NewBlock(hdr[:])
		if er == nil {
			er = chkblock(bl)
			if er != nil {
				fmt.Println(er.Error())
				os.Exit(1)
			}
		} else {
			fmt.Println(LastBlock.node.Height, er.Error())
		}
	}
	//fmt.Println("Height:", LastBlock.node.Height)
}
Пример #3
0
func (ch *Chain) ParseTillBlock(end *BlockTreeNode) {
	var b []byte
	var er error
	var trusted bool

	prv := time.Now().UnixNano()
	for !AbortNow && ch.BlockTreeEnd != end {
		cur := time.Now().UnixNano()
		if cur-prv >= 10e9 {
			fmt.Println("ParseTillBlock ...", ch.BlockTreeEnd.Height, "/", end.Height)
			prv = cur
		}

		nxt := ch.BlockTreeEnd.FindPathTo(end)
		if nxt == nil {
			break
		}

		b, trusted, er = ch.Blocks.BlockGet(nxt.BlockHash)
		if er != nil {
			panic("Db.BlockGet(): " + er.Error())
		}

		bl, er := btc.NewBlock(b)
		if er != nil {
			ch.DeleteBranch(nxt)
			break
		}

		er = bl.BuildTxList()
		if er != nil {
			ch.DeleteBranch(nxt)
			break
		}

		bl.Trusted = trusted

		changes, er := ch.ProcessBlockTransactions(bl, nxt.Height, end.Height)
		if er != nil {
			println("ProcessBlockTransactions", nxt.Height, er.Error())
			ch.DeleteBranch(nxt)
			break
		}
		if !trusted {
			ch.Blocks.BlockTrusted(bl.Hash.Hash[:])
		}

		ch.Unspent.CommitBlockTxs(changes, bl.Hash.Hash[:])

		ch.BlockTreeEnd = nxt
	}

	if !AbortNow && ch.BlockTreeEnd != end {
		end, _ = ch.BlockTreeRoot.FindFarthestNode()
		fmt.Println("ParseTillBlock failed - now go to", end.Height)
		ch.MoveToBlock(end)
	}
	ch.Unspent.Sync()
	ch.Save()
}
Пример #4
0
func GetchBlockForBIP152(hash *btc.Uint256) (crec *chain.BlckCachRec) {
	crec, _, _ = common.BlockChain.Blocks.BlockGetExt(hash)

	if crec == nil {
		fmt.Println("BlockGetExt failed for", hash.String())
		return
	}

	if crec.Block == nil {
		crec.Block, _ = btc.NewBlock(crec.Data)
		if crec.Block == nil {
			fmt.Println("SendCmpctBlk: btc.NewBlock() failed for", hash.String())
			return
		}
	}

	if len(crec.Block.Txs) == 0 {
		if crec.Block.BuildTxList() != nil {
			fmt.Println("SendCmpctBlk: bl.BuildTxList() failed for", hash.String())
			return
		}
	}

	if len(crec.BIP152) != 24 {
		crec.BIP152 = make([]byte, 24)
		copy(crec.BIP152[:8], crec.Data[48:56]) // set the nonce to 8 middle-bytes of block's merkle_root
		sha := sha256.New()
		sha.Write(crec.Data[:80])
		sha.Write(crec.BIP152[:8])
		copy(crec.BIP152[8:24], sha.Sum(nil)[0:16])
	}

	return
}
Пример #5
0
func GetAverageFee() float64 {
	Last.Mutex.Lock()
	end := Last.Block
	Last.Mutex.Unlock()

	LockCfg()
	blocks := CFG.AverageFeeBlocks
	UnlockCfg()
	if blocks <= 0 {
		blocks = 1 // at leats one block
	}

	AverageFeeMutex.Lock()
	defer AverageFeeMutex.Unlock()

	if end.Height == averageFeeLastBlock && averageFeeLastCount == blocks {
		return AverageFee_SPB // we've already calculated for this block
	}

	averageFeeLastBlock = end.Height
	averageFeeLastCount = blocks

	AverageFeeBytes = 0
	AverageFeeTotal = 0

	for blocks > 0 {
		bl, _, e := BlockChain.Blocks.BlockGet(end.BlockHash)
		if e != nil {
			return 0
		}
		block, e := btc.NewBlock(bl)
		if e != nil {
			return 0
		}

		cbasetx, cbasetxlen := btc.NewTx(bl[block.TxOffset:])
		for o := range cbasetx.TxOut {
			AverageFeeTotal += cbasetx.TxOut[o].Value
		}
		AverageFeeTotal -= btc.GetBlockReward(end.Height)

		AverageFeeBytes += uint64(len(bl) - block.TxOffset - cbasetxlen) /*do not count block header and conibase tx */

		blocks--
		end = end.Parent
	}
	if AverageFeeBytes == 0 {
		if AverageFeeTotal != 0 {
			panic("Impossible that miner gest a fee with no transactions in the block")
		}
		AverageFee_SPB = 0
	} else {
		AverageFee_SPB = float64(AverageFeeTotal) / float64(AverageFeeBytes)
	}
	return AverageFee_SPB
}
Пример #6
0
func (ch *Chain) UndoLastBlock() {
	fmt.Println("Undo block", ch.BlockTreeEnd.Height, ch.BlockTreeEnd.BlockHash.String(),
		ch.BlockTreeEnd.BlockSize>>10, "KB")

	raw, _, _ := ch.Blocks.BlockGet(ch.BlockTreeEnd.BlockHash)

	bl, _ := btc.NewBlock(raw)
	bl.BuildTxList()

	ch.Unspent.UndoBlockTxs(bl, ch.BlockTreeEnd.Parent.BlockHash.Hash[:])
	ch.BlockTreeEnd = ch.BlockTreeEnd.Parent
}
Пример #7
0
func BlocksMiner(bl []byte) (string, int) {
	for i, m := range MinerIds {
		if MinedBy(bl, m.Tag) {
			return m.Name, i
		}
	}
	bt, _ := btc.NewBlock(bl)
	cbtx, _ := btc.NewTx(bl[bt.TxOffset:])
	adr := btc.NewAddrFromPkScript(cbtx.TxOut[0].Pk_script, Testnet)
	if adr != nil {
		return adr.String(), -1
	}
	return "", -1
}
Пример #8
0
func defrag_db() {
	if (usif.DefragBlocksDB & 1) != 0 {
		qdb.SetDefragPercent(1)
		fmt.Print("Defragmenting UTXO database")
		for {
			if !common.BlockChain.Unspent.Idle() {
				break
			}
			fmt.Print(".")
		}
		fmt.Println("done")
	}

	if (usif.DefragBlocksDB & 2) != 0 {
		fmt.Println("Creating empty database in", common.GocoinHomeDir+"defrag", "...")
		os.RemoveAll(common.GocoinHomeDir + "defrag")
		defragdb := chain.NewBlockDB(common.GocoinHomeDir + "defrag")
		fmt.Println("Defragmenting the database...")
		blk := common.BlockChain.BlockTreeRoot
		for {
			blk = blk.FindPathTo(common.BlockChain.BlockTreeEnd)
			if blk == nil {
				fmt.Println("Database defragmenting finished successfully")
				fmt.Println("To use the new DB, move the two new files to a parent directory and restart the client")
				break
			}
			if (blk.Height & 0xff) == 0 {
				fmt.Printf("%d / %d blocks written (%d%%)\r", blk.Height, common.BlockChain.BlockTreeEnd.Height,
					100*blk.Height/common.BlockChain.BlockTreeEnd.Height)
			}
			bl, trusted, er := common.BlockChain.Blocks.BlockGet(blk.BlockHash)
			if er != nil {
				fmt.Println("FATAL ERROR during BlockGet:", er.Error())
				break
			}
			nbl, er := btc.NewBlock(bl)
			if er != nil {
				fmt.Println("FATAL ERROR during NewBlock:", er.Error())
				break
			}
			nbl.Trusted = trusted
			defragdb.BlockAdd(blk.Height, nbl)
		}
		defragdb.Sync()
		defragdb.Close()
	}
}
Пример #9
0
func (c *OneConnection) ProcessNewHeader(hdr []byte) (int, *OneBlockToGet) {
	var ok bool
	var b2g *OneBlockToGet
	bl, _ := btc.NewBlock(hdr)

	c.Mutex.Lock()
	c.InvStore(MSG_BLOCK, bl.Hash.Hash[:])
	c.Mutex.Unlock()

	if _, ok = ReceivedBlocks[bl.Hash.BIdx()]; ok {
		common.CountSafe("HeaderOld")
		//fmt.Println("", i, bl.Hash.String(), "-already received")
		return PH_STATUS_OLD, nil
	}

	if b2g, ok = BlocksToGet[bl.Hash.BIdx()]; ok {
		common.CountSafe("HeaderFresh")
		//fmt.Println(c.PeerAddr.Ip(), "block", bl.Hash.String(), " not new but get it")
		return PH_STATUS_FRESH, b2g
	}

	common.CountSafe("HeaderNew")
	//fmt.Println("", i, bl.Hash.String(), " - NEW!")

	common.BlockChain.BlockIndexAccess.Lock()
	defer common.BlockChain.BlockIndexAccess.Unlock()

	if er, dos, _ := common.BlockChain.PreCheckBlock(bl); er != nil {
		common.CountSafe("PreCheckBlockFail")
		//println("PreCheckBlock err", dos, er.Error())
		if dos {
			return PH_STATUS_FATAL, nil
		} else {
			return PH_STATUS_ERROR, nil
		}
	}

	node := common.BlockChain.AcceptHeader(bl)
	b2g = &OneBlockToGet{Started: c.LastMsgTime, Block: bl, BlockTreeNode: node, InProgress: 0}
	AddB2G(b2g)
	LastCommitedHeader = node

	return PH_STATUS_NEW, b2g
}
Пример #10
0
func (c *one_net_conn) block(d []byte) {
	BlocksMutex.Lock()
	defer BlocksMutex.Unlock()
	h := btc.NewSha2Hash(d[:80])

	c.Lock()
	c.last_blk_rcvd = time.Now()
	c.Unlock()

	bip := BlocksInProgress[h.Hash]
	if bip == nil || !bip.Conns[c.id] {
		COUNTER("UNEX")
		//fmt.Println(h.String(), "- already received", bip)
		return
	}

	delete(bip.Conns, c.id)
	c.Lock()
	c.inprogress--
	c.Unlock()
	atomic.AddUint64(&DlBytesDownloaded, uint64(len(d)))
	blocksize_update(len(d))

	bl, er := btc.NewBlock(d)
	if er != nil {
		fmt.Println(c.peerip, "-", er.Error())
		c.setbroken(true)
		return
	}

	bl.BuildTxList()
	if !bytes.Equal(btc.GetMerkel(bl.Txs), bl.MerkleRoot()) {
		fmt.Println(c.peerip, " - MerkleRoot mismatch at block", bip.Height)
		c.setbroken(true)
		return
	}

	BlocksCachedSize += uint(len(d))
	BlocksCached[bip.Height] = bl
	delete(BlocksToGet, bip.Height)
	delete(BlocksInProgress, h.Hash)

	//fmt.Println("  got block", height)
}
Пример #11
0
func (ch *Chain) GetRawTx(BlockHeight uint32, txid *btc.Uint256) (data []byte, er error) {
	// Find the block with the indicated Height in the main tree
	ch.BlockIndexAccess.Lock()
	n := ch.BlockTreeEnd
	if n.Height < BlockHeight {
		println(n.Height, BlockHeight)
		ch.BlockIndexAccess.Unlock()
		er = errors.New("GetRawTx: block height too big")
		return
	}
	for n.Height > BlockHeight {
		n = n.Parent
	}
	ch.BlockIndexAccess.Unlock()

	bd, _, e := ch.Blocks.BlockGet(n.BlockHash)
	if e != nil {
		er = errors.New("GetRawTx: block not in the database")
		return
	}

	bl, e := btc.NewBlock(bd)
	if e != nil {
		er = errors.New("GetRawTx: NewBlock failed")
		return
	}

	e = bl.BuildTxList()
	if e != nil {
		er = errors.New("GetRawTx: BuildTxList failed")
		return
	}

	// Find the transaction we need and store it in the file
	for i := range bl.Txs {
		if bl.Txs[i].Hash.Equal(txid) {
			data = bl.Txs[i].Serialize()
			return
		}
	}
	er = errors.New("GetRawTx: BuildTxList failed")
	return
}
Пример #12
0
func GetRawTransaction(BlockHeight uint32, txid *btc.Uint256, txf io.Writer) bool {
	// Find the block with the indicated Height in the main tree
	common.BlockChain.BlockIndexAccess.Lock()
	n := common.Last.Block
	if n.Height < BlockHeight {
		println(n.Height, BlockHeight)
		common.BlockChain.BlockIndexAccess.Unlock()
		panic("This should not happen")
	}
	for n.Height > BlockHeight {
		n = n.Parent
	}
	common.BlockChain.BlockIndexAccess.Unlock()

	bd, _, e := common.BlockChain.Blocks.BlockGet(n.BlockHash)
	if e != nil {
		println("BlockGet", n.BlockHash.String(), BlockHeight, e.Error())
		println("This should not happen - please, report a bug.")
		println("You can probably fix it by launching the client with -rescan")
		os.Exit(1)
	}

	bl, e := btc.NewBlock(bd)
	if e != nil {
		println("NewBlock: ", e.Error())
		os.Exit(1)
	}

	e = bl.BuildTxList()
	if e != nil {
		println("BuildTxList:", e.Error())
		os.Exit(1)
	}

	// Find the transaction we need and store it in the file
	for i := range bl.Txs {
		if bl.Txs[i].Hash.Equal(txid) {
			txf.Write(bl.Txs[i].Serialize())
			return true
		}
	}
	return false
}
Пример #13
0
func dump_block(s string) {
	h := btc.NewUint256FromString(s)
	if h == nil {
		println("Specify block's hash")
		return
	}
	crec, _, er := common.BlockChain.Blocks.BlockGetExt(btc.NewUint256(h.Hash[:]))
	if er != nil {
		println(er.Error())
		return
	}

	ioutil.WriteFile(h.String()+".bin", crec.Data, 0700)
	if crec.Block == nil {
		crec.Block, _ = btc.NewBlock(crec.Data)
	}
	if crec.Block.OldData == nil {
		crec.Block.BuildTxList()
	}
	ioutil.WriteFile(h.String()+".old", crec.Block.OldData, 0700)

	fmt.Println("Block saved")
}
Пример #14
0
func verify_block(blk []byte, sl one_idx_rec, off int) {
	bl, er := btc.NewBlock(blk)
	if er != nil {
		println("verify_block at off", off, er.Error())
		return
	}
	if !bytes.Equal(bl.Hash.Hash[:], sl.Hash()) {
		println("verify_block at off", off, "Header invalid")
		return
	}

	er = bl.BuildTxList()
	if er != nil {
		println("verify_block at off", off, er.Error())
		return
	}

	merk, _ := btc.GetMerkle(bl.Txs)
	if !bytes.Equal(bl.MerkleRoot(), merk) {
		println("verify_block at off", off, "Payload invalid")
		return
	}
}
Пример #15
0
func do_mining(s string) {
	var totbtc, hrs uint64
	if s != "" {
		hrs, _ = strconv.ParseUint(s, 10, 64)
	}
	if hrs == 0 {
		hrs = uint64(common.CFG.MiningStatHours)
	}
	fmt.Println("Looking back", hrs, "hours...")
	lim := uint32(time.Now().Add(-time.Hour * time.Duration(hrs)).Unix())
	common.Last.Mutex.Lock()
	bte := common.Last.Block
	end := bte
	common.Last.Mutex.Unlock()
	cnt, diff := 0, float64(0)
	tot_blocks, tot_blocks_len := 0, 0

	bip100_voting := make(map[string]uint)
	bip100x := regexp.MustCompile("/BV{0,1}[0-9]+[M]{0,1}/")

	for end.Timestamp() >= lim {
		bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash)
		if e != nil {
			println(cnt, e.Error())
			return
		}
		block, e := btc.NewBlock(bl)
		if e != nil {
			println("btc.NewBlock failed", e.Error())
			return
		}

		bt, _ := btc.NewBlock(bl)
		cbasetx, cbtxlen := btc.NewTx(bl[bt.TxOffset:])

		tot_blocks++
		tot_blocks_len += len(bl)
		diff += btc.GetDifficulty(block.Bits())
		common.LockCfg()
		if common.CFG.Beeps.MinerID != "" &&
			bytes.Contains(bl[bt.TxOffset:bt.TxOffset+cbtxlen], []byte(common.CFG.Beeps.MinerID)) {
			block.BuildTxList()
			totbtc += block.Txs[0].TxOut[0].Value
			cnt++
			fmt.Printf("%4d) %6d %s %s  %5.2f => %5.2f BTC total, %d txs, %.1f KB\n",
				cnt, end.Height, end.BlockHash.String(),
				time.Unix(int64(end.Timestamp()), 0).Format("2006-01-02 15:04:05"),
				float64(block.Txs[0].TxOut[0].Value)/1e8, float64(totbtc)/1e8,
				len(block.Txs), float64(len(bl))/1e3)
		}
		common.UnlockCfg()

		res := bip100x.Find(cbasetx.TxIn[0].ScriptSig)
		if res != nil {
			bip100_voting[string(res)]++
			nimer, _ := common.TxMiner(cbasetx)
			fmt.Println("      block", end.Height, "by", nimer, "voting", string(res), " total:", bip100_voting[string(res)])
		}

		end = end.Parent
	}
	if tot_blocks == 0 {
		fmt.Println("There are no blocks from the last", hrs, "hour(s)")
		return
	}
	diff /= float64(tot_blocks)
	common.LockCfg()
	if common.CFG.Beeps.MinerID != "" {
		fmt.Printf("%.8f BTC mined by %s, in %d blocks for the last %d hours\n",
			float64(totbtc)/1e8, common.CFG.Beeps.MinerID, cnt, hrs)
	}
	common.UnlockCfg()
	if cnt > 0 {
		fmt.Printf("Projected weekly income : %.0f BTC,  estimated hashrate : %s\n",
			7*24*float64(totbtc)/float64(hrs)/1e8,
			common.HashrateToString(float64(cnt)/float64(6*hrs)*diff*7158278.826667))
	}
	bph := float64(tot_blocks) / float64(hrs)
	fmt.Printf("Total network hashrate : %s @ average diff %.0f  (%.2f bph)\n",
		common.HashrateToString(bph/6*diff*7158278.826667), diff, bph)
	fmt.Printf("Average block size was %.1f KB,  next difficulty change in %d blocks\n",
		float64(tot_blocks_len/tot_blocks)/1e3, 2016-bte.Height%2016)
}
Пример #16
0
func json_blocks(w http.ResponseWriter, r *http.Request) {
	if !ipchecker(r) {
		return
	}

	type one_block struct {
		Height    uint32
		Timestamp uint32
		Hash      string
		TxCnt     int
		Size      int
		Version   uint32
		Reward    uint64
		Miner     string
		FeeSPB    float64

		Received                          uint32
		TimePre, TimeDl, TimeVer, TimeQue int
		WasteCnt                          uint
		MissedCnt                         int
		FromConID                         uint32
		Sigops                            int

		MinFeeKSPB     uint64
		NonWitnessSize int
	}

	var blks []*one_block

	common.Last.Mutex.Lock()
	end := common.Last.Block
	common.Last.Mutex.Unlock()

	for cnt := uint32(0); end != nil && cnt < atomic.LoadUint32(&common.CFG.WebUI.ShowBlocks); cnt++ {
		bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash)
		if e != nil {
			return
		}
		block, e := btc.NewBlock(bl)
		if e != nil {
			return
		}

		b := new(one_block)
		b.Height = end.Height
		b.Timestamp = block.BlockTime()
		b.Hash = end.BlockHash.String()
		b.TxCnt = block.TxCount
		b.Size = len(bl)
		b.Version = block.Version()

		cbasetx, cbaselen := btc.NewTx(bl[block.TxOffset:])
		for o := range cbasetx.TxOut {
			b.Reward += cbasetx.TxOut[o].Value
		}

		b.Miner, _ = common.TxMiner(cbasetx)
		if len(bl)-block.TxOffset-cbaselen != 0 {
			b.FeeSPB = float64(b.Reward-btc.GetBlockReward(end.Height)) / float64(len(bl)-block.TxOffset-cbaselen)
		}

		common.BlockChain.BlockIndexAccess.Lock()
		node := common.BlockChain.BlockIndex[end.BlockHash.BIdx()]
		common.BlockChain.BlockIndexAccess.Unlock()

		network.MutexRcv.Lock()
		rb := network.ReceivedBlocks[end.BlockHash.BIdx()]
		network.MutexRcv.Unlock()

		b.Received = uint32(rb.TmStart.Unix())
		b.Sigops = int(node.SigopsCost)

		if rb.TmPreproc.IsZero() {
			b.TimePre = -1
		} else {
			b.TimePre = int(rb.TmPreproc.Sub(rb.TmStart) / time.Millisecond)
		}

		if rb.TmDownload.IsZero() {
			b.TimeDl = -1
		} else {
			b.TimeDl = int(rb.TmDownload.Sub(rb.TmStart) / time.Millisecond)
		}

		if rb.TmQueue.IsZero() {
			b.TimeQue = -1
		} else {
			b.TimeQue = int(rb.TmQueue.Sub(rb.TmStart) / time.Millisecond)
		}

		if rb.TmAccepted.IsZero() {
			b.TimeVer = -1
		} else {
			b.TimeVer = int(rb.TmAccepted.Sub(rb.TmStart) / time.Millisecond)
		}

		b.WasteCnt = rb.Cnt
		b.MissedCnt = rb.TxMissing
		b.FromConID = rb.FromConID

		b.MinFeeKSPB = rb.MinFeeKSPB
		b.NonWitnessSize = rb.NonWitnessSize

		blks = append(blks, b)
		end = end.Parent
	}

	bx, er := json.Marshal(blks)
	if er == nil {
		w.Header()["Content-Type"] = []string{"application/json"}
		w.Write(bx)
	} else {
		println(er.Error())
	}

}
Пример #17
0
func (c *OneConnection) ProcessGetData(pl []byte) {
	var notfound []byte

	//println(c.PeerAddr.Ip(), "getdata")
	b := bytes.NewReader(pl)
	cnt, e := btc.ReadVLen(b)
	if e != nil {
		println("ProcessGetData:", e.Error(), c.PeerAddr.Ip())
		return
	}
	for i := 0; i < int(cnt); i++ {
		var typ uint32
		var h [36]byte

		n, _ := b.Read(h[:])
		if n != 36 {
			println("ProcessGetData: pl too short", c.PeerAddr.Ip())
			return
		}

		typ = binary.LittleEndian.Uint32(h[:4])
		c.Mutex.Lock()
		c.InvStore(typ, h[4:36])
		c.Mutex.Unlock()

		common.CountSafe(fmt.Sprintf("GetdataType-%x", typ))
		if typ == MSG_BLOCK || typ == MSG_WITNESS_BLOCK {
			crec, _, er := common.BlockChain.Blocks.BlockGetExt(btc.NewUint256(h[4:]))
			//bl, _, er := common.BlockChain.Blocks.BlockGet(btc.NewUint256(h[4:]))
			if er == nil {
				bl := crec.Data
				if typ == MSG_BLOCK {
					// remove witness data from the block
					if crec.Block == nil {
						crec.Block, _ = btc.NewBlock(bl)
					}
					if crec.Block.OldData == nil {
						crec.Block.BuildTxList()
					}
					//println("block size", len(crec.Data), "->", len(bl))
					bl = crec.Block.OldData
				}
				c.SendRawMsg("block", bl)
			} else {
				notfound = append(notfound, h[:]...)
			}
		} else if typ == MSG_TX || typ == MSG_WITNESS_TX {
			// transaction
			TxMutex.Lock()
			if tx, ok := TransactionsToSend[btc.NewUint256(h[4:]).BIdx()]; ok && tx.Blocked == 0 {
				tx.SentCnt++
				tx.Lastsent = time.Now()
				TxMutex.Unlock()
				if tx.SegWit == nil || typ == MSG_WITNESS_TX {
					c.SendRawMsg("tx", tx.Data)
				} else {
					c.SendRawMsg("tx", tx.Serialize())
				}
			} else {
				TxMutex.Unlock()
				notfound = append(notfound, h[:]...)
			}
		} else if typ == MSG_CMPCT_BLOCK {
			c.SendCmpctBlk(btc.NewUint256(h[4:]))
		} else {
			if common.DebugLevel > 0 {
				println("getdata for type", typ, "not supported yet")
			}
			if typ > 0 && typ <= 3 /*3 is a filtered block(we dont support it)*/ {
				notfound = append(notfound, h[:]...)
			}
		}
	}

	if len(notfound) > 0 {
		buf := new(bytes.Buffer)
		btc.WriteVlen(buf, uint64(len(notfound)/36))
		buf.Write(notfound)
		c.SendRawMsg("notfound", buf.Bytes())
	}
}
Пример #18
0
func p_blocks(w http.ResponseWriter, r *http.Request) {
	if !ipchecker(r) {
		return
	}

	blks := load_template("blocks.html")
	onerow := load_template("blocks_row.html")

	common.Last.Mutex.Lock()
	end := common.Last.Block
	common.Last.Mutex.Unlock()

	for cnt := uint32(0); end != nil && cnt < atomic.LoadUint32(&common.CFG.WebUI.ShowBlocks); cnt++ {
		bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash)
		if e != nil {
			return
		}
		block, e := btc.NewBlock(bl)
		if e != nil {
			return
		}
		cbasetx, _ := btc.NewTx(bl[block.TxOffset:])
		s := onerow

		s = strings.Replace(s, "{BLOCK_NUMBER}", fmt.Sprint(end.Height), 1)
		s = strings.Replace(s, "{BLOCK_TIMESTAMP}",
			time.Unix(int64(block.BlockTime()), 0).Format("Mon 15:04:05"), 1)
		s = strings.Replace(s, "{BLOCK_HASH}", end.BlockHash.String(), 1)
		s = strings.Replace(s, "{BLOCK_TXS}", fmt.Sprint(block.TxCount), 1)
		s = strings.Replace(s, "{BLOCK_SIZE}", fmt.Sprintf("%.1f", float64(len(bl))/1000), 1)
		var rew uint64
		for o := range cbasetx.TxOut {
			rew += cbasetx.TxOut[o].Value
		}
		s = strings.Replace(s, "<!--BLOCK_VERSION-->", fmt.Sprint(block.Version()), 1)
		s = strings.Replace(s, "{BLOCK_REWARD}", fmt.Sprintf("%.2f", float64(rew)/1e8), 1)
		mi, _ := common.TxMiner(cbasetx)
		if len(mi) > 10 {
			mi = mi[:10]
		}
		s = strings.Replace(s, "{BLOCK_MINER}", mi, 1)

		network.MutexRcv.Lock()
		rb := network.ReceivedBlocks[end.BlockHash.BIdx()]
		network.MutexRcv.Unlock()

		if rb.TmDownload != 0 {
			s = strings.Replace(s, "{TIME_TO_DOWNLOAD}", fmt.Sprint(int(rb.TmDownload/time.Millisecond)), 1)
		} else {
			s = strings.Replace(s, "{TIME_TO_DOWNLOAD}", "", 1)
		}
		if rb.TmAccept != 0 {
			s = strings.Replace(s, "{TIME_TO_ACCEPT}", fmt.Sprint(int(rb.TmAccept/time.Millisecond)), 1)
		} else {
			s = strings.Replace(s, "{TIME_TO_ACCEPT}", "", 1)
		}
		if rb.Cnt != 0 {
			s = strings.Replace(s, "{WASTED_BLOCKS}", fmt.Sprint(rb.Cnt), 1)
		} else {
			s = strings.Replace(s, "{WASTED_BLOCKS}", "", 1)
		}
		s = strings.Replace(s, "{TIME_RECEIVED}", rb.Time.Format("15:04:05"), 1)

		blks = templ_add(blks, "<!--BLOCK_ROW-->", s)

		end = end.Parent
	}

	write_html_head(w, r)
	w.Write([]byte(blks))
	write_html_tail(w)
}
Пример #19
0
func (c *one_net_conn) block(d []byte) {
	atomic.AddUint64(&DlBytesDownloaded, uint64(len(d)))

	BlocksMutex.Lock()
	defer BlocksMutex.Unlock()
	h := btc.NewSha2Hash(d[:80])

	c.Lock()
	c.last_blk_rcvd = time.Now()
	c.Unlock()

	bip := BlocksInProgress[h.Hash]
	if bip == nil || !bip.Conns[c.id] {
		COUNTER("BNOT")
		//fmt.Println(h.String(), "- already received", bip)
		return
	}
	//fmt.Println(h.String(), "- new", bip.Height)
	COUNTER("BYES")

	delete(bip.Conns, c.id)
	c.Lock()
	c.inprogress--
	c.Unlock()
	blocksize_update(len(d))

	bl, er := btc.NewBlock(d)
	if er != nil {
		fmt.Println(c.Ip(), "-", er.Error())
		c.setbroken(true)
		return
	}

	bl.BuildTxList()
	if !bytes.Equal(btc.GetMerkel(bl.Txs), bl.MerkleRoot()) {
		fmt.Println(c.Ip(), " - MerkleRoot mismatch at block", bip.Height)
		c.setbroken(true)
		return
	}

	delete(BlocksToGet, bip.Height)
	delete(BlocksInProgress, h.Hash)
	if len(BlocksInProgress) == 0 {
		EmptyInProgressCnt++
	}

	//println("got-", bip.Height, BlocksComplete+1)
	if BlocksComplete+1 == bip.Height {
		BlocksComplete++
		BlockQueue <- bl
		for {
			bl = BlocksCached[BlocksComplete+1]
			if bl == nil {
				break
			}
			BlocksComplete++
			delete(BlocksCached, BlocksComplete)
			BlocksCachedSize -= uint64(len(bl.Raw))
			BlockQueue <- bl
		}
	} else {
		BlocksCached[bip.Height] = bl
		BlocksCachedSize += uint64(len(d))
	}
}
Пример #20
0
func p_miners(w http.ResponseWriter, r *http.Request) {
	if !ipchecker(r) {
		return
	}

	common.ReloadMiners()

	m := make(map[string]omv, 20)
	var om omv
	cnt := 0
	common.Last.Mutex.Lock()
	end := common.Last.Block
	common.Last.Mutex.Unlock()
	var lastts int64
	var diff float64
	var totbts uint64
	var totfees uint64
	current_mid := -1
	now := time.Now().Unix()

	common.LockCfg()
	minerid := common.CFG.Beeps.MinerID
	common.UnlockCfg()

	next_diff_change := 2016 - end.Height%2016

	block_versions := make(map[uint32]uint)

	// bip100
	bip100_voting := make(map[string]uint)
	//var bip100, bip100v uint64
	bip100x := regexp.MustCompile("/BV{0,1}[0-9]+[M]{0,1}/")
	//bip100rx := regexp.MustCompile("/B[0-9]+[M]{0,1}/")

	for ; end != nil; cnt++ {
		if now-int64(end.Timestamp()) > int64(common.CFG.MiningStatHours)*3600 {
			break
		}
		lastts = int64(end.Timestamp())
		bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash)
		if e != nil {
			return
		}

		block, e := btc.NewBlock(bl)
		cbasetx, _ := btc.NewTx(bl[block.TxOffset:])

		block_versions[binary.LittleEndian.Uint32(bl[0:4])]++
		diff += btc.GetDifficulty(end.Bits())
		miner, mid := common.TxMiner(cbasetx)
		if mid == -1 {
			miner = "<i>" + miner + "</i>"
		}
		om = m[miner]
		om.cnt++
		om.bts += uint64(len(bl))
		om.mid = mid

		// Blocks reward
		var rew uint64
		for o := range cbasetx.TxOut {
			rew += cbasetx.TxOut[o].Value
		}
		om.fees += rew - btc.GetBlockReward(end.Height)

		// bip-100
		res := bip100x.Find(cbasetx.TxIn[0].ScriptSig)
		if res != nil {
			bip100_voting[string(res)]++
		}

		m[miner] = om
		if mid != -1 && current_mid == -1 && minerid == string(common.MinerIds[mid].Tag) {
			current_mid = mid
		}
		totbts += uint64(len(bl))
		end = end.Parent
	}

	if cnt == 0 {
		write_html_head(w, r)
		w.Write([]byte(fmt.Sprint("No blocks in last ", common.CFG.MiningStatHours, " hours")))
		write_html_tail(w)
		return
	}

	srt := make(onemiernstat, len(m))
	i := 0
	for k, v := range m {
		srt[i].name = k
		srt[i].omv = v
		i++
	}
	sort.Sort(srt)

	mnrs := load_template("miners.html")
	onerow := load_template("miners_row.html")

	diff /= float64(cnt)
	bph := float64(cnt) / float64(common.CFG.MiningStatHours)
	hrate := bph / 6 * diff * 7158278.826667
	mnrs = strings.Replace(mnrs, "{MINING_HOURS}", fmt.Sprint(common.CFG.MiningStatHours), 1)
	mnrs = strings.Replace(mnrs, "{BLOCKS_COUNT}", fmt.Sprint(cnt), 1)
	mnrs = strings.Replace(mnrs, "{FIRST_BLOCK_TIME}", time.Unix(lastts, 0).Format("2006-01-02 15:04:05"), 1)
	mnrs = strings.Replace(mnrs, "{AVG_BLOCKS_PER_HOUR}", fmt.Sprintf("%.2f", bph), 1)
	mnrs = strings.Replace(mnrs, "{AVG_DIFFICULTY}", common.NumberToString(diff), 1)
	mnrs = strings.Replace(mnrs, "{AVG_HASHDATE}", common.HashrateToString(hrate), 1)
	mnrs = strings.Replace(mnrs, "{AVG_BLOCKSIZE}", fmt.Sprintf("%.1fKB", float64(totbts)/float64(cnt)/1000), 1)
	mnrs = strings.Replace(mnrs, "{DIFF_CHANGE_IN}", fmt.Sprint(next_diff_change), 1)
	mnrs = strings.Replace(mnrs, "{MINER_MON_IDX}", fmt.Sprint(current_mid), 1)

	for i := range srt {
		s := onerow
		s = strings.Replace(s, "{MINER_NAME}", srt[i].name, 1)
		s = strings.Replace(s, "{BLOCK_COUNT}", fmt.Sprint(srt[i].cnt), 1)
		s = strings.Replace(s, "{TOTAL_PERCENT}", fmt.Sprintf("%.0f", 100*float64(srt[i].cnt)/float64(cnt)), 1)
		s = strings.Replace(s, "{MINER_HASHRATE}", common.HashrateToString(hrate*float64(srt[i].cnt)/float64(cnt)), 1)
		s = strings.Replace(s, "{AVG_BLOCK_SIZE}", fmt.Sprintf("%.1fKB", float64(srt[i].bts)/float64(srt[i].cnt)/1000), 1)
		s = strings.Replace(s, "{MINER_ID}", fmt.Sprint(srt[i].mid), -1)
		s = strings.Replace(s, "<!--TOTAL_FEES-->", btc.UintToBtc(srt[i].fees), -1)
		s = strings.Replace(s, "<!--FEE_PER_BYTE-->", fmt.Sprint(srt[i].fees/srt[i].bts), -1)
		mnrs = templ_add(mnrs, "<!--MINER_ROW-->", s)
		totfees += srt[i].fees
	}

	mnrs = strings.Replace(mnrs, "<!--TOTAL_MINING_FEES-->", btc.UintToBtc(totfees), 1)
	mnrs = strings.Replace(mnrs, "<!--AVERAGE_FEE_PER_BYTE-->", fmt.Sprint(totfees/totbts), 1)

	var bv string
	for k, v := range block_versions {
		if bv != "" {
			bv += ",&nbsp;&nbsp;"
		}
		bv += fmt.Sprintf("%d (%d%%) x <b>v%d</b>", v, 100*int(v)/cnt, k)
	}
	mnrs = strings.Replace(mnrs, "<!--BLOCK_VERSIONS-->", bv, 1)

	// bip100
	bv = ""
	for k, v := range bip100_voting {
		if bv != "" {
			bv += " + "
		}
		bv += fmt.Sprintf("%sx%d", k, v)
	}

	mnrs = strings.Replace(mnrs, "<!--BLOCKSIZE_VOTES-->", bv, 1)

	write_html_head(w, r)
	w.Write([]byte(mnrs))
	write_html_tail(w)
}
Пример #21
0
func SubmitBlock(cmd *RpcCommand, resp *RpcResponse, b []byte) {
	var bd []byte
	var er error

	switch uu := cmd.Params.(type) {
	case []interface{}:
		if len(uu) < 1 {
			resp.Error = RpcError{Code: -1, Message: "empty params array"}
			return
		}
		bd, er = hex.DecodeString(uu[0].(string))
		if er != nil {
			resp.Error = RpcError{Code: -3, Message: er.Error()}
			return
		}

	default:
		resp.Error = RpcError{Code: -2, Message: "incorrect params type"}
		return
	}

	bs := new(BlockSubmited)

	bs.Block, er = btc.NewBlock(bd)
	if er != nil {
		resp.Error = RpcError{Code: -4, Message: er.Error()}
		return
	}

	network.MutexRcv.Lock()
	network.ReceivedBlocks[bs.Block.Hash.BIdx()] = &network.OneReceivedBlock{TmStart: time.Now()}
	network.MutexRcv.Unlock()

	println("new block", bs.Block.Hash.String(), "len", len(bd), "- submitting...")
	bs.Done.Add(1)
	RpcBlocks <- bs
	bs.Done.Wait()
	if bs.Error != "" {
		//resp.Error = RpcError{Code: -10, Message: bs.Error}
		idx := strings.Index(bs.Error, "- RPC_Result:")
		if idx == -1 {
			resp.Result = "inconclusive"
		} else {
			resp.Result = bs.Error[idx+13:]
		}
		println("submiting block error:", bs.Error)
		println("submiting block result:", resp.Result.(string))

		print("time_now:", time.Now().Unix())
		print("  cur_block_ts:", bs.Block.BlockTime())
		print("  last_given_now:", last_given_time)
		print("  last_given_min:", last_given_mintime)
		common.Last.Mutex.Lock()
		print("  prev_block_ts:", common.Last.Block.Timestamp())
		common.Last.Mutex.Unlock()
		println()

		return
	}

	// cress check with bitcoind...
	if false {
		bitcoind_result := process_rpc(b)
		json.Unmarshal(bitcoind_result, &resp)
		switch cmd.Params.(type) {
		case string:
			println("\007Block rejected by bitcoind:", resp.Result.(string))
			ioutil.WriteFile(fmt.Sprint(bs.Block.Height, "-", bs.Block.Hash.String()), bd, 0777)
		default:
			println("submiting block verified OK", bs.Error)
		}
	}
}
Пример #22
0
func do_mining(s string) {
	var totbtc, hrs uint64
	if s != "" {
		hrs, _ = strconv.ParseUint(s, 10, 64)
	}
	if hrs == 0 {
		hrs = uint64(common.CFG.MiningStatHours)
	}
	fmt.Println("Looking back", hrs, "hours...")
	lim := uint32(time.Now().Add(-time.Hour * time.Duration(hrs)).Unix())
	common.Last.Mutex.Lock()
	bte := common.Last.Block
	end := bte
	common.Last.Mutex.Unlock()
	cnt, diff := 0, float64(0)
	tot_blocks, tot_blocks_len := 0, 0
	for end.Timestamp() >= lim {
		bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash)
		if e != nil {
			println(cnt, e.Error())
			return
		}
		block, e := btc.NewBlock(bl)
		if e != nil {
			println("btc.NewBlock failed", e.Error())
			return
		}
		tot_blocks++
		tot_blocks_len += len(bl)
		diff += btc.GetDifficulty(block.Bits())
		if common.MinedByUs(bl) {
			block.BuildTxList()
			totbtc += block.Txs[0].TxOut[0].Value
			cnt++
			fmt.Printf("%4d) %6d %s %s  %5.2f => %5.2f BTC total, %d txs, %.1f KB\n",
				cnt, end.Height, end.BlockHash.String(),
				time.Unix(int64(end.Timestamp()), 0).Format("2006-01-02 15:04:05"),
				float64(block.Txs[0].TxOut[0].Value)/1e8, float64(totbtc)/1e8,
				len(block.Txs), float64(len(bl))/1e3)
		}
		end = end.Parent
	}
	if tot_blocks == 0 {
		fmt.Println("There are no blocks from the last", hrs, "hour(s)")
		return
	}
	diff /= float64(tot_blocks)
	common.LockCfg()
	if common.CFG.Beeps.MinerID != "" {
		fmt.Printf("%.8f BTC mined by %s, in %d blocks for the last %d hours\n",
			float64(totbtc)/1e8, common.CFG.Beeps.MinerID, cnt, hrs)
	}
	common.UnlockCfg()
	if cnt > 0 {
		fmt.Printf("Projected weekly income : %.0f BTC,  estimated hashrate : %s\n",
			7*24*float64(totbtc)/float64(hrs)/1e8,
			common.HashrateToString(float64(cnt)/float64(6*hrs)*diff*7158278.826667))
	}
	bph := float64(tot_blocks) / float64(hrs)
	fmt.Printf("Total network hashrate : %s @ average diff %.0f  (%.2f bph)\n",
		common.HashrateToString(bph/6*diff*7158278.826667), diff, bph)
	fmt.Printf("Average block size was %.1f KB,  next difficulty change in %d blocks\n",
		float64(tot_blocks_len/tot_blocks)/1e3, 2016-bte.Height%2016)
}
Пример #23
0
func import_blockchain(dir string) {
	BlockDatabase := blockdb.NewBlockDB(dir, Magic)
	chain := chain.NewChain(GocoinHomeDir, GenesisBlock, false)

	var bl *btc.Block
	var er error
	var dat []byte
	var totbytes, perbytes uint64

	chain.DoNotSync = true

	fmt.Println("Be patient while importing Satoshi's database... ")
	start := time.Now().UnixNano()
	prv := start
	for {
		now := time.Now().UnixNano()
		if now-prv >= 10e9 {
			stat(now-start, now-prv, totbytes, perbytes, chain.BlockTreeEnd.Height)
			prv = now // show progress each 10 seconds
			perbytes = 0
		}

		dat, er = BlockDatabase.FetchNextBlock()
		if dat == nil || er != nil {
			println("END of DB file")
			break
		}

		bl, er = btc.NewBlock(dat[:])
		if er != nil {
			println("Block inconsistent:", er.Error())
			break
		}

		bl.Trusted = Trust

		er, _, _ = chain.CheckBlock(bl)

		if er != nil {
			if er.Error() != "Genesis" {
				println("CheckBlock failed:", er.Error())
				os.Exit(1) // Such a thing should not happen, so let's better abort here.
			}
			continue
		}

		er = chain.AcceptBlock(bl)
		if er != nil {
			println("AcceptBlock failed:", er.Error())
			os.Exit(1) // Such a thing should not happen, so let's better abort here.
		}

		totbytes += uint64(len(bl.Raw))
		perbytes += uint64(len(bl.Raw))
	}

	stop := time.Now().UnixNano()
	stat(stop-start, stop-prv, totbytes, perbytes, chain.BlockTreeEnd.Height)

	fmt.Println("Satoshi's database import finished in", (stop-start)/1e9, "seconds")

	fmt.Println("Now saving the new database...")
	chain.Save()
	chain.Close()
	fmt.Println("Database saved. No more imports should be needed.")
}
Пример #24
0
func json_blocks(w http.ResponseWriter, r *http.Request) {
	if !ipchecker(r) {
		return
	}

	type one_block struct {
		Height    uint32
		Timestamp uint32
		Hash      string
		TxCnt     int
		Size      int
		Version   uint32
		Reward    uint64
		Miner     string

		Received        uint32
		TimeDl, TimeVer int
		WasteCnt        uint
	}

	var blks []*one_block

	common.Last.Mutex.Lock()
	end := common.Last.Block
	common.Last.Mutex.Unlock()

	for cnt := uint32(0); end != nil && cnt < atomic.LoadUint32(&common.CFG.WebUI.ShowBlocks); cnt++ {
		bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash)
		if e != nil {
			return
		}
		block, e := btc.NewBlock(bl)
		if e != nil {
			return
		}

		b := new(one_block)
		b.Height = end.Height
		b.Timestamp = block.BlockTime()
		b.Hash = end.BlockHash.String()
		b.TxCnt = block.TxCount
		b.Size = len(bl)
		b.Version = block.Version()

		cbasetx, _ := btc.NewTx(bl[block.TxOffset:])
		for o := range cbasetx.TxOut {
			b.Reward += cbasetx.TxOut[o].Value
		}

		b.Miner, _ = common.TxMiner(cbasetx)

		network.MutexRcv.Lock()
		rb := network.ReceivedBlocks[end.BlockHash.BIdx()]
		network.MutexRcv.Unlock()

		b.Received = uint32(rb.Time.Unix())

		if rb.TmDownload != 0 {
			b.TimeDl = int(rb.TmDownload / time.Millisecond)
		} else {
			b.TimeDl = -1
		}

		if rb.TmAccept != 0 {
			b.TimeVer = int(rb.TmAccept / time.Millisecond)
		} else {
			b.TimeVer = -1
		}

		b.WasteCnt = rb.Cnt

		blks = append(blks, b)
		end = end.Parent
	}

	bx, er := json.Marshal(blks)
	if er == nil {
		w.Header()["Content-Type"] = []string{"application/json"}
		w.Write(bx)
	} else {
		println(er.Error())
	}

}