<commit_before>package async

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var (
	input    chan *cmd
	output   chan *batchCmd
	groupDic map[string]*group
	gLocker  sync.RWMutex
)

type CacheProvider interface {
	Put(string, interface{}, interface{}) error
	Get(string, interface{}) (interface{}, error)
}

func init() {
	groupDic = make(map[string]*group)
	input = make(chan *cmd, 128)
	output = make(chan *batchCmd, 128)
	go runloop()
}

type group struct {
	name      string
	batchSize int
	method    func(...interface{}) (map[interface{}]interface{}, error)
	cmdDic    map[interface{}][]*cmd
	keyDic    map[interface{}]bool
	cache     CacheProvider
}

type cmd struct {
	group    string
	key      interface{}
	callback chan interface{}
}

type batchCmd struct {
	group  string
	keys   []interface{}
	err    error
	result map[interface{}]interface{}
}

func RegisterGroup(
	name string,
	batchSize int,
	method func(...interface{}) (map[interface{}]interface{}, error),
	cache CacheProvider) error {
	gLocker.Lock()
	defer gLocker.Unlock()
	_, ok := groupDic[name]
	if ok {
		return fmt.Errorf("duplicate group:%s", name)
	}
	groupDic[name] = &group{
		name:      name,
		batchSize: batchSize,
		method:    method,
		cmdDic:    make(map[interface{}][]*cmd),
		keyDic:    make(map[interface{}]bool),
		cache:     cache,
	}
	return nil
}

func doing(ctx context.Context, b *batchCmd, method func(...interface{}) (map[interface{}]interface{}, error)) {
	res, err := Safety(func() (interface{}, error) {
		return method(b.keys...)
	})
	if err != nil {
		b.err = err
	} else {
		b.result = res.(map[interface{}]interface{})
	}
	output <- b
}

func runloop() {
	ctx := context.Background()
	timer := time.NewTicker(10 * time.Millisecond)
	for {
		select {
		case c := <-input:
			{
				gLocker.RLocker()
				defer gLocker.RUnlock()
				g, ok := groupDic[c.group]
				if false == ok {
					c.callback <- fmt.Errorf("invalid group:%s", c.group)
					continue
				}
				// cache provider
				if g.cache != nil {
					res, err := g.cache.Get(g.name, c.key)
					if res != nil && err == nil {
						c.callback <- res
						continue
					}
				}
				target, ok := g.cmdDic[c.key]
				if ok {
					g.cmdDic[c.key] = append(target, c)
				} else {
					g.cmdDic[c.key] = []*cmd{c}
					g.keyDic[c.key] = true
				}

				if len(g.keyDic) >= g.batchSize {
					b := &batchCmd{group: g.name}
					b.keys = make([]interface{}, len(g.keyDic))
					index := 0
					for k, _ := range g.keyDic {
						b.keys[index] = k
						index = index + 1
					}
					g.keyDic = make(map[interface{}]bool)
					go doing(ctx, b, g.method)
				}
			}
		case b := <-output:
			{
				gLocker.RLocker()
				defer gLocker.RUnlock()
				g, _ := groupDic[b.group]
				if b.err != nil {
					for _, key := range b.keys {
						target, ok := g.cmdDic[key]
						if ok {
							for _, c := range target {
								c.callback <- b.err
								close(c.callback)
							}
						}
						delete(g.cmdDic, key)
					}
				} else {
					for _, key := range b.keys {
						res, ok := b.result[key]
						if false == ok {
							res = fmt.Errorf("invalid key:%s", key)
						} else {
							// cache provider
							if g.cache != nil {
								g.cache.Put(g.name, key, res)
							}
						}
						target, ok := g.cmdDic[key]
						if ok {
							for _, c := range target {
								c.callback <- res
								close(c.callback)
							}
						}
						delete(g.cmdDic, key)
					}
				}
			}
		case <-timer.C:
			{
				gLocker.RLocker()
				defer gLocker.RUnlock()
				for _, g := range groupDic {
					if len(g.keyDic) > 0 {
						b := &batchCmd{group: g.name}
						b.keys = make([]interface{}, len(g.keyDic))
						index := 0
						for k, _ := range g.keyDic {
							b.keys[index] = k
							index = index + 1
						}
						g.keyDic = make(map[interface{}]bool)
						go doing(ctx, b, g.method)
					}
				}
				timer.Reset(10 * time.Millisecond)
			}
		}
	}
}

func Get(group string, key interface{}) (interface{}, error) {
	c := &cmd{
		group:    group,
		key:      key,
		callback: make(chan interface{}, 1),
	}
	input <- c
	res := <-c.callback
	switch res.(type) {
	case error:
		return nil, res.(error)
	default:
		return res, nil
	}
}
<commit_msg>fix bug<commit_after>package async

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var (
	input    chan *cmd
	output   chan *batchCmd
	groupDic map[string]*group
	gLocker  sync.RWMutex
)

type CacheProvider interface {
	Put(string, interface{}, interface{}) error
	Get(string, interface{}) (interface{}, error)
}

func init() {
	groupDic = make(map[string]*group)
	input = make(chan *cmd, 128)
	output = make(chan *batchCmd, 128)
	go runloop()
}

type group struct {
	name      string
	batchSize int
	method    func(...interface{}) (map[interface{}]interface{}, error)
	cmdDic    map[interface{}][]*cmd
	keyDic    map[interface{}]bool
	cache     CacheProvider
}

type cmd struct {
	group    string
	key      interface{}
	callback chan interface{}
}

type batchCmd struct {
	group  string
	keys   []interface{}
	err    error
	result map[interface{}]interface{}
}

func RegisterGroup(
	name string,
	batchSize int,
	method func(...interface{}) (map[interface{}]interface{}, error),
	cache CacheProvider) error {
	gLocker.Lock()
	defer gLocker.Unlock()
	_, ok := groupDic[name]
	if ok {
		return fmt.Errorf("duplicate group:%s", name)
	}
	groupDic[name] = &group{
		name:      name,
		batchSize: batchSize,
		method:    method,
		cmdDic:    make(map[interface{}][]*cmd),
		keyDic:    make(map[interface{}]bool),
		cache:     cache,
	}
	return nil
}

func doing(ctx context.Context, b *batchCmd, method func(...interface{}) (map[interface{}]interface{}, error)) {
	res, err := Safety(func() (interface{}, error) {
		return method(b.keys...)
	})
	if err != nil {
		b.err = err
	} else {
		b.result = res.(map[interface{}]interface{})
	}
	output <- b
}

func runloop() {
	ctx := context.Background()
	timer := time.NewTicker(10 * time.Millisecond)
	for {
		select {
		case c := <-input:
			{
				gLocker.RLocker()
				defer gLocker.RUnlock()
				g, ok := groupDic[c.group]
				if false == ok {
					c.callback <- fmt.Errorf("invalid group:%s", c.group)
					close(c.callback)
					continue
				}
				// cache provider
				if g.cache != nil {
					res, err := g.cache.Get(g.name, c.key)
					if res != nil && err == nil {
						c.callback <- res
						close(c.callback)
						continue
					}
				}
				target, ok := g.cmdDic[c.key]
				if ok {
					g.cmdDic[c.key] = append(target, c)
				} else {
					g.cmdDic[c.key] = []*cmd{c}
					g.keyDic[c.key] = true
				}

				if len(g.keyDic) >= g.batchSize {
					b := &batchCmd{group: g.name}
					b.keys = make([]interface{}, len(g.keyDic))
					index := 0
					for k, _ := range g.keyDic {
						b.keys[index] = k
						index = index + 1
					}
					g.keyDic = make(map[interface{}]bool)
					go doing(ctx, b, g.method)
				}
			}
		case b := <-output:
			{
				gLocker.RLocker()
				defer gLocker.RUnlock()
				g, _ := groupDic[b.group]
				if b.err != nil {
					for _, key := range b.keys {
						target, ok := g.cmdDic[key]
						if ok {
							for _, c := range target {
								c.callback <- b.err
								close(c.callback)
							}
						}
						delete(g.cmdDic, key)
					}
				} else {
					for _, key := range b.keys {
						res, ok := b.result[key]
						if false == ok {
							res = fmt.Errorf("invalid key:%s", key)
						} else {
							// cache provider
							if g.cache != nil {
								g.cache.Put(g.name, key, res)
							}
						}
						target, ok := g.cmdDic[key]
						if ok {
							for _, c := range target {
								c.callback <- res
								close(c.callback)
							}
						}
						delete(g.cmdDic, key)
					}
				}
			}
		case <-timer.C:
			{
				gLocker.RLocker()
				defer gLocker.RUnlock()
				for _, g := range groupDic {
					if len(g.keyDic) > 0 {
						b := &batchCmd{group: g.name}
						b.keys = make([]interface{}, len(g.keyDic))
						index := 0
						for k, _ := range g.keyDic {
							b.keys[index] = k
							index = index + 1
						}
						g.keyDic = make(map[interface{}]bool)
						go doing(ctx, b, g.method)
					}
				}
				timer.Reset(10 * time.Millisecond)
			}
		}
	}
}

func Get(group string, key interface{}) (interface{}, error) {
	c := &cmd{
		group:    group,
		key:      key,
		callback: make(chan interface{}, 1),
	}
	input <- c
	res := <-c.callback
	switch res.(type) {
	case error:
		return nil, res.(error)
	default:
		return res, nil
	}
}
<|endoftext|>


<commit_before>package virtualbox

import (
	"bytes"
	"fmt"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"log"
	"strings"
	"text/template"
	"time"
	"unicode"
	"unicode/utf8"
)

const KeyLeftShift uint32 = 0xFFE1

type bootCommandTemplateData struct {
	HTTPIP   string
	HTTPPort uint
	Name     string
}

// This step "types" the boot command into the VM over VNC.
//
// Uses:
//   config *config
//   driver Driver
//   http_port int
//   ui     packer.Ui
//   vmName string
//
// Produces:
//   <nothing>
type stepTypeBootCommand struct{}

func (s *stepTypeBootCommand) Run(state map[string]interface{}) multistep.StepAction {
	config := state["config"].(*config)
	driver := state["driver"].(Driver)
	httpPort := state["http_port"].(uint)
	ui := state["ui"].(packer.Ui)
	vmName := state["vmName"].(string)

	tplData := &bootCommandTemplateData{
		"10.0.2.2",
		httpPort,
		config.VMName,
	}

	ui.Say("Typing the boot command...")
	for _, command := range config.BootCommand {
		var buf bytes.Buffer
		t := template.Must(template.New("boot").Parse(command))
		t.Execute(&buf, tplData)

		for _, code := range scancodes(buf.String()) {
			if code == "wait" {
				time.Sleep(1 * time.Second)
				continue
			}

			// Since typing is sometimes so slow, we check for an interrupt
			// in between each character.
			if _, ok := state[multistep.StateCancelled]; ok {
				return multistep.ActionHalt
			}

			if err := driver.VBoxManage("controlvm", vmName, "keyboardputscancode", code); err != nil {
				err := fmt.Errorf("Error sending boot command: %s", err)
				state["error"] = err
				ui.Error(err.Error())
				return multistep.ActionHalt
			}
		}
	}

	return multistep.ActionContinue
}

func (*stepTypeBootCommand) Cleanup(map[string]interface{}) {}

func scancodes(message string) []string {
	special := make(map[string][]string)
	special["<enter>"] = []string{"1c", "9c"}
	special["<return>"] = []string{"1c", "9c"}
	special["<esc>"] = []string{"01", "81"}

	shiftedChars := "~!@#$%^&*()_+{}|:\"<>?"

	// Scancodes reference: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
	scancodeIndex := make(map[string]uint)
	scancodeIndex["1234567890-="] = 0x02
	scancodeIndex["!@#$%^&*()_+"] = 0x02
	scancodeIndex["qwertyuiop[]"] = 0x10
	scancodeIndex["QWERTYUIOP{}"] = 0x10
	scancodeIndex["asdfghjkl;'`"] = 0x1e
	scancodeIndex[`ASDFGHJKL:"~`] = 0x1e
	scancodeIndex[`\zxcvbnm,./`] = 0x2b
	scancodeIndex["|ZXCVBNM<>?"] = 0x2b
	scancodeIndex[" "] = 0x39

	scancodeMap := make(map[rune]uint)
	for chars, start := range scancodeIndex {
		var i uint = 0
		for len(chars) > 0 {
			r, size := utf8.DecodeRuneInString(chars)
			chars = chars[size:]
			scancodeMap[r] = start + i
			i += 1
		}
	}

	result := make([]string, 0, len(message)*2)
	for len(message) > 0 {
		var scancode []string

		if strings.HasPrefix(message, "<wait>") {
			log.Printf("Special code <wait> found, will sleep at this point.")
			scancode = []string{"wait"}
			message = message[len("<wait>"):]
		}

		if scancode == nil {
			for specialCode, specialValue := range special {
				if strings.HasPrefix(message, specialCode) {
					log.Printf("Special code '%s' found, replacing with: %s", specialCode, specialValue)
					scancode = specialValue
					message = message[len(specialCode):]
					break
				}
			}
		}

		if scancode == nil {
			r, size := utf8.DecodeRuneInString(message)
			message = message[size:]
			scancodeInt := scancodeMap[r]
			keyShift := unicode.IsUpper(r) || strings.ContainsRune(shiftedChars, r)

			scancode = make([]string, 0, 4)
			if keyShift {
				scancode = append(scancode, "2a")
			}

			scancode = append(scancode, fmt.Sprintf("%02x", scancodeInt))

			if keyShift {
				scancode = append(scancode, "aa")
			}

			scancode = append(scancode, fmt.Sprintf("%02x", scancodeInt+0x80))
			log.Printf("Sending char '%c', code '%v', shift %v", r, scancode, keyShift)
		}

		result = append(result, scancode...)
	}

	return result
}
<commit_msg>builder/virtualbox: recognize <tab><commit_after>package virtualbox

import (
	"bytes"
	"fmt"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"log"
	"strings"
	"text/template"
	"time"
	"unicode"
	"unicode/utf8"
)

const KeyLeftShift uint32 = 0xFFE1

type bootCommandTemplateData struct {
	HTTPIP   string
	HTTPPort uint
	Name     string
}

// This step "types" the boot command into the VM over VNC.
//
// Uses:
//   config *config
//   driver Driver
//   http_port int
//   ui     packer.Ui
//   vmName string
//
// Produces:
//   <nothing>
type stepTypeBootCommand struct{}

func (s *stepTypeBootCommand) Run(state map[string]interface{}) multistep.StepAction {
	config := state["config"].(*config)
	driver := state["driver"].(Driver)
	httpPort := state["http_port"].(uint)
	ui := state["ui"].(packer.Ui)
	vmName := state["vmName"].(string)

	tplData := &bootCommandTemplateData{
		"10.0.2.2",
		httpPort,
		config.VMName,
	}

	ui.Say("Typing the boot command...")
	for _, command := range config.BootCommand {
		var buf bytes.Buffer
		t := template.Must(template.New("boot").Parse(command))
		t.Execute(&buf, tplData)

		for _, code := range scancodes(buf.String()) {
			if code == "wait" {
				time.Sleep(1 * time.Second)
				continue
			}

			// Since typing is sometimes so slow, we check for an interrupt
			// in between each character.
			if _, ok := state[multistep.StateCancelled]; ok {
				return multistep.ActionHalt
			}

			if err := driver.VBoxManage("controlvm", vmName, "keyboardputscancode", code); err != nil {
				err := fmt.Errorf("Error sending boot command: %s", err)
				state["error"] = err
				ui.Error(err.Error())
				return multistep.ActionHalt
			}
		}
	}

	return multistep.ActionContinue
}

func (*stepTypeBootCommand) Cleanup(map[string]interface{}) {}

func scancodes(message string) []string {
	special := make(map[string][]string)
	special["<enter>"] = []string{"1c", "9c"}
	special["<esc>"] = []string{"01", "81"}
	special["<return>"] = []string{"1c", "9c"}
	special["<tab>"] = []string{"0f", "8f"}

	shiftedChars := "~!@#$%^&*()_+{}|:\"<>?"

	// Scancodes reference: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
	scancodeIndex := make(map[string]uint)
	scancodeIndex["1234567890-="] = 0x02
	scancodeIndex["!@#$%^&*()_+"] = 0x02
	scancodeIndex["qwertyuiop[]"] = 0x10
	scancodeIndex["QWERTYUIOP{}"] = 0x10
	scancodeIndex["asdfghjkl;'`"] = 0x1e
	scancodeIndex[`ASDFGHJKL:"~`] = 0x1e
	scancodeIndex[`\zxcvbnm,./`] = 0x2b
	scancodeIndex["|ZXCVBNM<>?"] = 0x2b
	scancodeIndex[" "] = 0x39

	scancodeMap := make(map[rune]uint)
	for chars, start := range scancodeIndex {
		var i uint = 0
		for len(chars) > 0 {
			r, size := utf8.DecodeRuneInString(chars)
			chars = chars[size:]
			scancodeMap[r] = start + i
			i += 1
		}
	}

	result := make([]string, 0, len(message)*2)
	for len(message) > 0 {
		var scancode []string

		if strings.HasPrefix(message, "<wait>") {
			log.Printf("Special code <wait> found, will sleep at this point.")
			scancode = []string{"wait"}
			message = message[len("<wait>"):]
		}

		if scancode == nil {
			for specialCode, specialValue := range special {
				if strings.HasPrefix(message, specialCode) {
					log.Printf("Special code '%s' found, replacing with: %s", specialCode, specialValue)
					scancode = specialValue
					message = message[len(specialCode):]
					break
				}
			}
		}

		if scancode == nil {
			r, size := utf8.DecodeRuneInString(message)
			message = message[size:]
			scancodeInt := scancodeMap[r]
			keyShift := unicode.IsUpper(r) || strings.ContainsRune(shiftedChars, r)

			scancode = make([]string, 0, 4)
			if keyShift {
				scancode = append(scancode, "2a")
			}

			scancode = append(scancode, fmt.Sprintf("%02x", scancodeInt))

			if keyShift {
				scancode = append(scancode, "aa")
			}

			scancode = append(scancode, fmt.Sprintf("%02x", scancodeInt+0x80))
			log.Printf("Sending char '%c', code '%v', shift %v", r, scancode, keyShift)
		}

		result = append(result, scancode...)
	}

	return result
}
<|endoftext|>


<commit_before>package bip39

import (
	"crypto/rand"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"errors"
	"fmt"
	"math/big"
	"strings"

	"golang.org/x/crypto/pbkdf2"
)

var (
	// Some bitwise operands for working with big.Ints
	Last11BitsMask          = big.NewInt(2047)
	RightShift11BitsDivider = big.NewInt(2048)
	BigOne                  = big.NewInt(1)
	BigTwo                  = big.NewInt(2)

	// Wordlist sets the language used for the mnemonic
	WordList       = EnglishWordList

	// ReverseWordMap is a reverse lookup of Wordlist
	ReverseWordMap = map[string]int{}
)

func init() {
	for i, v := range WordList {
		ReverseWordMap[v] = i
	}
}

// NewEntropy will create random entropy bytes
// so long as the requested size bitSize is an appropriate size.
func NewEntropy(bitSize int) ([]byte, error) {
	err := validateEntropyBitSize(bitSize)
	if err != nil {
		return nil, err
	}

	entropy := make([]byte, bitSize/8)
	_, err = rand.Read(entropy)
	return entropy, err
}

// NewMnemonic will return a string consisting of the mnemonic words for
// the given entropy.
// If the provide entropy is invalid, an error will be returned.
func NewMnemonic(entropy []byte) (string, error) {
	// Compute some lengths for convenience
	entropyBitLength := len(entropy) * 8
	checksumBitLength := entropyBitLength / 32
	sentenceLength := (entropyBitLength + checksumBitLength) / 11

	err := validateEntropyBitSize(entropyBitLength)
	if err != nil {
		return "", err
	}

	// Add checksum to entropy
	entropy = addChecksum(entropy)

	// Break entropy up into sentenceLength chunks of 11 bits
	// For each word AND mask the rightmost 11 bits and find the word at that index
	// Then bitshift entropy 11 bits right and repeat
	// Add to the last empty slot so we can work with LSBs instead of MSB

	// Entropy as an int so we can bitmask without worrying about bytes slices
	entropyInt := new(big.Int).SetBytes(entropy)

	// Slice to hold words in
	words := make([]string, sentenceLength)

	// Throw away big int for AND masking
	word := big.NewInt(0)

	for i := sentenceLength - 1; i >= 0; i-- {
		// Get 11 right most bits and bitshift 11 to the right for next time
		word.And(entropyInt, Last11BitsMask)
		entropyInt.Div(entropyInt, RightShift11BitsDivider)

		// Get the bytes representing the 11 bits as a 2 byte slice
		wordBytes := padByteSlice(word.Bytes(), 2)

		// Convert bytes to an index and add that word to the list
		words[i] = WordList[binary.BigEndian.Uint16(wordBytes)]
	}

	return strings.Join(words, " "), nil
}

// MnemonicToByteArray takes a mnemonic string and turns it into a byte array
// suitable for creating another mnemonic.
// An error is returned if the mnemonic is invalid.
func MnemonicToByteArray(mnemonic string) ([]byte, error) {
	if IsMnemonicValid(mnemonic) == false {
		return nil, fmt.Errorf("Invalid mnemonic")
	}
	mnemonicSlice := strings.Split(mnemonic, " ")

	bitSize := len(mnemonicSlice) * 11
	err := validateEntropyWithChecksumBitSize(bitSize)
	if err != nil {
		return nil, err
	}
	checksumSize := bitSize % 32

	b := big.NewInt(0)
	modulo := big.NewInt(2048)
	for _, v := range mnemonicSlice {
		index, found := ReverseWordMap[v]
		if found == false {
			return nil, fmt.Errorf("Word `%v` not found in reverse map", v)
		}
		add := big.NewInt(int64(index))
		b = b.Mul(b, modulo)
		b = b.Add(b, add)
	}
	hex := b.Bytes()
	checksumModulo := big.NewInt(0).Exp(big.NewInt(2), big.NewInt(int64(checksumSize)), nil)
	entropy, _ := big.NewInt(0).DivMod(b, checksumModulo, big.NewInt(0))

	entropyHex := entropy.Bytes()

	// Add padding (an extra byte is for checksum)
	byteSize := (bitSize-checksumSize)/8 + 1
	if len(hex) != byteSize {
		tmp := make([]byte, byteSize)
		diff := byteSize - len(hex)
		for i := 0; i < len(hex); i++ {
			tmp[i+diff] = hex[i]
		}
		hex = tmp
	}

	// Add padding (no extra byte, entropy itself does not contain checksum)
	entropyByteSize := (bitSize - checksumSize) / 8
	if len(entropyHex) != entropyByteSize {
		tmp := make([]byte, entropyByteSize)
		diff := entropyByteSize - len(entropyHex)
		for i := 0; i < len(entropyHex); i++ {
			tmp[i+diff] = entropyHex[i]
		}
		entropyHex = tmp
	}

	validationHex := addChecksum(entropyHex)
	if len(validationHex) != byteSize {
		tmp2 := make([]byte, byteSize)
		diff2 := byteSize - len(validationHex)
		for i := 0; i < len(validationHex); i++ {
			tmp2[i+diff2] = validationHex[i]
		}
		validationHex = tmp2
	}

	if len(hex) != len(validationHex) {
		panic("[]byte len mismatch - it shouldn't happen")
	}
	for i := range validationHex {
		if hex[i] != validationHex[i] {
			return nil, fmt.Errorf("Invalid byte at position %v", i)
		}
	}
	return hex, nil
}

// NewSeedWithErrorChecking creates a hashed seed output given the mnemonic string and a password.
// An error is returned if the mnemonic is not convertible to a byte array.
func NewSeedWithErrorChecking(mnemonic string, password string) ([]byte, error) {
	_, err := MnemonicToByteArray(mnemonic)
	if err != nil {
		return nil, err
	}
	return NewSeed(mnemonic, password), nil
}

// NewSeed creates a hashed seed output given a provided string and password.
// No checking is performed to validate that the string provided is a valid mnemonic.
func NewSeed(mnemonic string, password string) []byte {
	return pbkdf2.Key([]byte(mnemonic), []byte("mnemonic"+password), 2048, 64, sha512.New)
}

// Appends to data the first (len(data) / 32)bits of the result of sha256(data)
// Currently only supports data up to 32 bytes
func addChecksum(data []byte) []byte {
	// Get first byte of sha256
	hasher := sha256.New()
	hasher.Write(data)
	hash := hasher.Sum(nil)
	firstChecksumByte := hash[0]

	// len() is in bytes so we divide by 4
	checksumBitLength := uint(len(data) / 4)

	// For each bit of check sum we want we shift the data one the left
	// and then set the (new) right most bit equal to checksum bit at that index
	// staring from the left
	dataBigInt := new(big.Int).SetBytes(data)
	for i := uint(0); i < checksumBitLength; i++ {
		// Bitshift 1 left
		dataBigInt.Mul(dataBigInt, BigTwo)

		// Set rightmost bit if leftmost checksum bit is set
		if uint8(firstChecksumByte&(1<<(7-i))) > 0 {
			dataBigInt.Or(dataBigInt, BigOne)
		}
	}

	return dataBigInt.Bytes()
}

func padByteSlice(slice []byte, length int) []byte {
	newSlice := make([]byte, length-len(slice))
	return append(newSlice, slice...)
}

func validateEntropyBitSize(bitSize int) error {
	if (bitSize%32) != 0 || bitSize < 128 || bitSize > 256 {
		return errors.New("Entropy length must be [128, 256] and a multiple of 32")
	}
	return nil
}

func validateEntropyWithChecksumBitSize(bitSize int) error {
	if (bitSize != 128+4) && (bitSize != 160+5) && (bitSize != 192+6) && (bitSize != 224+7) && (bitSize != 256+8) {
		return fmt.Errorf("Wrong entropy + checksum size - expected %v, got %v", int((bitSize-bitSize%32)+(bitSize-bitSize%32)/32), bitSize)
	}
	return nil
}

// IsMnemonicValid attempts to verify that the provided mnemonic is valid.
// Validity is determined by both the number of words being appropriate,
// and that all the words in the mnemonic are present in the word list.
func IsMnemonicValid(mnemonic string) bool {
	// Create a list of all the words in the mnemonic sentence
	words := strings.Fields(mnemonic)

	//Get num of words
	numOfWords := len(words)

	// The number of words should be 12, 15, 18, 21 or 24
	if numOfWords%3 != 0 || numOfWords < 12 || numOfWords > 24 {
		return false
	}

	// Check if all words belong in the wordlist
	for i := 0; i < numOfWords; i++ {
		if !contains(WordList, words[i]) {
			return false
		}
	}

	return true
}

func contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}
<commit_msg>better checksum failure reporting<commit_after>package bip39

import (
	"crypto/rand"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"errors"
	"fmt"
	"math/big"
	"strings"

	"golang.org/x/crypto/pbkdf2"
)

var (
	// Some bitwise operands for working with big.Ints
	Last11BitsMask          = big.NewInt(2047)
	RightShift11BitsDivider = big.NewInt(2048)
	BigOne                  = big.NewInt(1)
	BigTwo                  = big.NewInt(2)

	// Wordlist sets the language used for the mnemonic
	WordList       = EnglishWordList

	// ReverseWordMap is a reverse lookup of Wordlist
	ReverseWordMap = map[string]int{}
)

func init() {
	for i, v := range WordList {
		ReverseWordMap[v] = i
	}
}

// NewEntropy will create random entropy bytes
// so long as the requested size bitSize is an appropriate size.
func NewEntropy(bitSize int) ([]byte, error) {
	err := validateEntropyBitSize(bitSize)
	if err != nil {
		return nil, err
	}

	entropy := make([]byte, bitSize/8)
	_, err = rand.Read(entropy)
	return entropy, err
}

// NewMnemonic will return a string consisting of the mnemonic words for
// the given entropy.
// If the provide entropy is invalid, an error will be returned.
func NewMnemonic(entropy []byte) (string, error) {
	// Compute some lengths for convenience
	entropyBitLength := len(entropy) * 8
	checksumBitLength := entropyBitLength / 32
	sentenceLength := (entropyBitLength + checksumBitLength) / 11

	err := validateEntropyBitSize(entropyBitLength)
	if err != nil {
		return "", err
	}

	// Add checksum to entropy
	entropy = addChecksum(entropy)

	// Break entropy up into sentenceLength chunks of 11 bits
	// For each word AND mask the rightmost 11 bits and find the word at that index
	// Then bitshift entropy 11 bits right and repeat
	// Add to the last empty slot so we can work with LSBs instead of MSB

	// Entropy as an int so we can bitmask without worrying about bytes slices
	entropyInt := new(big.Int).SetBytes(entropy)

	// Slice to hold words in
	words := make([]string, sentenceLength)

	// Throw away big int for AND masking
	word := big.NewInt(0)

	for i := sentenceLength - 1; i >= 0; i-- {
		// Get 11 right most bits and bitshift 11 to the right for next time
		word.And(entropyInt, Last11BitsMask)
		entropyInt.Div(entropyInt, RightShift11BitsDivider)

		// Get the bytes representing the 11 bits as a 2 byte slice
		wordBytes := padByteSlice(word.Bytes(), 2)

		// Convert bytes to an index and add that word to the list
		words[i] = WordList[binary.BigEndian.Uint16(wordBytes)]
	}

	return strings.Join(words, " "), nil
}

// MnemonicToByteArray takes a mnemonic string and turns it into a byte array
// suitable for creating another mnemonic.
// An error is returned if the mnemonic is invalid.
func MnemonicToByteArray(mnemonic string) ([]byte, error) {
	if IsMnemonicValid(mnemonic) == false {
		return nil, fmt.Errorf("Invalid mnemonic")
	}
	mnemonicSlice := strings.Split(mnemonic, " ")

	bitSize := len(mnemonicSlice) * 11
	err := validateEntropyWithChecksumBitSize(bitSize)
	if err != nil {
		return nil, err
	}
	checksumSize := bitSize % 32

	b := big.NewInt(0)
	modulo := big.NewInt(2048)
	for _, v := range mnemonicSlice {
		index, found := ReverseWordMap[v]
		if found == false {
			return nil, fmt.Errorf("Word `%v` not found in reverse map", v)
		}
		add := big.NewInt(int64(index))
		b = b.Mul(b, modulo)
		b = b.Add(b, add)
	}
	hex := b.Bytes()
	checksumModulo := big.NewInt(0).Exp(big.NewInt(2), big.NewInt(int64(checksumSize)), nil)
	entropy, _ := big.NewInt(0).DivMod(b, checksumModulo, big.NewInt(0))

	entropyHex := entropy.Bytes()

	// Add padding (an extra byte is for checksum)
	byteSize := (bitSize-checksumSize)/8 + 1
	if len(hex) != byteSize {
		tmp := make([]byte, byteSize)
		diff := byteSize - len(hex)
		for i := 0; i < len(hex); i++ {
			tmp[i+diff] = hex[i]
		}
		hex = tmp
	}

	// Add padding (no extra byte, entropy itself does not contain checksum)
	entropyByteSize := (bitSize - checksumSize) / 8
	if len(entropyHex) != entropyByteSize {
		tmp := make([]byte, entropyByteSize)
		diff := entropyByteSize - len(entropyHex)
		for i := 0; i < len(entropyHex); i++ {
			tmp[i+diff] = entropyHex[i]
		}
		entropyHex = tmp
	}

	validationHex := addChecksum(entropyHex)
	if len(validationHex) != byteSize {
		tmp2 := make([]byte, byteSize)
		diff2 := byteSize - len(validationHex)
		for i := 0; i < len(validationHex); i++ {
			tmp2[i+diff2] = validationHex[i]
		}
		validationHex = tmp2
	}

	if len(hex) != len(validationHex) {
		panic("[]byte len mismatch - it shouldn't happen")
	}
	for i := range validationHex {
		if hex[i] != validationHex[i] {
			return nil, fmt.Errorf("Mnemonic checksum error. Check words are in correct order. (decoded byte %v)", i)
		}
	}
	return hex, nil
}

// NewSeedWithErrorChecking creates a hashed seed output given the mnemonic string and a password.
// An error is returned if the mnemonic is not convertible to a byte array.
func NewSeedWithErrorChecking(mnemonic string, password string) ([]byte, error) {
	_, err := MnemonicToByteArray(mnemonic)
	if err != nil {
		return nil, err
	}
	return NewSeed(mnemonic, password), nil
}

// NewSeed creates a hashed seed output given a provided string and password.
// No checking is performed to validate that the string provided is a valid mnemonic.
func NewSeed(mnemonic string, password string) []byte {
	return pbkdf2.Key([]byte(mnemonic), []byte("mnemonic"+password), 2048, 64, sha512.New)
}

// Appends to data the first (len(data) / 32)bits of the result of sha256(data)
// Currently only supports data up to 32 bytes
func addChecksum(data []byte) []byte {
	// Get first byte of sha256
	hasher := sha256.New()
	hasher.Write(data)
	hash := hasher.Sum(nil)
	firstChecksumByte := hash[0]

	// len() is in bytes so we divide by 4
	checksumBitLength := uint(len(data) / 4)

	// For each bit of check sum we want we shift the data one the left
	// and then set the (new) right most bit equal to checksum bit at that index
	// staring from the left
	dataBigInt := new(big.Int).SetBytes(data)
	for i := uint(0); i < checksumBitLength; i++ {
		// Bitshift 1 left
		dataBigInt.Mul(dataBigInt, BigTwo)

		// Set rightmost bit if leftmost checksum bit is set
		if uint8(firstChecksumByte&(1<<(7-i))) > 0 {
			dataBigInt.Or(dataBigInt, BigOne)
		}
	}

	return dataBigInt.Bytes()
}

func padByteSlice(slice []byte, length int) []byte {
	newSlice := make([]byte, length-len(slice))
	return append(newSlice, slice...)
}

func validateEntropyBitSize(bitSize int) error {
	if (bitSize%32) != 0 || bitSize < 128 || bitSize > 256 {
		return errors.New("Entropy length must be [128, 256] and a multiple of 32")
	}
	return nil
}

func validateEntropyWithChecksumBitSize(bitSize int) error {
	if (bitSize != 128+4) && (bitSize != 160+5) && (bitSize != 192+6) && (bitSize != 224+7) && (bitSize != 256+8) {
		return fmt.Errorf("Wrong entropy + checksum size - expected %v, got %v", int((bitSize-bitSize%32)+(bitSize-bitSize%32)/32), bitSize)
	}
	return nil
}

// IsMnemonicValid attempts to verify that the provided mnemonic is valid.
// Validity is determined by both the number of words being appropriate,
// and that all the words in the mnemonic are present in the word list.
func IsMnemonicValid(mnemonic string) bool {
	// Create a list of all the words in the mnemonic sentence
	words := strings.Fields(mnemonic)

	//Get num of words
	numOfWords := len(words)

	// The number of words should be 12, 15, 18, 21 or 24
	if numOfWords%3 != 0 || numOfWords < 12 || numOfWords > 24 {
		return false
	}

	// Check if all words belong in the wordlist
	for i := 0; i < numOfWords; i++ {
		if !contains(WordList, words[i]) {
			return false
		}
	}

	return true
}

func contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package goory

import (
	"github.com/bongo227/goory/instructions"
	"github.com/bongo227/goory/types"
	"github.com/bongo227/goory/value"
)

type nextName func() string

// Block is a seqential list of instructions ending with a terminator instruction
type Block struct {
	function     *Function
	name         string
	instructions []value.Instruction
	nextName     nextName
}

func newBlock(function *Function, name string) *Block {
	return &Block{
		function: function,
		name:     name,
		nextName: function.module.nextTempName,
	}
}

// Function returns the parent function
func (b *Block) Function() *Function {
	return b.function
}

// Name gets the name of the block
func (b *Block) Name() string {
	return b.name
}

// Llvm returns the llvm ir representation of the block
func (b *Block) Llvm() string {
	s := "\t" + b.name + ":\n"
	for _, i := range b.instructions {
		s += "\t\t" + i.Llvm() + "\n"
	}

	return s
}

// Type returns new block type
func (b *Block) Type() types.Type {
	return types.NewBlockType()
}

// Ident gets the identifyer of the block
func (b *Block) Ident() string {
	return b.name
}

// Terminated returns true if the block is terminated (ends in branch or return)
func (b *Block) Terminated() bool {
	return b.instructions[len(b.instructions)-1].IsTerminator()
}

// Add creates a new add instruction.
// lhs and rhs must be integer types of the same size.
// Add returns the result of this instruction with the same type as lhs and rhs.
func (b *Block) Add(lhs value.Value, rhs value.Value) *instructions.Add {
	i := instructions.NewAdd(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// And create a new and instruction.
// lhs and rhs must be boolean types.
// And returns the result of the instruction as a boolean type.
func (b *Block) And(lhs, rhs value.Value) *instructions.And {
	i := instructions.NewAnd(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Br creates a new br instruction.
// block must be a block type.
func (b *Block) Br(block value.Value) *instructions.Br {
	i := instructions.NewBr(b, b.nextName(), block)
	b.instructions = append(b.instructions, i)
	return i
}

// Call creates a new call instruction.
// function must be a function type.
// operands must match the types of the function arguments.
// Call returns the result of the instruction with the same type as the function return type.
func (b *Block) Call(function value.Value, operands ...value.Value) *instructions.Call {
	i := instructions.NewCall(b, b.nextName(), function, operands...)
	b.instructions = append(b.instructions, i)
	return i
}

// CondBr creates a new conditional branch instruction.
// condition must be a boolean type.
// trueBlock and falseBlock must be block types.
func (b *Block) CondBr(condition, trueBlock, falseBlock value.Value) *instructions.CondBr {
	i := instructions.NewCondBr(b, b.nextName(), condition, trueBlock, falseBlock)
	b.instructions = append(b.instructions, i)
	return i
}

// Div creates a new integer division instruction.
// lhs and rhs must be integer types.
// Div returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Div(lhs, rhs value.Value) *instructions.Div {
	i := instructions.NewDiv(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Extractvalue creates a new extract value instruction
// location must be an aggregate type
// position is the index at which to extract the value from location
// Extractvalue returns the type specified in location at index position
func (b *Block) Extractvalue(location value.Value, position int) *instructions.Extractvalue {
	i := instructions.NewExtractvalue(b, b.nextName(), location, position)
	b.instructions = append(b.instructions, i)
	return i
}

// Fadd creates a new float add instruction.
// lhs and rhs must be float or double types.
// Fadd returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Fadd(lhs value.Value, rhs value.Value) *instructions.Fadd {
	i := instructions.NewFadd(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Fcmp creates a new float add instruction.
// mode controls the behavior of the comparison, see https://godoc.org/github.com/bongo227/goory#pkg-variables.
// lhs and rhs must be float or double types.
// Fcmp returns the result of the instruction as a boolean type.
func (b *Block) Fcmp(mode string, lhs, rhs value.Value) *instructions.Fcmp {
	i := instructions.NewFcmp(b, b.nextName(), mode, lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Fdiv creates a new float add instruction.
// lhs and rhs must be float or double types.
// Fdiv returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Fdiv(lhs value.Value, rhs value.Value) *instructions.Fdiv {
	i := instructions.NewFdiv(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Fmul creates a new float add instruction.
// lhs and rhs must be float or double types.
// Fmul returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Fmul(lhs value.Value, rhs value.Value) *instructions.Fmul {
	i := instructions.NewFmul(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Fpext creates a new float extention instruction.
// value must be a float or double type.
// cast must be a type larger than value.
// Fpext returns the result of the instruction with the same type as cast.
func (b *Block) Fpext(value value.Value, cast types.Type) *instructions.Fpext {
	// TODO: add support for fp128 etc
	i := instructions.NewFpext(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Fptosi creates a new float to signed integer type.
// value must be a float of double type.
// cast must be an integer type.
// Fptosi returns the result of the instruction with the same type as cast.
func (b *Block) Fptosi(value value.Value, cast types.Type) *instructions.Fptosi {
	i := instructions.NewFptosi(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Fptrunc creates a new float truncation.
// value must be a float or double type.
// cast must be a type smaller than value.
// Fptrunc returns the result of the instruction with the same type as cast.
func (b *Block) Fptrunc(value value.Value, cast types.Type) *instructions.Fptrunc {
	i := instructions.NewFptrunc(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Fsub creates a new float subtraction instruction.
// lhs and rhs must be float or double types.
// Fsub returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Fsub(lhs value.Value, rhs value.Value) *instructions.Fsub {
	i := instructions.NewFsub(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

var (
	// IntEq is an integer equals comparison
	IntEq = "eq"

	// IntUlt is an integer unordered less than comparison
	IntUlt = "ult"
)

// Insertvalue creates a new insert value instruction.
// location must be an aggregate type the value is to be inserted into.
// value must match the type of the location at index position.
// position spesifys the index in which to insert value in location.
// Insertvalue returns the result of the instruction with the same type as location.
func (b *Block) Insertvalue(location, value value.Value, position int) *instructions.Insertvalue {
	i := instructions.NewInsertvalue(b, b.nextName(), location, value, position)
	b.instructions = append(b.instructions, i)
	return i
}

// Icmp creates a new integer comparison instruction.
// mode controls the behavior of the comparison, see: https://godoc.org/github.com/bongo227/goory#pkg-variables.
// lhs and rhs must be integer types of the the same size.
// Icmp returns the result of the instruction as a boolean type.
func (b *Block) Icmp(mode string, lhs, rhs value.Value) *instructions.Icmp {
	i := instructions.NewIcmp(b, b.nextName(), mode, lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Mul creates a new integer multiplication instruction.
// lhs and rhs must be integer types of the the same size.
// Mul returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Mul(lhs value.Value, rhs value.Value) *instructions.Mul {
	i := instructions.NewMul(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Or creates a new bitwise or instruction.
// lhs and rhs must be boolean types.
// Or returns the result of the instruction as a boolean type.
func (b *Block) Or(lhs value.Value, rhs value.Value) *instructions.Or {
	i := instructions.NewOr(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Phi creates a new phi instruction.
// Phi returns the phi instruction to which you add all incoming blocks.
func (b *Block) Phi() *instructions.Phi {
	i := instructions.NewPhi(b, b.nextName())
	b.instructions = append(b.instructions, i)
	return i
}

// Ret creates a new return instruction.
// value must be the same type as the function return type.
func (b *Block) Ret(value value.Value) *instructions.Ret {
	i := instructions.NewRet(b, value)
	b.instructions = append(b.instructions, i)
	return i
}

// Sitofp creates a new signed integer to float instruction.
// value must be an integer type.
// cast must be a float type.
// Sitofp returns the result of the instruction with the same type as cast.
func (b *Block) Sitofp(value value.Value, cast types.Type) *instructions.Sitofp {
	i := instructions.NewSitofp(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Sub creates a new float sub instruction.
// lhs and rhs must be float or double types.
// Sub retruns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Sub(lhs value.Value, rhs value.Value) *instructions.Sub {
	i := instructions.NewSub(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Trunc creates a new integer truncation instruction.
// value must be an integer type.
// cast must be a integer type smaller than value.
// Trunc returns the result of the instruction with the same type as cast.
func (b *Block) Trunc(value value.Value, cast types.Type) *instructions.Trunc {
	i := instructions.NewTrunc(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Xor creates a new float exclusive or instruction.
// lhs and rhs must be boolean types.
// Xor returns the result of the instruction as a boolean type.
func (b *Block) Xor(lhs value.Value, rhs value.Value) *instructions.Xor {
	i := instructions.NewXor(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Zext creates a new zero extention instruction.
// value must be an integer type.
// cast must be a integer type larger than value.
// Zext returns the result of the instruction with the same type as cast.
func (b *Block) Zext(value value.Value, cast types.Type) *instructions.Zext {
	i := instructions.NewZext(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}
<commit_msg>Added more integer/float comparison modes and readded the cast method<commit_after>package goory

import (
	"github.com/bongo227/goory/instructions"
	"github.com/bongo227/goory/types"
	"github.com/bongo227/goory/value"
)

type nextName func() string

// Block is a seqential list of instructions ending with a terminator instruction
type Block struct {
	function     *Function
	name         string
	instructions []value.Instruction
	nextName     nextName
}

func newBlock(function *Function, name string) *Block {
	return &Block{
		function: function,
		name:     name,
		nextName: function.module.nextTempName,
	}
}

// Function returns the parent function
func (b *Block) Function() *Function {
	return b.function
}

// Name gets the name of the block
func (b *Block) Name() string {
	return b.name
}

// Llvm returns the llvm ir representation of the block
func (b *Block) Llvm() string {
	s := "\t" + b.name + ":\n"
	for _, i := range b.instructions {
		s += "\t\t" + i.Llvm() + "\n"
	}

	return s
}

// Type returns new block type
func (b *Block) Type() types.Type {
	return types.NewBlockType()
}

// Ident gets the identifyer of the block
func (b *Block) Ident() string {
	return b.name
}

// Terminated returns true if the block is terminated (ends in branch or return)
func (b *Block) Terminated() bool {
	return b.instructions[len(b.instructions)-1].IsTerminator()
}

// Add creates a new add instruction.
// lhs and rhs must be integer types of the same size.
// Add returns the result of this instruction with the same type as lhs and rhs.
func (b *Block) Add(lhs value.Value, rhs value.Value) *instructions.Add {
	i := instructions.NewAdd(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// And create a new and instruction.
// lhs and rhs must be boolean types.
// And returns the result of the instruction as a boolean type.
func (b *Block) And(lhs, rhs value.Value) *instructions.And {
	i := instructions.NewAnd(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Br creates a new br instruction.
// block must be a block type.
func (b *Block) Br(block value.Value) *instructions.Br {
	i := instructions.NewBr(b, b.nextName(), block)
	b.instructions = append(b.instructions, i)
	return i
}

// Call creates a new call instruction.
// function must be a function type.
// operands must match the types of the function arguments.
// Call returns the result of the instruction with the same type as the function return type.
func (b *Block) Call(function value.Value, operands ...value.Value) *instructions.Call {
	i := instructions.NewCall(b, b.nextName(), function, operands...)
	b.instructions = append(b.instructions, i)
	return i
}

// CondBr creates a new conditional branch instruction.
// condition must be a boolean type.
// trueBlock and falseBlock must be block types.
func (b *Block) CondBr(condition, trueBlock, falseBlock value.Value) *instructions.CondBr {
	i := instructions.NewCondBr(b, b.nextName(), condition, trueBlock, falseBlock)
	b.instructions = append(b.instructions, i)
	return i
}

// Div creates a new integer division instruction.
// lhs and rhs must be integer types.
// Div returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Div(lhs, rhs value.Value) *instructions.Div {
	i := instructions.NewDiv(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Extractvalue creates a new extract value instruction
// location must be an aggregate type
// position is the index at which to extract the value from location
// Extractvalue returns the type specified in location at index position
func (b *Block) Extractvalue(location value.Value, position value.Value) *instructions.Extractvalue {
	i := instructions.NewExtractvalue(b, b.nextName(), location, position)
	b.instructions = append(b.instructions, i)
	return i
}

// Fadd creates a new float add instruction.
// lhs and rhs must be float or double types.
// Fadd returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Fadd(lhs value.Value, rhs value.Value) *instructions.Fadd {
	i := instructions.NewFadd(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

var (
	// FloatOeq is a float ordered equal comparison
	FloatOeq = "oeq"

	// FloatOlt is a float ordered less than comparison
	FloatOlt = "olt"

	// Float One is a float ordered not equals comparison
	FloatOne = "one"

	// FloatOgt is a float ordered greater than comparison
	FloatOgt = "ogt"
)

// Fcmp creates a new float add instruction.
// mode controls the behavior of the comparison, see https://godoc.org/github.com/bongo227/goory#pkg-variables.
// lhs and rhs must be float or double types.
// Fcmp returns the result of the instruction as a boolean type.
func (b *Block) Fcmp(mode string, lhs, rhs value.Value) *instructions.Fcmp {
	i := instructions.NewFcmp(b, b.nextName(), mode, lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Fdiv creates a new float add instruction.
// lhs and rhs must be float or double types.
// Fdiv returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Fdiv(lhs value.Value, rhs value.Value) *instructions.Fdiv {
	i := instructions.NewFdiv(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Fmul creates a new float add instruction.
// lhs and rhs must be float or double types.
// Fmul returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Fmul(lhs value.Value, rhs value.Value) *instructions.Fmul {
	i := instructions.NewFmul(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Fpext creates a new float extention instruction.
// value must be a float or double type.
// cast must be a type larger than value.
// Fpext returns the result of the instruction with the same type as cast.
func (b *Block) Fpext(value value.Value, cast types.Type) *instructions.Fpext {
	// TODO: add support for fp128 etc
	i := instructions.NewFpext(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Fptosi creates a new float to signed integer type.
// value must be a float of double type.
// cast must be an integer type.
// Fptosi returns the result of the instruction with the same type as cast.
func (b *Block) Fptosi(value value.Value, cast types.Type) *instructions.Fptosi {
	i := instructions.NewFptosi(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Fptrunc creates a new float truncation.
// value must be a float or double type.
// cast must be a type smaller than value.
// Fptrunc returns the result of the instruction with the same type as cast.
func (b *Block) Fptrunc(value value.Value, cast types.Type) *instructions.Fptrunc {
	i := instructions.NewFptrunc(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Fsub creates a new float subtraction instruction.
// lhs and rhs must be float or double types.
// Fsub returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Fsub(lhs value.Value, rhs value.Value) *instructions.Fsub {
	i := instructions.NewFsub(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

var (
	// IntEq is an integer equals comparison
	IntEq = "eq"

	// IntNe is an integer not equals comparison
	IntNe = "ne"

	// IntUlt is an integer unsigned less than comparison
	IntUlt = "ult"

	// IntSlt is an integer signed less than comparison
	IntSlt = "slt"

	// IntUgt is an integer unsigned greater than comparison
	IntUgt = "ugt"

	// IntSgt is an integer signed greater than comparison
	IntSgt = "sgt"
)

// Insertvalue creates a new insert value instruction.
// location must be an aggregate type the value is to be inserted into.
// value must match the type of the location at index position.
// position spesifys the index in which to insert value in location.
// Insertvalue returns the result of the instruction with the same type as location.
func (b *Block) Insertvalue(location, value value.Value, position value.Value) *instructions.Insertvalue {
	i := instructions.NewInsertvalue(b, b.nextName(), location, value, position)
	b.instructions = append(b.instructions, i)
	return i
}

// Icmp creates a new integer comparison instruction.
// mode controls the behavior of the comparison, see: https://godoc.org/github.com/bongo227/goory#pkg-variables.
// lhs and rhs must be integer types of the the same size.
// Icmp returns the result of the instruction as a boolean type.
func (b *Block) Icmp(mode string, lhs, rhs value.Value) *instructions.Icmp {
	i := instructions.NewIcmp(b, b.nextName(), mode, lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Mul creates a new integer multiplication instruction.
// lhs and rhs must be integer types of the the same size.
// Mul returns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Mul(lhs value.Value, rhs value.Value) *instructions.Mul {
	i := instructions.NewMul(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Or creates a new bitwise or instruction.
// lhs and rhs must be boolean types.
// Or returns the result of the instruction as a boolean type.
func (b *Block) Or(lhs value.Value, rhs value.Value) *instructions.Or {
	i := instructions.NewOr(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Phi creates a new phi instruction.
// Phi returns the phi instruction to which you add all incoming blocks.
func (b *Block) Phi() *instructions.Phi {
	i := instructions.NewPhi(b, b.nextName())
	b.instructions = append(b.instructions, i)
	return i
}

// Ret creates a new return instruction.
// value must be the same type as the function return type.
func (b *Block) Ret(value value.Value) *instructions.Ret {
	i := instructions.NewRet(b, value)
	b.instructions = append(b.instructions, i)
	return i
}

// Sitofp creates a new signed integer to float instruction.
// value must be an integer type.
// cast must be a float type.
// Sitofp returns the result of the instruction with the same type as cast.
func (b *Block) Sitofp(value value.Value, cast types.Type) *instructions.Sitofp {
	i := instructions.NewSitofp(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Sub creates a new float sub instruction.
// lhs and rhs must be float or double types.
// Sub retruns the result of the instruction with the same type as lhs and rhs.
func (b *Block) Sub(lhs value.Value, rhs value.Value) *instructions.Sub {
	i := instructions.NewSub(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Trunc creates a new integer truncation instruction.
// value must be an integer type.
// cast must be a integer type smaller than value.
// Trunc returns the result of the instruction with the same type as cast.
func (b *Block) Trunc(value value.Value, cast types.Type) *instructions.Trunc {
	i := instructions.NewTrunc(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Xor creates a new float exclusive or instruction.
// lhs and rhs must be boolean types.
// Xor returns the result of the instruction as a boolean type.
func (b *Block) Xor(lhs value.Value, rhs value.Value) *instructions.Xor {
	i := instructions.NewXor(b, b.nextName(), lhs, rhs)
	b.instructions = append(b.instructions, i)
	return i
}

// Zext creates a new zero extention instruction.
// value must be an integer type.
// cast must be a integer type larger than value.
// Zext returns the result of the instruction with the same type as cast.
func (b *Block) Zext(value value.Value, cast types.Type) *instructions.Zext {
	i := instructions.NewZext(b, b.nextName(), value, cast)
	b.instructions = append(b.instructions, i)
	return i
}

// Cast creates a cast for value to type cast
func (b *Block) Cast(value value.Value, cast types.Type) value.Value {
	atomicCast, isAtomicCast := cast.(types.Atomic)
	if !isAtomicCast {
		panic("Cast is not atomic")
	}

	atomic, isAtomic := value.Type().(types.Atomic)
	if !isAtomic {
		panic("Value is not an atomic type")
	}

	// Value type is the same as cast type so return the value
	if atomic.Equal(atomicCast) {
		return value
	}

	// Cast integer to integer
	if types.IsInteger(atomic) && types.IsInteger(atomicCast) {
		if types.Compare(atomic, atomicCast) == -1 {
			// Cast is bigger so expand value
			i := instructions.NewZext(b, b.nextName(), value, atomicCast)
			b.instructions = append(b.instructions, i)
			return i
		}
		// Cast is smaller so truncate value
		i := instructions.NewTrunc(b, b.nextName(), value, atomicCast)
		b.instructions = append(b.instructions, i)
		return i
	}

	// Cast float to float
	if types.IsFp(atomic) && types.IsFp(atomicCast){
		if types.Compare(atomic, atomicCast) == -1 {
			// Cast is bigger so expand value
			i := instructions.NewFpext(b, b.nextName(), value, atomicCast)
			b.instructions = append(b.instructions, i)
			return i
		}
		// Cast is smaller so truncate value
		i := instructions.NewFptrunc(b, b.nextName(), value, atomicCast)
		b.instructions = append(b.instructions, i)
		return i
	}

	// Cast integer to float
	if types.IsInteger(atomic) && types.IsFp(atomicCast) {
		i := instructions.NewSitofp(b, b.nextName(), value, atomicCast)
		b.instructions = append(b.instructions, i)
		return i
	}

	// Cast float to integer
	if types.IsFp(atomic) && types.IsInteger(atomicCast) {
		i := instructions.NewFptosi(b, b.nextName(), value, atomicCast)
		b.instructions = append(b.instructions, i)
		return i
	}

	panic("Cannot cast non integer or pointer value")
}

<|endoftext|>


<commit_before>package bogus

import (
	"net"
	"net/http"
	"net/http/httptest"
)

type Bogus struct {
	server  *httptest.Server
	hits    int
	payload string
	status  int
}

func New() *Bogus {
	return &Bogus{}
}

func (b *Bogus) Hits() int {
	return b.hits
}

func (b *Bogus) HostPort() (string, string) {
	h, p, _ := net.SplitHostPort(b.server.URL[7:])
	return h, p
}

func (b *Bogus) SetPayload(r string) {
	b.payload = r
}

func (b *Bogus) SetStatus(s int) {
	b.status = s
}

func (b *Bogus) Start() {
	b.server = httptest.NewServer(
		http.HandlerFunc(
			func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(b.status)
				b.hits++
				w.Write([]byte(b.payload))
			}))
}
<commit_msg>adding close func<commit_after>package bogus

import (
	"net"
	"net/http"
	"net/http/httptest"
)

type Bogus struct {
	server  *httptest.Server
	hits    int
	payload string
	status  int
}

func New() *Bogus {
	return &Bogus{}
}

func (b *Bogus) Close() {
	b.server.Close()
}

func (b *Bogus) Hits() int {
	return b.hits
}

func (b *Bogus) HostPort() (string, string) {
	h, p, _ := net.SplitHostPort(b.server.URL[7:])
	return h, p
}

func (b *Bogus) SetPayload(r string) {
	b.payload = r
}

func (b *Bogus) SetStatus(s int) {
	b.status = s
}

func (b *Bogus) Start() {
	b.server = httptest.NewServer(
		http.HandlerFunc(
			func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(b.status)
				b.hits++
				w.Write([]byte(b.payload))
			}))
}
<|endoftext|>


<commit_before>// Copyright 2021 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tracing

import (
	"context"
	"reflect"
	"time"

	"github.com/go-kit/log"
	"github.com/go-kit/log/level"
	"github.com/pkg/errors"
	config_util "github.com/prometheus/common/config"
	"github.com/prometheus/common/version"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
	"go.opentelemetry.io/otel/propagation"
	"go.opentelemetry.io/otel/sdk/resource"
	tracesdk "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
	"go.opentelemetry.io/otel/trace"
	"google.golang.org/grpc/credentials"

	"github.com/prometheus/prometheus/config"
)

const serviceName = "prometheus"

// Manager is capable of building, (re)installing and shutting down
// the tracer provider.
type Manager struct {
	logger       log.Logger
	done         chan struct{}
	config       config.TracingConfig
	shutdownFunc func() error
}

// NewManager creates a new tracing manager.
func NewManager(logger log.Logger) *Manager {
	return &Manager{
		logger: logger,
		done:   make(chan struct{}),
	}
}

// Run starts the tracing manager. It registers the global text map propagator and error handler.
// It is blocking.
func (m *Manager) Run() {
	otel.SetTextMapPropagator(propagation.TraceContext{})
	otel.SetErrorHandler(otelErrHandler(func(err error) {
		level.Error(m.logger).Log("msg", "OpenTelemetry handler returned an error", "err", err)
	}))
	<-m.done
}

// ApplyConfig takes care of refreshing the tracing configuration by shutting down
// the current tracer provider (if any is registered) and installing a new one.
func (m *Manager) ApplyConfig(cfg *config.Config) error {
	// Update only if a config change is detected. If TLS configuration is
	// set, we have to restart the manager to make sure that new TLS
	// certificates are picked up.
	var blankTLSConfig config_util.TLSConfig
	if reflect.DeepEqual(m.config, cfg.TracingConfig) && m.config.TLSConfig == blankTLSConfig {
		return nil
	}

	if m.shutdownFunc != nil {
		if err := m.shutdownFunc(); err != nil {
			return errors.Wrap(err, "failed to shut down the tracer provider")
		}
	}

	// If no endpoint is set, assume tracing should be disabled.
	if cfg.TracingConfig.Endpoint == "" {
		m.config = cfg.TracingConfig
		m.shutdownFunc = nil
		otel.SetTracerProvider(trace.NewNoopTracerProvider())
		level.Info(m.logger).Log("msg", "Tracing provider uninstalled.")
		return nil
	}

	tp, shutdownFunc, err := buildTracerProvider(context.Background(), cfg.TracingConfig)
	if err != nil {
		return errors.Wrap(err, "failed to install a new tracer provider")
	}

	m.shutdownFunc = shutdownFunc
	m.config = cfg.TracingConfig
	otel.SetTracerProvider(tp)

	level.Info(m.logger).Log("msg", "Successfully installed a new tracer provider.")
	return nil
}

// Stop gracefully shuts down the tracer provider and stops the tracing manager.
func (m *Manager) Stop() {
	defer close(m.done)

	if m.shutdownFunc == nil {
		return
	}

	if err := m.shutdownFunc(); err != nil {
		level.Error(m.logger).Log("msg", "failed to shut down the tracer provider", "err", err)
	}

	level.Info(m.logger).Log("msg", "Tracing manager stopped")
}

type otelErrHandler func(err error)

func (o otelErrHandler) Handle(err error) {
	o(err)
}

// buildTracerProvider return a new tracer provider ready for installation, together
// with a shutdown function.
func buildTracerProvider(ctx context.Context, tracingCfg config.TracingConfig) (trace.TracerProvider, func() error, error) {
	client, err := getClient(tracingCfg)
	if err != nil {
		return nil, nil, err
	}

	exp, err := otlptrace.New(ctx, client)
	if err != nil {
		return nil, nil, err
	}

	// Create a resource describing the service and the runtime.
	res, err := resource.New(
		ctx,
		resource.WithSchemaURL(semconv.SchemaURL),
		resource.WithAttributes(
			semconv.ServiceNameKey.String(serviceName),
			semconv.ServiceVersionKey.String(version.Version),
		),
		resource.WithProcessRuntimeDescription(),
		resource.WithTelemetrySDK(),
	)
	if err != nil {
		return nil, nil, err
	}

	tp := tracesdk.NewTracerProvider(
		tracesdk.WithBatcher(exp),
		tracesdk.WithSampler(tracesdk.ParentBased(
			tracesdk.TraceIDRatioBased(tracingCfg.SamplingFraction),
		)),
		tracesdk.WithResource(res),
	)

	return tp, func() error {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		err := tp.Shutdown(ctx)
		if err != nil {
			return err
		}

		return nil
	}, nil
}

// getClient returns an appropriate OTLP client (either gRPC or HTTP), based
// on the provided tracing configuration.
func getClient(tracingCfg config.TracingConfig) (otlptrace.Client, error) {
	var client otlptrace.Client
	switch tracingCfg.ClientType {
	case config.TracingClientGRPC:
		opts := []otlptracegrpc.Option{otlptracegrpc.WithEndpoint(tracingCfg.Endpoint)}
		if tracingCfg.Insecure {
			opts = append(opts, otlptracegrpc.WithInsecure())
		}
		if tracingCfg.Compression != "" {
			opts = append(opts, otlptracegrpc.WithCompressor(tracingCfg.Compression))
		}
		if len(tracingCfg.Headers) != 0 {
			opts = append(opts, otlptracegrpc.WithHeaders(tracingCfg.Headers))
		}
		if tracingCfg.Timeout != 0 {
			opts = append(opts, otlptracegrpc.WithTimeout(time.Duration(tracingCfg.Timeout)))
		}

		tlsConf, err := config_util.NewTLSConfig(&tracingCfg.TLSConfig)
		if err != nil {
			return nil, err
		}
		opts = append(opts, otlptracegrpc.WithTLSCredentials(credentials.NewTLS(tlsConf)))

		client = otlptracegrpc.NewClient(opts...)
	case config.TracingClientHTTP:
		opts := []otlptracehttp.Option{otlptracehttp.WithEndpoint(tracingCfg.Endpoint)}
		if tracingCfg.Insecure {
			opts = append(opts, otlptracehttp.WithInsecure())
		}
		// Currently, OTEL supports only gzip compression.
		if tracingCfg.Compression == config.GzipCompression {
			opts = append(opts, otlptracehttp.WithCompression(otlptracehttp.GzipCompression))
		}
		if len(tracingCfg.Headers) != 0 {
			opts = append(opts, otlptracehttp.WithHeaders(tracingCfg.Headers))
		}
		if tracingCfg.Timeout != 0 {
			opts = append(opts, otlptracehttp.WithTimeout(time.Duration(tracingCfg.Timeout)))
		}

		tlsConf, err := config_util.NewTLSConfig(&tracingCfg.TLSConfig)
		if err != nil {
			return nil, err
		}
		opts = append(opts, otlptracehttp.WithTLSClientConfig(tlsConf))

		client = otlptracehttp.NewClient(opts...)
	}

	return client, nil
}
<commit_msg>Tracing/GRPC: Set TLS credentials only when insecure is false.<commit_after>// Copyright 2021 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tracing

import (
	"context"
	"reflect"
	"time"

	"github.com/go-kit/log"
	"github.com/go-kit/log/level"
	"github.com/pkg/errors"
	config_util "github.com/prometheus/common/config"
	"github.com/prometheus/common/version"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
	"go.opentelemetry.io/otel/propagation"
	"go.opentelemetry.io/otel/sdk/resource"
	tracesdk "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
	"go.opentelemetry.io/otel/trace"
	"google.golang.org/grpc/credentials"

	"github.com/prometheus/prometheus/config"
)

const serviceName = "prometheus"

// Manager is capable of building, (re)installing and shutting down
// the tracer provider.
type Manager struct {
	logger       log.Logger
	done         chan struct{}
	config       config.TracingConfig
	shutdownFunc func() error
}

// NewManager creates a new tracing manager.
func NewManager(logger log.Logger) *Manager {
	return &Manager{
		logger: logger,
		done:   make(chan struct{}),
	}
}

// Run starts the tracing manager. It registers the global text map propagator and error handler.
// It is blocking.
func (m *Manager) Run() {
	otel.SetTextMapPropagator(propagation.TraceContext{})
	otel.SetErrorHandler(otelErrHandler(func(err error) {
		level.Error(m.logger).Log("msg", "OpenTelemetry handler returned an error", "err", err)
	}))
	<-m.done
}

// ApplyConfig takes care of refreshing the tracing configuration by shutting down
// the current tracer provider (if any is registered) and installing a new one.
func (m *Manager) ApplyConfig(cfg *config.Config) error {
	// Update only if a config change is detected. If TLS configuration is
	// set, we have to restart the manager to make sure that new TLS
	// certificates are picked up.
	var blankTLSConfig config_util.TLSConfig
	if reflect.DeepEqual(m.config, cfg.TracingConfig) && m.config.TLSConfig == blankTLSConfig {
		return nil
	}

	if m.shutdownFunc != nil {
		if err := m.shutdownFunc(); err != nil {
			return errors.Wrap(err, "failed to shut down the tracer provider")
		}
	}

	// If no endpoint is set, assume tracing should be disabled.
	if cfg.TracingConfig.Endpoint == "" {
		m.config = cfg.TracingConfig
		m.shutdownFunc = nil
		otel.SetTracerProvider(trace.NewNoopTracerProvider())
		level.Info(m.logger).Log("msg", "Tracing provider uninstalled.")
		return nil
	}

	tp, shutdownFunc, err := buildTracerProvider(context.Background(), cfg.TracingConfig)
	if err != nil {
		return errors.Wrap(err, "failed to install a new tracer provider")
	}

	m.shutdownFunc = shutdownFunc
	m.config = cfg.TracingConfig
	otel.SetTracerProvider(tp)

	level.Info(m.logger).Log("msg", "Successfully installed a new tracer provider.")
	return nil
}

// Stop gracefully shuts down the tracer provider and stops the tracing manager.
func (m *Manager) Stop() {
	defer close(m.done)

	if m.shutdownFunc == nil {
		return
	}

	if err := m.shutdownFunc(); err != nil {
		level.Error(m.logger).Log("msg", "failed to shut down the tracer provider", "err", err)
	}

	level.Info(m.logger).Log("msg", "Tracing manager stopped")
}

type otelErrHandler func(err error)

func (o otelErrHandler) Handle(err error) {
	o(err)
}

// buildTracerProvider return a new tracer provider ready for installation, together
// with a shutdown function.
func buildTracerProvider(ctx context.Context, tracingCfg config.TracingConfig) (trace.TracerProvider, func() error, error) {
	client, err := getClient(tracingCfg)
	if err != nil {
		return nil, nil, err
	}

	exp, err := otlptrace.New(ctx, client)
	if err != nil {
		return nil, nil, err
	}

	// Create a resource describing the service and the runtime.
	res, err := resource.New(
		ctx,
		resource.WithSchemaURL(semconv.SchemaURL),
		resource.WithAttributes(
			semconv.ServiceNameKey.String(serviceName),
			semconv.ServiceVersionKey.String(version.Version),
		),
		resource.WithProcessRuntimeDescription(),
		resource.WithTelemetrySDK(),
	)
	if err != nil {
		return nil, nil, err
	}

	tp := tracesdk.NewTracerProvider(
		tracesdk.WithBatcher(exp),
		tracesdk.WithSampler(tracesdk.ParentBased(
			tracesdk.TraceIDRatioBased(tracingCfg.SamplingFraction),
		)),
		tracesdk.WithResource(res),
	)

	return tp, func() error {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		err := tp.Shutdown(ctx)
		if err != nil {
			return err
		}

		return nil
	}, nil
}

// getClient returns an appropriate OTLP client (either gRPC or HTTP), based
// on the provided tracing configuration.
func getClient(tracingCfg config.TracingConfig) (otlptrace.Client, error) {
	var client otlptrace.Client
	switch tracingCfg.ClientType {
	case config.TracingClientGRPC:
		opts := []otlptracegrpc.Option{otlptracegrpc.WithEndpoint(tracingCfg.Endpoint)}
		if tracingCfg.Insecure {
			opts = append(opts, otlptracegrpc.WithInsecure())
		} else {
			// Use of TLS Credentials forces the use of TLS. Therefore it can
			// only be set when `insecure` is set to false.
			tlsConf, err := config_util.NewTLSConfig(&tracingCfg.TLSConfig)
			if err != nil {
				return nil, err
			}
			opts = append(opts, otlptracegrpc.WithTLSCredentials(credentials.NewTLS(tlsConf)))
		}
		if tracingCfg.Compression != "" {
			opts = append(opts, otlptracegrpc.WithCompressor(tracingCfg.Compression))
		}
		if len(tracingCfg.Headers) != 0 {
			opts = append(opts, otlptracegrpc.WithHeaders(tracingCfg.Headers))
		}
		if tracingCfg.Timeout != 0 {
			opts = append(opts, otlptracegrpc.WithTimeout(time.Duration(tracingCfg.Timeout)))
		}

		client = otlptracegrpc.NewClient(opts...)
	case config.TracingClientHTTP:
		opts := []otlptracehttp.Option{otlptracehttp.WithEndpoint(tracingCfg.Endpoint)}
		if tracingCfg.Insecure {
			opts = append(opts, otlptracehttp.WithInsecure())
		}
		// Currently, OTEL supports only gzip compression.
		if tracingCfg.Compression == config.GzipCompression {
			opts = append(opts, otlptracehttp.WithCompression(otlptracehttp.GzipCompression))
		}
		if len(tracingCfg.Headers) != 0 {
			opts = append(opts, otlptracehttp.WithHeaders(tracingCfg.Headers))
		}
		if tracingCfg.Timeout != 0 {
			opts = append(opts, otlptracehttp.WithTimeout(time.Duration(tracingCfg.Timeout)))
		}

		tlsConf, err := config_util.NewTLSConfig(&tracingCfg.TLSConfig)
		if err != nil {
			return nil, err
		}
		opts = append(opts, otlptracehttp.WithTLSClientConfig(tlsConf))

		client = otlptracehttp.NewClient(opts...)
	}

	return client, nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"database/sql"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/clockworkcoding/goodreads"
	"github.com/demisto/slack"
	_ "github.com/lib/pq"
	"golang.org/x/oauth2"
	"log"
	"net/http"
	"os"
	"time"
)

var (
	db     *sql.DB
	config Configuration
)

type state struct {
	auth string
	ts   time.Time
}

// globalState is an example of how to store a state between calls
var globalState state

// writeError writes an error to the reply - example only
func writeError(w http.ResponseWriter, status int, err string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	w.Write([]byte(err))
}

// addToSlack initializes the oauth process and redirects to Slack
func addToSlack(w http.ResponseWriter, r *http.Request) {
	// Just generate random state
	b := make([]byte, 10)
	_, err := rand.Read(b)
	if err != nil {
		writeError(w, 500, err.Error())
	}
	globalState = state{auth: hex.EncodeToString(b), ts: time.Now()}
	conf := &oauth2.Config{
		ClientID:     config.Slack.ClientID,
		ClientSecret: config.Slack.ClientSecret,
		Scopes:       []string{"client"},
		Endpoint: oauth2.Endpoint{
			AuthURL:  "https://slack.com/oauth/authorize",
			TokenURL: "https://slack.com/api/oauth.access", // not actually used here
		},
	}
	url := conf.AuthCodeURL(globalState.auth)
	http.Redirect(w, r, url, http.StatusFound)
}

// auth receives the callback from Slack, validates and displays the user information
func auth(w http.ResponseWriter, r *http.Request) {
	state := r.FormValue("state")
	code := r.FormValue("code")
	errStr := r.FormValue("error")
	if errStr != "" {
		writeError(w, 401, errStr)
		return
	}
	if state == "" || code == "" {
		writeError(w, 400, "Missing state or code")
		return
	}
	if state != globalState.auth {
		writeError(w, 403, "State does not match")
		return
	}
	// As an example, we allow only 5 min between requests
	if time.Since(globalState.ts) > 5*time.Minute {
		writeError(w, 403, "State is too old")
		return
	}
	token, err := slack.OAuthAccess(config.Slack.ClientID, config.Slack.ClientSecret, code, "")
	if err != nil {
		writeError(w, 401, err.Error())
		return
	}
	s, err := slack.New(slack.SetToken(token.AccessToken))
	if err != nil {
		writeError(w, 500, err.Error())
		return
	}
	// Get our own user id
	test, err := s.AuthTest()
	if err != nil {
		writeError(w, 500, err.Error())
		return
	}
	w.Write([]byte(fmt.Sprintf("OAuth successful for team %s and user %s", test.Team, test.User)))
}

// home displays the add-to-slack button
func home(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(`<html><head><title>Slack OAuth Test</title></head><body><a href="/add">Add To Slack</a></body></html>`))
}

type Configuration struct {
	Goodreads struct {
		Key    string `json:"Key"`
		Secret string `json:"Secret"`
	} `json:"Goodreads"`
	Slack struct {
		ClientID     string `json:"ClientID"`
		ClientSecret string `json:"ClientSecret"`
	} `json:"slack"`
	Db struct {
		URI string `json:"URI"`
	} `json:"db"`
}

func main() {
	gr := goodreads.NewClient(config.Goodreads.Key, config.Goodreads.Secret)
	results, err := gr.GetSearch("Collapsing Empire")
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	book, err := gr.GetBook(results.Search_work[0].Search_best_book.Search_id.Text)
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	db, err = sql.Open("postgres", config.Db.URI)
	if err != nil {
		log.Fatalf("Error opening database: %q", err)
	}

	fmt.Println(book.Book_title[0].Text)
	fmt.Println(book.Book_description.Text)

	http.HandleFunc("/dbfunc", dbFunc)
	http.HandleFunc("/add", addToSlack)
	http.HandleFunc("/auth", auth)
	http.HandleFunc("/", home)
	log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil))

}

func dbFunc(w http.ResponseWriter, r *http.Request) {
	if _, err := db.Exec("CREATE TABLE IF NOT EXISTS ticks (tick timestamp)"); err != nil {
		writeError(w, 500, "Error creating database table: "+err.Error())
		return
	}

	if _, err := db.Exec("INSERT INTO ticks VALUES (now())"); err != nil {
		writeError(w, 500, "Error incrementing tick: "+err.Error())
		return
	}

	rows, err := db.Query("SELECT tick FROM ticks")
	if err != nil {
		writeError(w, 500, "Error reading ticks: "+err.Error())
		return
	}

	defer rows.Close()
	for rows.Next() {
		var tick time.Time
		if err := rows.Scan(&tick); err != nil {
			writeError(w, 500, "Error scanning ticks:"+err.Error())
			return
		}
		w.Write([]byte(fmt.Sprintf("Read from DB: %s\n", tick.String())))
	}
}

func init() {
	config = readConfig()
}

func readConfig() Configuration {
	configuration := Configuration{}

	if configuration.Slack.ClientID = os.Getenv("slackClientID"); configuration.Slack.ClientID != "" {
		configuration.Slack.ClientSecret = os.Getenv("slackClientSecret")
		configuration.Goodreads.Secret = os.Getenv("goodReadsSecret")
		configuration.Goodreads.Key = os.Getenv("goodReadsKey")
		configuration.Db.URI = os.Getenv("DATABASE_URL")
	} else {
		file, _ := os.Open("conf.json")
		decoder := json.NewDecoder(file)
		err := decoder.Decode(&configuration)
		if err != nil {
			fmt.Println("error:", err)
		}
	}
	return configuration
}
<commit_msg>now accepting oauth from slack<commit_after>package main

import (
	"crypto/rand"
	"database/sql"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/clockworkcoding/goodreads"
	_ "github.com/lib/pq"
	"github.com/nlopes/slack"
	"golang.org/x/oauth2"
	"log"
	"net/http"
	"os"
	"time"
)

var (
	db     *sql.DB
	config Configuration
)

type state struct {
	auth string
	ts   time.Time
}

// globalState is an example of how to store a state between calls
var globalState state

// writeError writes an error to the reply - example only
func writeError(w http.ResponseWriter, status int, err string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	w.Write([]byte(err))
}

// addToSlack initializes the oauth process and redirects to Slack
func addToSlack(w http.ResponseWriter, r *http.Request) {
	// Just generate random state
	b := make([]byte, 10)
	_, err := rand.Read(b)
	if err != nil {
		writeError(w, 500, err.Error())
	}
	globalState = state{auth: hex.EncodeToString(b), ts: time.Now()}
	conf := &oauth2.Config{
		ClientID:     config.Slack.ClientID,
		ClientSecret: config.Slack.ClientSecret,
		Scopes:       []string{"channels:history", "incoming-webhook"},
		Endpoint: oauth2.Endpoint{
			AuthURL:  "https://slack.com/oauth/authorize",
			TokenURL: "https://slack.com/api/oauth.access", // not actually used here
		},
	}
	url := conf.AuthCodeURL(globalState.auth)
	http.Redirect(w, r, url, http.StatusFound)
}

// auth receives the callback from Slack, validates and displays the user information
func auth(w http.ResponseWriter, r *http.Request) {
	state := r.FormValue("state")
	code := r.FormValue("code")
	errStr := r.FormValue("error")
	if errStr != "" {
		writeError(w, 401, errStr)
		return
	}
	if state == "" || code == "" {
		writeError(w, 400, "Missing state or code")
		return
	}
	if state != globalState.auth {
		writeError(w, 403, "State does not match")
		return
	}
	// As an example, we allow only 5 min between requests
	if time.Since(globalState.ts) > 5*time.Minute {
		writeError(w, 403, "State is too old")
		return
	}
	oAuthResponse, err := slack.GetOAuthResponse(config.Slack.ClientID, config.Slack.ClientSecret, code, "", false)
	if err != nil {
		writeError(w, 401, err.Error())
		return
	}
	fmt.Println(oAuthResponse.IncomingWebhook.Channel)

	w.Write([]byte(fmt.Sprintf("OAuth successful for team %s and user %s", oAuthResponse.TeamName, oAuthResponse.UserID)))
	saveSlackAuth(oAuthResponse)

}

// home displays the add-to-slack button
func home(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(`<html><head><title>Slack OAuth Test</title></head><body><a href="/add">Add To Slack</a></body></html>`))
}

type Challenge struct {
	Token     string `json:"token"`
	Challenge string `json:"challenge"`
	Type      string `json:"type"`
}

// event responds to events from slack
func event(w http.ResponseWriter, r *http.Request) {
	fmt.Println("event reached")
	decoder := json.NewDecoder(r.Body)

	var challenge Challenge
	err := decoder.Decode(&challenge)
	if err != nil {
		fmt.Println("ERR: " + err.Error())
	}
	defer r.Body.Close()
	fmt.Println(challenge.Challenge)

	w.Write([]byte(challenge.Challenge))
}

type Configuration struct {
	Goodreads struct {
		Key    string `json:"Key"`
		Secret string `json:"Secret"`
	} `json:"Goodreads"`
	Slack struct {
		ClientID          string `json:"ClientID"`
		ClientSecret      string `json:"ClientSecret"`
		VerificationToken string `json:"VerificationToken"`
	} `json:"slack"`
	Db struct {
		URI string `json:"URI"`
	} `json:"db"`
}

func main() {
	gr := goodreads.NewClient(config.Goodreads.Key, config.Goodreads.Secret)

	results, err := gr.GetSearch("Collapsing Empire")
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	_, err = gr.GetBook(results.Search_work[0].Search_best_book.Search_id.Text)
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	db, err = sql.Open("postgres", config.Db.URI)
	if err != nil {
		log.Fatalf("Error opening database: %q", err)
	}

	//fmt.Println(book.Book_title[0].Text)
	//fmt.Println(book.Book_description.Text)

	http.HandleFunc("/dbfunc", dbFunc)
	http.HandleFunc("/add", addToSlack)
	http.HandleFunc("/auth", auth)
	http.HandleFunc("/event", event)
	http.HandleFunc("/", home)
	log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil))

}

func saveSlackAuth(oAuth *slack.OAuthResponse) {

	if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS slack_auth (
		team varchar(200),
		teamid varchar(20),
		token varchar(200),
		url varchar(200),
		configUrl varchar(200),
		channel varchar(200),
		channelid varchar(200),
		createdtime	timestamp
		)`); err != nil {
		fmt.Println("Error creating database table: " + err.Error())
		return
	}

	if _, err := db.Exec(fmt.Sprintf("INSERT INTO slack_auth VALUES ('%s','%s','%s','%s','%s','%s','%s, now()')", oAuth.TeamName, oAuth.TeamID,
		oAuth.AccessToken, oAuth.IncomingWebhook.URL, oAuth.IncomingWebhook.ConfigurationURL, oAuth.IncomingWebhook.Channel, oAuth.IncomingWebhook.ChannelID)); err != nil {
		fmt.Println("Error incrementing tick: " + err.Error())
		return
	}

	rows, err := db.Query("SELECT * FROM slack_auth")
	if err != nil {
		fmt.Println("Error reading ticks: " + err.Error())
		return
	}
	defer rows.Close()
	for rows.Next() {
		var a, b, c, d, e, f, g string
		if err := rows.Scan(&a, &b, &c, &d, &e, &f, &g); err != nil {
			fmt.Println("Error scanning ticks:" + err.Error())
			return
		}
		fmt.Printf("Read from DB: %s - %s - %s - %s - %s - %s - %s\n", a, b, c, d, e, f, g)
	}
}
func dbFunc(w http.ResponseWriter, r *http.Request) {

	if _, err := db.Exec("DROP TABLE IF EXISTS slack_auth"); err != nil {
		fmt.Println("Error creating database table: " + err.Error())
		return
	}
	w.Write([]byte(fmt.Sprintf("Table Dropped")))
}

func init() {
	config = readConfig()
}

func readConfig() Configuration {
	configuration := Configuration{}

	if configuration.Slack.ClientID = os.Getenv("SLACK_CLIENT_ID"); configuration.Slack.ClientID != "" {
		configuration.Slack.ClientSecret = os.Getenv("SLACK_CLIENT_SECRET")
		configuration.Goodreads.Secret = os.Getenv("GOODREADS_SECRET")
		configuration.Goodreads.Key = os.Getenv("GOODREADS_KEY")
		configuration.Db.URI = os.Getenv("DATABASE_URL")
		configuration.Slack.VerificationToken = os.Getenv("SLACK_VERIFICATION_TOKEN")
	} else {
		file, _ := os.Open("conf.json")
		decoder := json.NewDecoder(file)
		err := decoder.Decode(&configuration)
		if err != nil {
			fmt.Println("error:", err)
		}
	}
	return configuration
}
<|endoftext|>


<commit_before>// Copyright or whatever, Roger Booth (roger.booth@gmail.com)
// In the unlikely event that you find this code useful,
// feel free to provide attribution :)
package main

import (
	"container/ring"
	"fmt"
)

type Color string

var colors = [...]Color{"white", "blue", "red", "yellow", "orange", "green"}
var edgesForFace = map[Color][]Color{
	"white":  {"red", "green", "orange", "blue"},
	"blue":   {"white", "orange", "yellow", "red"},
	"red":    {"blue", "yellow", "green", "white"},
	"yellow": {"green", "red", "blue", "orange"},
	"orange": {"yellow", "blue", "white", "green"},
	"green":  {"orange", "white", "red", "yellow"},
}

var edgePos = [...]int{0, 1, 2, 4, 3, 2, 4, 5, 6, 6, 7, 0}

type Face [8]Color

type Edge [12]*Color

type Cube struct {
	faceMap map[Color]*Face
	edgeMap map[Color]Edge
}

func NewCube() (*Cube, error) {
	newFaceMap := make(map[Color]*Face)
	newEdgeMap := make(map[Color]Edge)
	for _, color := range colors {
		newFaceMap[color] = &Face{color, color, color, color, color, color, color, color}
	}
	i := 0
	for _, faceColor := range colors {
		var newEdge Edge
		for _, edgeColor := range edgesForFace[faceColor] {
		        //fmt.Println(faceColor)
		        //fmt.Println(i)
			newEdge[i] = &newFaceMap[edgeColor][edgePos[i]]
			newEdge[i+1] = &newFaceMap[edgeColor][edgePos[i+1]]
			newEdge[i+2] = &newFaceMap[edgeColor][edgePos[i+2]]
			i += 3
			if i == 12 {
			    i = 0
			}
		}
		newEdgeMap[faceColor] = newEdge
	}
	return &Cube{newFaceMap, newEdgeMap}, nil
}

type ThreeDTransformer struct {
	faceRing ring.Ring
	edgeRing ring.Ring
}

func main() {
	cube1,_ := NewCube()

	//fmt.Println(cube1)
	fmt.Println(cube1.faceMap["red"][1])
	fmt.Println(cube1.faceMap["red"][2])
	fmt.Println(*cube1.edgeMap["red"][2])
	fmt.Println(*cube1.edgeMap["red"][3])
	fmt.Println(*cube1.edgeMap["red"][8])
	fmt.Println(*cube1.edgeMap["red"][11])
}
<commit_msg>Coordinates were wrong.<commit_after>// Copyright or whatever, Roger Booth (roger.booth@gmail.com)
// In the unlikely event that you find this code useful,
// feel free to provide attribution :)
package main

import (
	"container/ring"
	"fmt"
)

type Color string

var colors = [...]Color{"white", "blue", "red", "yellow", "orange", "green"}
var edgesForFace = map[Color][]Color{
	"white":  {"red", "green", "orange", "blue"},
	"blue":   {"white", "orange", "yellow", "red"},
	"red":    {"blue", "yellow", "green", "white"},
	"yellow": {"green", "red", "blue", "orange"},
	"orange": {"yellow", "blue", "white", "green"},
	"green":  {"orange", "white", "red", "yellow"},
}

var edgePos = [...]int{0, 7, 6, 4, 3, 2, 6, 5, 4, 2, 1, 0}

type Face [8]Color

type Edge [12]*Color

type Cube struct {
	faceMap map[Color]*Face
	edgeMap map[Color]Edge
}

func NewCube() (*Cube, error) {
	newFaceMap := make(map[Color]*Face)
	newEdgeMap := make(map[Color]Edge)
	for _, color := range colors {
		newFaceMap[color] = &Face{color, color, color, color, color, color, color, color}
	}
	i := 0
	for _, faceColor := range colors {
		var newEdge Edge
		for _, edgeColor := range edgesForFace[faceColor] {
		        //fmt.Println(faceColor)
		        //fmt.Println(i)
			newEdge[i] = &newFaceMap[edgeColor][edgePos[i]]
			newEdge[i+1] = &newFaceMap[edgeColor][edgePos[i+1]]
			newEdge[i+2] = &newFaceMap[edgeColor][edgePos[i+2]]
			i += 3
			if i == 12 {
			    i = 0
			}
		}
		newEdgeMap[faceColor] = newEdge
	}
	return &Cube{newFaceMap, newEdgeMap}, nil
}

type ThreeDTransformer struct {
	faceRing ring.Ring
	edgeRing ring.Ring
}

func main() {
	cube1,_ := NewCube()

	//fmt.Println(cube1)
	fmt.Println(cube1.faceMap["red"][1])
	fmt.Println(cube1.faceMap["red"][2])
	fmt.Println(*cube1.edgeMap["red"][2])
	fmt.Println(*cube1.edgeMap["red"][3])
	fmt.Println(*cube1.edgeMap["red"][8])
	fmt.Println(*cube1.edgeMap["red"][11])
}
<|endoftext|>