Skip to content
Snippets Groups Projects
curl.go 1.95 KiB
Newer Older
package curl

import (
capossele's avatar
capossele committed
	"math"

Wolfgang Welz's avatar
Wolfgang Welz committed
	"github.com/iotaledger/iota.go/trinary"
capossele's avatar
capossele committed
	HASH_LENGTH  = 243
Wolfgang Welz's avatar
Wolfgang Welz committed
	STATE_LENGTH = 3 * HASH_LENGTH
Wolfgang Welz's avatar
Wolfgang Welz committed
	TRUTH_TABLE = trinary.Trits{1, 0, -1, 2, 1, -1, 0, 2, -1, 1, 0}
)

type Hash interface {
capossele's avatar
capossele committed
	Initialize()
	InitializeCurl(trits *[]int8, length int, rounds int)
	Reset()
	Absorb(trits *[]int8, offset int, length int)
	Squeeze(resp []int8, offset int, length int) []int
capossele's avatar
capossele committed
	Hash
Wolfgang Welz's avatar
Wolfgang Welz committed
	state      trinary.Trits
capossele's avatar
capossele committed
	hashLength int
	rounds     int
}

func NewCurl(hashLength int, rounds int) *Curl {
capossele's avatar
capossele committed
	this := &Curl{
		hashLength: hashLength,
		rounds:     rounds,
	}
capossele's avatar
capossele committed
	this.Reset()
capossele's avatar
capossele committed
	return this
}

func (curl *Curl) Initialize() {
capossele's avatar
capossele committed
	curl.InitializeCurl(nil, 0, curl.rounds)
Wolfgang Welz's avatar
Wolfgang Welz committed
func (curl *Curl) InitializeCurl(trits trinary.Trits, length int, rounds int) {
capossele's avatar
capossele committed
	curl.rounds = rounds
	if trits != nil {
		curl.state = trits
capossele's avatar
capossele committed
	} else {
Wolfgang Welz's avatar
Wolfgang Welz committed
		curl.state = make(trinary.Trits, STATE_LENGTH)
capossele's avatar
capossele committed
	}
}

func (curl *Curl) Reset() {
capossele's avatar
capossele committed
	curl.InitializeCurl(nil, 0, curl.rounds)
Wolfgang Welz's avatar
Wolfgang Welz committed
func (curl *Curl) Absorb(trits trinary.Trits, offset int, length int) {
capossele's avatar
capossele committed
	for {
		limit := int(math.Min(HASH_LENGTH, float64(length)))
		copy(curl.state, trits[offset:offset+limit])
capossele's avatar
capossele committed
		curl.Transform()
		offset += HASH_LENGTH
		length -= HASH_LENGTH
		if length <= 0 {
			break
		}
	}
Wolfgang Welz's avatar
Wolfgang Welz committed
func (curl *Curl) Squeeze(resp trinary.Trits, offset int, length int) trinary.Trits {
capossele's avatar
capossele committed
	for {
		limit := int(math.Min(HASH_LENGTH, float64(length)))
		copy(resp[offset:offset+limit], curl.state)
		curl.Transform()
		offset += HASH_LENGTH
		length -= HASH_LENGTH
		if length <= 0 {
			break
		}
	}
	return resp
}

func (curl *Curl) Transform() {
capossele's avatar
capossele committed
	var index = 0
	for round := 0; round < curl.rounds; round++ {
Wolfgang Welz's avatar
Wolfgang Welz committed
		stateCopy := make(trinary.Trits, STATE_LENGTH)
capossele's avatar
capossele committed
		copy(stateCopy, curl.state)
		for i := 0; i < STATE_LENGTH; i++ {
			incr := 364
			if index >= 365 {
				incr = -365
			}
			index2 := index + incr
			curl.state[i] = TRUTH_TABLE[stateCopy[index]+(stateCopy[index2]<<2)+5]
			index = index2
		}
	}
}