<commit_before>// Copyright (c) 2014-2015 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package payment

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/hex"
	"encoding/json"
	"github.com/bitmark-inc/bitmarkd/background"
	"github.com/bitmark-inc/bitmarkd/configuration"
	"github.com/bitmark-inc/bitmarkd/fault"
	"github.com/bitmark-inc/bitmarkd/transaction"
	"github.com/bitmark-inc/logger"
	"io/ioutil"
	"net/http"
	"strings"
	"sync"
	"time"
)

// global constants
const (
	bitcoinMinimumVersion = 90200           // do not start if bitcoind older than this
	bitcoinRateLimit      = 15.0            // blocks/second
	bitcoinPollingTime    = 2 * time.Minute // sample bitcoin "blockcount" RPC at this interval
	bitcoinMaximumRetries = 10              // panic after this many consecutive errors
	bitcoinCurrencyName   = "bitcoin"       // all lowercase currency string
	bitcoinBlockRange     = 200             // number of blocks to consider as relevant
	bitcoinConfirmations  = 3               // stop processing this many blocks back from most recent block

	// this is how far back in the bitcoin block chain to start when process begins
	bitcoinBlockOffset = bitcoinBlockRange + bitcoinConfirmations
)

// globals for background proccess
type bitcoinData struct {
	sync.RWMutex // to allow locking

	// logger
	log *logger.L

	// connection to bitcoin daemon
	client *http.Client
	url    string

	// authentication
	username string
	password string

	// identifier for the RPC
	id uint64

	// payment info
	minerAddress      string
	fee               uint64 // value in Satoshis avoid float because of rounding errors
	latestBlockNumber uint64

	// for garbage collection
	expire map[uint64][]transaction.Link

	// for background
	background *background.T

	// set once during initialise
	initialised bool
}

// global data
var globalBitcoinData bitcoinData

// list of background processes to start
var bitcoinProcesses = background.Processes{
	bitcoinBackground,
}

// external API
// ------------

// initialise for bitcoin payments
// also calls the internal initialisePayment() and register()
//
// Note fee is a string value and is converted to Satoshis to avoid rounding errors
func BitcoinInitialise(configuration configuration.BitcoinAccess) error {

	// ensure payments are initialised
	if err := paymentInitialise(); nil != err {
		return err
	}

	globalBitcoinData.Lock()
	defer globalBitcoinData.Unlock()

	// no need to start if already started
	if globalBitcoinData.initialised {
		return fault.ErrAlreadyInitialised
	}

	if "" == configuration.Address {
		return fault.ErrPaymentAddressMissing
	}

	globalBitcoinData.log = logger.New(bitcoinCurrencyName)
	if nil == globalBitcoinData.log {
		return fault.ErrInvalidLoggerChannel
	}
	globalBitcoinData.log.Info("starting…")

	globalBitcoinData.id = 0
	globalBitcoinData.username = configuration.Username
	globalBitcoinData.password = <PASSWORD>.Password
	globalBitcoinData.url = configuration.URL
	globalBitcoinData.minerAddress = configuration.Address
	globalBitcoinData.fee = convertToSatoshi([]byte(configuration.Fee))
	globalBitcoinData.latestBlockNumber = 0
	globalBitcoinData.expire = make(map[uint64][]transaction.Link, bitcoinBlockRange)<commit_msg>[payment] use the configuration provided start block number<commit_after>// Copyright (c) 2014-2015 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package payment

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/hex"
	"encoding/json"
	"github.com/bitmark-inc/bitmarkd/background"
	"github.com/bitmark-inc/bitmarkd/configuration"
	"github.com/bitmark-inc/bitmarkd/fault"
	"github.com/bitmark-inc/bitmarkd/transaction"
	"github.com/bitmark-inc/logger"
	"io/ioutil"
	"net/http"
	"strings"
	"sync"
	"time"
)

// global constants
const (
	bitcoinMinimumVersion = 90200           // do not start if bitcoind older than this
	bitcoinRateLimit      = 15.0            // blocks/second
	bitcoinPollingTime    = 2 * time.Minute // sample bitcoin "blockcount" RPC at this interval
	bitcoinMaximumRetries = 10              // panic after this many consecutive errors
	bitcoinCurrencyName   = "bitcoin"       // all lowercase currency string
	bitcoinBlockRange     = 200             // number of blocks to consider as relevant
	bitcoinConfirmations  = 3               // stop processing this many blocks back from most recent block

	// this is how far back in the bitcoin block chain to start when process begins
	bitcoinBlockOffset = bitcoinBlockRange + bitcoinConfirmations
)

// globals for background proccess
type bitcoinData struct {
	sync.RWMutex // to allow locking

	// logger
	log *logger.L

	// connection to bitcoin daemon
	client *http.Client
	url    string

	// authentication
	username string
	password string

	// identifier for the RPC
	id uint64

	// payment info
	minerAddress      string
	fee               uint64 // value in Satoshis avoid float because of rounding errors
	latestBlockNumber uint64

	// for garbage collection
	expire map[uint64][]transaction.Link

	// for background
	background *background.T

	// set once during initialise
	initialised bool
}

// global data
var globalBitcoinData bitcoinData

// list of background processes to start
var bitcoinProcesses = background.Processes{
	bitcoinBackground,
}

// external API
// ------------

// initialise for bitcoin payments
// also calls the internal initialisePayment() and register()
//
// Note fee is a string value and is converted to Satoshis to avoid rounding errors
func BitcoinInitialise(configuration configuration.BitcoinAccess) error {

	// ensure payments are initialised
	if err := paymentInitialise(); nil != err {
		return err
	}

	globalBitcoinData.Lock()
	defer globalBitcoinData.Unlock()

	// no need to start if already started
	if globalBitcoinData.initialised {
		return fault.ErrAlreadyInitialised
	}

	if "" == configuration.Address {
		return fault.ErrPaymentAddressMissing
	}

	globalBitcoinData.log = logger.New(bitcoinCurrencyName)
	if nil == globalBitcoinData.log {
		return fault.ErrInvalidLoggerChannel
	}
	globalBitcoinData.log.Info("starting…")

	globalBitcoinData.id = 0
	globalBitcoinData.username = configuration.Username
	globalBitcoinData.password = <PASSWORD>
	globalBitcoinData.url = configuration.URL
	globalBitcoinData.minerAddress = configuration.Address
	globalBitcoinData.fee = convertToSatoshi([]byte(configuration.Fee))
	globalBitcoinData.latestBlockNumber = configuration.Start
	globalBitcoinData.expire = make(map[uint64][]transaction.Link, bitcoinBlockRange)
{'fraction_non_alphanumeric': 0.08317069509082721, 'fraction_numerical': 0.011259570635039785, 'mean_word_length': 3.665266106442577, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5587085', 'n_tokens_mistral': 2016, 'n_tokens_neox': 1886, 'n_words': 582}