Skip to content

Commit

Permalink
Merge pull request #418 from iden3/iden232
Browse files Browse the repository at this point in the history
IDEN-232 get rid of merkletree dependency. Replace merkletree.Hash ty…
  • Loading branch information
OBrezhniev authored Mar 25, 2022
2 parents e5b5639 + 08ec28c commit 199bd22
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 136 deletions.
14 changes: 5 additions & 9 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,11 @@ on:
jobs:
lint:
runs-on: ubuntu-20.04
container: golangci/golangci-lint:v1.43.0
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
- uses: actions/setup-go@v2
with:
path: |
~/.cache/go-build
/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- run: golangci-lint run
go-version: 1.18.0
- uses: golangci/golangci-lint-action@v2
with:
version: v1.45.0
3 changes: 2 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ jobs:
strategy:
matrix:
containers:
- 1.17.2-bullseye
- 1.17.8-bullseye
- 1.18.0-bullseye
runs-on: ubuntu-20.04
container: golang:${{matrix.containers}}
steps:
Expand Down
75 changes: 12 additions & 63 deletions claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"time"

"github.com/iden3/go-iden3-crypto/utils"
"github.com/iden3/go-merkletree-sql"
)

/*
Expand Down Expand Up @@ -57,7 +56,7 @@ var ErrIncorrectIDPosition = errors.New("incorrect ID position")
// ErrNoID returns when ID not found in the Claim.
var ErrNoID = errors.New("ID is not set")

// ErrSlotOverflow means some DataSlot overflows Q Field. And wraps the name
// ErrSlotOverflow means some ElemBytes overflows Q Field. And wraps the name
// of overflowed slot.
type ErrSlotOverflow struct {
Field SlotName
Expand Down Expand Up @@ -91,50 +90,9 @@ func (sc SchemaHash) MarshalText() ([]byte, error) {
return dst, nil
}

// DataSlot length is 32 bytes. But not all 32-byte values are valid.
// The value should be not greater than Q constant
// 21888242871839275222246405745257275088548364400416034343698204186575808495617
type DataSlot [32]byte

// ToInt returns *big.Int representation of DataSlot.
func (ds DataSlot) ToInt() *big.Int {
return new(big.Int).SetBytes(utils.SwapEndianness(ds[:]))
}

// SetInt sets data slot to serialized value of *big.Int. And checks that the
// value is valid (fills in Field Q).
// Returns ErrDataOverflow if the value is too large
func (ds *DataSlot) SetInt(value *big.Int) error {
if !utils.CheckBigIntInField(value) {
return ErrDataOverflow
}

val := utils.SwapEndianness(value.Bytes())
copy((*ds)[:], val)
memset((*ds)[len(val):], 0)
return nil
}

// NewDataSlotFromInt creates new DataSlot from *big.Int.
// Returns error ErrDataOverflow if value is too large to fill the Field Q.
func NewDataSlotFromInt(i *big.Int) (DataSlot, error) {
var s DataSlot
bs := i.Bytes()
// may be this check is redundant because of CheckBigIntInField, but just
// in case.
if len(bs) > len(s) {
return s, ErrDataOverflow
}
if !utils.CheckBigIntInField(i) {
return s, ErrDataOverflow
}
copy(s[:], utils.SwapEndianness(bs))
return s, nil
}

type Claim struct {
index [4]DataSlot
value [4]DataSlot
index [4]ElemBytes
value [4]ElemBytes
}

// Subject for the time being describes the location of ID (in index or value
Expand Down Expand Up @@ -236,7 +194,7 @@ func WithExpirationDate(dt time.Time) Option {

// WithIndexData sets data to index slots A & B.
// Returns ErrSlotOverflow if slotA or slotB value are too big.
func WithIndexData(slotA, slotB DataSlot) Option {
func WithIndexData(slotA, slotB ElemBytes) Option {
return func(c *Claim) error {
return c.SetIndexData(slotA, slotB)
}
Expand All @@ -260,7 +218,7 @@ func WithIndexDataInts(slotA, slotB *big.Int) Option {

// WithValueData sets data to value slots A & B.
// Returns ErrSlotOverflow if slotA or slotB value are too big.
func WithValueData(slotA, slotB DataSlot) Option {
func WithValueData(slotA, slotB ElemBytes) Option {
return func(c *Claim) error {
return c.SetValueData(slotA, slotB)
}
Expand Down Expand Up @@ -451,7 +409,7 @@ func (c *Claim) GetExpirationDate() (time.Time, bool) {

// SetIndexData sets data to index slots A & B.
// Returns ErrSlotOverflow if slotA or slotB value are too big.
func (c *Claim) SetIndexData(slotA, slotB DataSlot) error {
func (c *Claim) SetIndexData(slotA, slotB ElemBytes) error {
slotsAsInts := []*big.Int{slotA.ToInt(), slotB.ToInt()}
if !utils.CheckBigIntArrayInField(slotsAsInts) {
return ErrDataOverflow
Expand Down Expand Up @@ -484,7 +442,7 @@ func (c *Claim) SetIndexDataInts(slotA, slotB *big.Int) error {

// SetValueData sets data to value slots A & B.
// Returns ErrSlotOverflow if slotA or slotB value are too big.
func (c *Claim) SetValueData(slotA, slotB DataSlot) error {
func (c *Claim) SetValueData(slotA, slotB ElemBytes) error {
slotsAsInts := []*big.Int{slotA.ToInt(), slotB.ToInt()}
if !utils.CheckBigIntArrayInField(slotsAsInts) {
return ErrDataOverflow
Expand Down Expand Up @@ -515,7 +473,7 @@ func (c *Claim) SetValueDataInts(slotA, slotB *big.Int) error {
return setSlotInt(&c.value[3], slotB, SlotNameValueB)
}

func setSlotBytes(slot *DataSlot, value []byte, slotName SlotName) error {
func setSlotBytes(slot *ElemBytes, value []byte, slotName SlotName) error {
if len(value) > len(*slot) {
return ErrSlotOverflow{slotName}
}
Expand All @@ -527,8 +485,7 @@ func setSlotBytes(slot *DataSlot, value []byte, slotName SlotName) error {
return nil
}

func setSlotInt(slot *DataSlot, value *big.Int, slotName SlotName) error {

func setSlotInt(slot *ElemBytes, value *big.Int, slotName SlotName) error {
if value == nil {
value = big.NewInt(0)
}
Expand All @@ -540,17 +497,9 @@ func setSlotInt(slot *DataSlot, value *big.Int, slotName SlotName) error {
return err
}

// TreeEntry creates new merkletree.Entry from the claim. Following changes to
// claim does not change returned merkletree.Entry.
func (c *Claim) TreeEntry() merkletree.Entry {
var e merkletree.Entry
for i := range c.index {
copy(e.Data[i][:], c.index[i][:])
}
for i := range c.value {
copy(e.Data[i+len(c.index)][:], c.value[i][:])
}
return e
// RawSlots returns raw bytes of claim's index and value
func (c *Claim) RawSlots() (index [4]ElemBytes, value [4]ElemBytes) {
return c.index, c.value
}

// Clone returns full deep copy of claim
Expand Down
65 changes: 35 additions & 30 deletions claim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
"testing"
"time"

"github.com/iden3/go-iden3-crypto/poseidon"
"github.com/iden3/go-iden3-crypto/utils"

"github.com/stretchr/testify/require"
)

Expand All @@ -37,34 +37,33 @@ func TestNewClaim(t *testing.T) {
require.False(t, ok)
}

func (ds DataSlot) String() string {
func (el ElemBytes) String() string {
var b bytes.Buffer
for j := len(ds) - 1; j >= 0; j-- {
b.WriteString(fmt.Sprintf("% 08b", ds[j]))
for j := len(el) - 1; j >= 0; j-- {
b.WriteString(fmt.Sprintf("% 08b", el[j]))
}
return b.String()
}

func TestMerketreeEntryHash(t *testing.T) {
func TestRawSlots(t *testing.T) {
var schemaHash SchemaHash
claim, err := NewClaim(schemaHash, WithFlagUpdatable(true))
require.NoError(t, err)
e := claim.TreeEntry()

hi, hv, err := e.HiHv()
index, value := claim.RawSlots()
indexHash, err := poseidon.Hash([]*big.Int{
index[0].ToInt(), index[1].ToInt(), index[2].ToInt(), index[3].ToInt()})
require.NoError(t, err)

hit, err := hi.MarshalText()
valueHash, err := poseidon.Hash([]*big.Int{
value[0].ToInt(), value[1].ToInt(), value[2].ToInt(), value[3].ToInt()})
require.NoError(t, err)

require.Equal(t,
"19905260441950906049955646784794273651462264973332746773406911374272567544299",
string(hit))
indexHash.Text(10))

hvt, err := hv.MarshalText()
require.NoError(t, err)
require.Equal(t,
"2351654555892372227640888372176282444150254868378439619268573230312091195718",
string(hvt))
valueHash.Text(10))
}

func TestClaim_GetSchemaHash(t *testing.T) {
Expand All @@ -74,7 +73,8 @@ func TestClaim_GetSchemaHash(t *testing.T) {
require.Equal(t, schemaHashLn, n)
claim, err := NewClaim(sc)
require.NoError(t, err)
require.True(t, bytes.Equal(sc[:], utils.SwapEndianness(claim.index[0][:schemaHashLn])))
require.True(t,
bytes.Equal(sc[:], utils.SwapEndianness(claim.index[0][:schemaHashLn])))

shFromClaim := claim.GetSchemaHash()
shFromClaimHexBytes, err := shFromClaim.MarshalText()
Expand Down Expand Up @@ -159,18 +159,22 @@ func toInt(t testing.TB, s string) *big.Int {
}

func TestIntSize(t *testing.T) {
iX := toInt(t, "16243864111864693853212588481963275789994876191154110553066821559749894481761")
iY := toInt(t, "7078462697308959301666117070269719819629678436794910510259518359026273676830")
vX := toInt(t, "12448278679517811784508557734102986855579744384337338465055621486538311281772")
vY := toInt(t, "9260608685281348956030279125705000716237952776955782848598673606545494194823")
iX := toInt(t,
"16243864111864693853212588481963275789994876191154110553066821559749894481761")
iY := toInt(t,
"7078462697308959301666117070269719819629678436794910510259518359026273676830")
vX := toInt(t,
"12448278679517811784508557734102986855579744384337338465055621486538311281772")
vY := toInt(t,
"9260608685281348956030279125705000716237952776955782848598673606545494194823")

ixSlot, err := NewDataSlotFromInt(iX)
ixSlot, err := NewElemBytesFromInt(iX)
require.NoError(t, err)
iySlot, err := NewDataSlotFromInt(iY)
iySlot, err := NewElemBytesFromInt(iY)
require.NoError(t, err)
vxSlot, err := NewDataSlotFromInt(vX)
vxSlot, err := NewElemBytesFromInt(vX)
require.NoError(t, err)
vySlot, err := NewDataSlotFromInt(vY)
vySlot, err := NewElemBytesFromInt(vY)
require.NoError(t, err)
_, err = NewClaim(SchemaHash{},
WithIndexData(ixSlot, iySlot),
Expand All @@ -179,25 +183,25 @@ func TestIntSize(t *testing.T) {
}

func TestNewDataSlotFromInt(t *testing.T) {
ds, err := NewDataSlotFromInt(toInt(t,
ds, err := NewElemBytesFromInt(toInt(t,
"16243864111864693853212588481963275789994876191154110553066821559749894481761"))
require.NoError(t, err)
expected := DataSlot{
expected := ElemBytes{
0x61, 0x27, 0xa0, 0xeb, 0x58, 0x7a, 0x6c, 0x2b,
0x4a, 0xa8, 0xc1, 0x2e, 0xf5, 0x01, 0xb2, 0xdb,
0xd0, 0x9c, 0xb1, 0xa5, 0x9c, 0x83, 0x42, 0x57,
0x91, 0xa5, 0x20, 0xbf, 0x86, 0xb3, 0xe9, 0x23,
}
require.Equal(t, expected, ds)

_, err = NewDataSlotFromInt(toInt(t,
_, err = NewElemBytesFromInt(toInt(t,
"9916243864111864693853212588481963275789994876191154110553066821559749894481761"))
require.EqualError(t, err, ErrDataOverflow.Error())
}

func TestClaim_WithIndexDataInts(t *testing.T) {

expSlot := DataSlot{}
expSlot := ElemBytes{}
err := expSlot.SetInt(big.NewInt(0))
require.NoError(t, err)

Expand All @@ -216,7 +220,7 @@ func TestClaim_WithIndexDataInts(t *testing.T) {

func TestClaim_WithValueDataInts(t *testing.T) {

expSlot := DataSlot{}
expSlot := ElemBytes{}
err := expSlot.SetInt(big.NewInt(0))
require.NoError(t, err)

Expand All @@ -236,8 +240,9 @@ func TestClaim_WithValueDataInts(t *testing.T) {

func TestClaim_WithIndexDataBytes(t *testing.T) {

iX := toInt(t, "124482786795178117845085577341029868555797443843373384650556214865383112817")
expSlot := DataSlot{}
iX := toInt(t,
"124482786795178117845085577341029868555797443843373384650556214865383112817")
expSlot := ElemBytes{}
err := expSlot.SetInt(big.NewInt(0))
require.NoError(t, err)

Expand Down
63 changes: 63 additions & 0 deletions elem_bytes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package core

import (
"encoding/hex"
"math/big"

"github.com/iden3/go-iden3-crypto/utils"
)

// ElemBytes length is 32 bytes. But not all 32-byte values are valid.
// The value should be not greater than Q constant
// 21888242871839275222246405745257275088548364400416034343698204186575808495617
type ElemBytes [32]byte

// ToInt returns *big.Int representation of ElemBytes.
func (el ElemBytes) ToInt() *big.Int {
return new(big.Int).SetBytes(utils.SwapEndianness(el[:]))
}

// SetInt sets element's data to serialized value of *big.Int in little-endian.
// And checks that the value is valid (fits in Field Q).
// Returns ErrDataOverflow if the value is too large
func (el *ElemBytes) SetInt(value *big.Int) error {
if !utils.CheckBigIntInField(value) {
return ErrDataOverflow
}

val := utils.SwapEndianness(value.Bytes())
copy((*el)[:], val)
memset((*el)[len(val):], 0)
return nil
}

// Hex returns HEX representation of ElemBytes
func (el ElemBytes) Hex() string {
return hex.EncodeToString(el[:])
}

// NewElemBytesFromInt creates new ElemBytes from *big.Int.
// Returns error ErrDataOverflow if value is too large to fill the Field Q.
func NewElemBytesFromInt(i *big.Int) (ElemBytes, error) {
var s ElemBytes
bs := i.Bytes()
// may be this check is redundant because of CheckBigIntInField, but just
// in case.
if len(bs) > len(s) {
return s, ErrDataOverflow
}
if !utils.CheckBigIntInField(i) {
return s, ErrDataOverflow
}
copy(s[:], utils.SwapEndianness(bs))
return s, nil
}

// ElemBytesToInts converts slice of ElemBytes to slice of *big.Int
func ElemBytesToInts(elements []ElemBytes) []*big.Int {
result := make([]*big.Int, len(elements))
for i := range elements {
result[i] = elements[i].ToInt()
}
return result
}
Loading

0 comments on commit 199bd22

Please sign in to comment.