package m import ( "errors" "fmt" "github.com/google/uuid" "go-nkode/hashset" py "go-nkode/py-builtin" "go-nkode/util" ) type Customer struct { Id CustomerId NKodePolicy NKodePolicy Attributes CustomerAttributes } func NewCustomer(nkodePolicy NKodePolicy) (*Customer, error) { customerAttrs, err := NewCustomerAttributes() if err != nil { return nil, err } customer := Customer{ Id: CustomerId(uuid.New()), NKodePolicy: nkodePolicy, Attributes: *customerAttrs, } return &customer, nil } func (c *Customer) IsValidNKode(kp KeypadDimension, passcodeAttrIdx []int) error { nkodeLen := len(passcodeAttrIdx) if nkodeLen < c.NKodePolicy.MinNkodeLen { return errors.New(fmt.Sprintf("NKode length %d is too short. Minimum nKode length is %d", nkodeLen, c.NKodePolicy.MinNkodeLen)) } validIdx := py.All[int](passcodeAttrIdx, func(i int) bool { return i >= 0 && i < kp.TotalAttrs() }) if !validIdx { return errors.New(fmt.Sprintf("One or more idx out of range 0-%d in IsValidNKode", kp.TotalAttrs()-1)) } passcodeSetVals := make(hashset.Set[uint64]) passcodeAttrVals := make(hashset.Set[uint64]) attrVals, err := c.Attributes.AttrValsForKp(kp) if err != nil { return err } for idx := 0; idx < nkodeLen; idx++ { attrVal := attrVals[passcodeAttrIdx[idx]] setVal, err := c.Attributes.GetAttrSetVal(attrVal, kp) if err != nil { return err } passcodeSetVals.Add(setVal) passcodeAttrVals.Add(attrVal) } if passcodeSetVals.Size() < c.NKodePolicy.DistinctSets { return errors.New(fmt.Sprintf("passcode has two few distinct sets min %d, has %d", c.NKodePolicy.DistinctSets, passcodeSetVals.Size())) } if passcodeAttrVals.Size() < c.NKodePolicy.DistinctAttributes { return errors.New(fmt.Sprintf("passcode has two few distinct attributes min %d, has %d", c.NKodePolicy.DistinctAttributes, passcodeAttrVals.Size())) } return nil } func (c *Customer) RenewKeys() ([]uint64, []uint64) { oldAttrs := make([]uint64, len(c.Attributes.AttrVals)) oldSets := make([]uint64, len(c.Attributes.SetVals)) copy(oldAttrs, c.Attributes.AttrVals) copy(oldSets, c.Attributes.SetVals) err := c.Attributes.Renew() if err != nil { panic(err) } attrsXor, err := util.XorLists(oldAttrs, c.Attributes.AttrVals) if err != nil { panic(err) } setXor, err := util.XorLists(oldSets, c.Attributes.SetVals) if err != nil { panic(err) } return setXor, attrsXor }