|
@ -11,33 +11,35 @@ const N_FULL_ROUNDS_TOTAL = 2 * HALF_N_FULL_ROUNDS |
|
|
const N_PARTIAL_ROUNDS = 22 |
|
|
const N_PARTIAL_ROUNDS = 22 |
|
|
const N_ROUNDS = N_FULL_ROUNDS_TOTAL + N_PARTIAL_ROUNDS |
|
|
const N_ROUNDS = N_FULL_ROUNDS_TOTAL + N_PARTIAL_ROUNDS |
|
|
const MAX_WIDTH = 12 |
|
|
const MAX_WIDTH = 12 |
|
|
const WIDTH = 12 |
|
|
|
|
|
const SPONGE_WIDTH = 12 |
|
|
const SPONGE_WIDTH = 12 |
|
|
const SPONGE_RATE = 8 |
|
|
const SPONGE_RATE = 8 |
|
|
|
|
|
|
|
|
type PoseidonState = [WIDTH]F |
|
|
|
|
|
|
|
|
type PoseidonState = [SPONGE_WIDTH]F |
|
|
|
|
|
type PoseidonStateExtension = [SPONGE_WIDTH]QuadraticExtension |
|
|
|
|
|
|
|
|
type PoseidonChip struct { |
|
|
type PoseidonChip struct { |
|
|
api frontend.API `gnark:"-"` |
|
|
|
|
|
field frontend.API `gnark:"-"` |
|
|
|
|
|
|
|
|
api frontend.API `gnark:"-"` |
|
|
|
|
|
fieldAPI frontend.API `gnark:"-"` |
|
|
|
|
|
qeAPI *QuadraticExtensionAPI `gnark:"-"` |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func NewPoseidonChip(api frontend.API, field frontend.API) *PoseidonChip { |
|
|
|
|
|
return &PoseidonChip{api: api, field: field} |
|
|
|
|
|
|
|
|
func NewPoseidonChip(api frontend.API, field frontend.API, qeAPI *QuadraticExtensionAPI) *PoseidonChip { |
|
|
|
|
|
return &PoseidonChip{api: api, fieldAPI: field} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) Poseidon(input PoseidonState) PoseidonState { |
|
|
func (c *PoseidonChip) Poseidon(input PoseidonState) PoseidonState { |
|
|
state := input |
|
|
state := input |
|
|
roundCounter := 0 |
|
|
roundCounter := 0 |
|
|
state = c.fullRounds(state, &roundCounter) |
|
|
|
|
|
state = c.partialRounds(state, &roundCounter) |
|
|
|
|
|
state = c.fullRounds(state, &roundCounter) |
|
|
|
|
|
|
|
|
state = c.FullRounds(state, &roundCounter) |
|
|
|
|
|
state = c.PartialRounds(state, &roundCounter) |
|
|
|
|
|
state = c.FullRounds(state, &roundCounter) |
|
|
return state |
|
|
return state |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) HashNToMNoPad(input []F, nbOutputs int) []F { |
|
|
func (c *PoseidonChip) HashNToMNoPad(input []F, nbOutputs int) []F { |
|
|
var state PoseidonState |
|
|
var state PoseidonState |
|
|
|
|
|
|
|
|
for i := 0; i < WIDTH; i++ { |
|
|
|
|
|
|
|
|
for i := 0; i < SPONGE_WIDTH; i++ { |
|
|
state[i] = ZERO_F |
|
|
state[i] = ZERO_F |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -69,24 +71,24 @@ func (c *PoseidonChip) HashNoPad(input []F) Hash { |
|
|
return hash |
|
|
return hash |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) fullRounds(state PoseidonState, roundCounter *int) PoseidonState { |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) FullRounds(state PoseidonState, roundCounter *int) PoseidonState { |
|
|
for i := 0; i < HALF_N_FULL_ROUNDS; i++ { |
|
|
for i := 0; i < HALF_N_FULL_ROUNDS; i++ { |
|
|
state = c.constantLayer(state, roundCounter) |
|
|
|
|
|
state = c.sBoxLayer(state) |
|
|
|
|
|
state = c.mdsLayer(state) |
|
|
|
|
|
|
|
|
state = c.ConstantLayer(state, roundCounter) |
|
|
|
|
|
state = c.SBoxLayer(state) |
|
|
|
|
|
state = c.MdsLayer(state) |
|
|
*roundCounter += 1 |
|
|
*roundCounter += 1 |
|
|
} |
|
|
} |
|
|
return state |
|
|
return state |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) partialRounds(state PoseidonState, roundCounter *int) PoseidonState { |
|
|
|
|
|
state = c.partialFirstConstantLayer(state) |
|
|
|
|
|
state = c.mdsPartialLayerInit(state) |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) PartialRounds(state PoseidonState, roundCounter *int) PoseidonState { |
|
|
|
|
|
state = c.PartialFirstConstantLayer(state) |
|
|
|
|
|
state = c.MdsPartialLayerInit(state) |
|
|
|
|
|
|
|
|
for i := 0; i < N_PARTIAL_ROUNDS; i++ { |
|
|
for i := 0; i < N_PARTIAL_ROUNDS; i++ { |
|
|
state[0] = c.sBoxMonomial(state[0]) |
|
|
|
|
|
state[0] = c.field.Add(state[0], FAST_PARTIAL_ROUND_CONSTANTS[i]).(F) |
|
|
|
|
|
state = c.mdsPartialLayerFast(state, i) |
|
|
|
|
|
|
|
|
state[0] = c.SBoxMonomial(state[0]) |
|
|
|
|
|
state[0] = c.fieldAPI.Add(state[0], FAST_PARTIAL_ROUND_CONSTANTS[i]).(F) |
|
|
|
|
|
state = c.MdsPartialLayerFast(state, i) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
*roundCounter += N_PARTIAL_ROUNDS |
|
|
*roundCounter += N_PARTIAL_ROUNDS |
|
@ -94,38 +96,64 @@ func (c *PoseidonChip) partialRounds(state PoseidonState, roundCounter *int) Pos |
|
|
return state |
|
|
return state |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) constantLayer(state PoseidonState, roundCounter *int) PoseidonState { |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) ConstantLayer(state PoseidonState, roundCounter *int) PoseidonState { |
|
|
|
|
|
for i := 0; i < 12; i++ { |
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
|
|
|
roundConstant := NewFieldElement(ALL_ROUND_CONSTANTS[i+SPONGE_WIDTH*(*roundCounter)]) |
|
|
|
|
|
state[i] = c.fieldAPI.Add(state[i], roundConstant).(F) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return state |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *PoseidonChip) ConstantLayerExtension(state PoseidonStateExtension, roundCounter *int) PoseidonStateExtension { |
|
|
for i := 0; i < 12; i++ { |
|
|
for i := 0; i < 12; i++ { |
|
|
if i < WIDTH { |
|
|
|
|
|
roundConstant := NewFieldElement(ALL_ROUND_CONSTANTS[i+WIDTH*(*roundCounter)]) |
|
|
|
|
|
state[i] = c.field.Add(state[i], roundConstant).(F) |
|
|
|
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
|
|
|
roundConstant := c.qeAPI.FieldToQE(NewFieldElement(ALL_ROUND_CONSTANTS[i+SPONGE_WIDTH*(*roundCounter)])) |
|
|
|
|
|
state[i] = c.qeAPI.AddExtension(state[i], roundConstant) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return state |
|
|
return state |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) sBoxLayer(state PoseidonState) PoseidonState { |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) SBoxMonomial(x F) F { |
|
|
|
|
|
x2 := c.fieldAPI.Mul(x, x) |
|
|
|
|
|
x4 := c.fieldAPI.Mul(x2, x2) |
|
|
|
|
|
x3 := c.fieldAPI.Mul(x2, x) |
|
|
|
|
|
return c.fieldAPI.Mul(x3, x4).(F) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *PoseidonChip) SBoxMonomialExtension(x QuadraticExtension) QuadraticExtension { |
|
|
|
|
|
x2 := c.qeAPI.MulExtension(x, x) |
|
|
|
|
|
x4 := c.qeAPI.MulExtension(x2, x2) |
|
|
|
|
|
x3 := c.qeAPI.MulExtension(x2, x) |
|
|
|
|
|
return c.qeAPI.MulExtension(x3, x4) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *PoseidonChip) SBoxLayer(state PoseidonState) PoseidonState { |
|
|
for i := 0; i < 12; i++ { |
|
|
for i := 0; i < 12; i++ { |
|
|
if i < WIDTH { |
|
|
|
|
|
state[i] = c.sBoxMonomial(state[i]) |
|
|
|
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
|
|
|
state[i] = c.SBoxMonomial(state[i]) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return state |
|
|
return state |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) sBoxMonomial(x F) F { |
|
|
|
|
|
x2 := c.field.Mul(x, x) |
|
|
|
|
|
x4 := c.field.Mul(x2, x2) |
|
|
|
|
|
x3 := c.field.Mul(x2, x) |
|
|
|
|
|
return c.field.Mul(x3, x4).(F) |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) SBoxLayerExtension(state PoseidonStateExtension) PoseidonStateExtension { |
|
|
|
|
|
for i := 0; i < 12; i++ { |
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
|
|
|
state[i] = c.SBoxMonomialExtension(state[i]) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return state |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) mdsRowShf(r int, v [WIDTH]frontend.Variable) frontend.Variable { |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) MdsRowShf(r int, v [SPONGE_WIDTH]frontend.Variable) frontend.Variable { |
|
|
res := frontend.Variable(0) |
|
|
res := frontend.Variable(0) |
|
|
|
|
|
|
|
|
for i := 0; i < 12; i++ { |
|
|
for i := 0; i < 12; i++ { |
|
|
if i < WIDTH { |
|
|
|
|
|
res1 := c.api.Mul(v[(i+r)%WIDTH], frontend.Variable(MDS_MATRIX_CIRC[i])) |
|
|
|
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
|
|
|
res1 := c.api.Mul(v[(i+r)%SPONGE_WIDTH], frontend.Variable(MDS_MATRIX_CIRC[i])) |
|
|
res = c.api.Add(res, res1) |
|
|
res = c.api.Add(res, res1) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -134,38 +162,76 @@ func (c *PoseidonChip) mdsRowShf(r int, v [WIDTH]frontend.Variable) frontend.Var |
|
|
return res |
|
|
return res |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) mdsLayer(state_ PoseidonState) PoseidonState { |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) MdsRowShfExtension(r int, v [SPONGE_WIDTH]QuadraticExtension) QuadraticExtension { |
|
|
|
|
|
res := c.qeAPI.FieldToQE(NewFieldElement(0)) |
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < 12; i++ { |
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
|
|
|
matrixVal := c.qeAPI.FieldToQE(NewFieldElement(MDS_MATRIX_CIRC[i])) |
|
|
|
|
|
res1 := c.qeAPI.MulExtension(v[(i+r)%SPONGE_WIDTH], matrixVal) |
|
|
|
|
|
res = c.qeAPI.AddExtension(res, res1) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
matrixVal := c.qeAPI.FieldToQE(NewFieldElement(MDS_MATRIX_DIAG[r])) |
|
|
|
|
|
res = c.qeAPI.AddExtension(res, c.qeAPI.MulExtension(v[r], matrixVal)) |
|
|
|
|
|
return res |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *PoseidonChip) MdsLayer(state_ PoseidonState) PoseidonState { |
|
|
var result PoseidonState |
|
|
var result PoseidonState |
|
|
for i := 0; i < WIDTH; i++ { |
|
|
|
|
|
|
|
|
for i := 0; i < SPONGE_WIDTH; i++ { |
|
|
result[i] = NewFieldElement(0) |
|
|
result[i] = NewFieldElement(0) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
var state [WIDTH]frontend.Variable |
|
|
|
|
|
for i := 0; i < WIDTH; i++ { |
|
|
|
|
|
state[i] = c.api.FromBinary(c.field.ToBinary(state_[i])...) |
|
|
|
|
|
|
|
|
var state [SPONGE_WIDTH]frontend.Variable |
|
|
|
|
|
for i := 0; i < SPONGE_WIDTH; i++ { |
|
|
|
|
|
state[i] = c.api.FromBinary(c.fieldAPI.ToBinary(state_[i])...) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for r := 0; r < 12; r++ { |
|
|
for r := 0; r < 12; r++ { |
|
|
if r < WIDTH { |
|
|
|
|
|
sum := c.mdsRowShf(r, state) |
|
|
|
|
|
|
|
|
if r < SPONGE_WIDTH { |
|
|
|
|
|
sum := c.MdsRowShf(r, state) |
|
|
bits := c.api.ToBinary(sum) |
|
|
bits := c.api.ToBinary(sum) |
|
|
result[r] = c.field.FromBinary(bits).(F) |
|
|
|
|
|
|
|
|
result[r] = c.fieldAPI.FromBinary(bits).(F) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *PoseidonChip) MdsLayerExtension(state_ PoseidonStateExtension) PoseidonStateExtension { |
|
|
|
|
|
var result PoseidonStateExtension |
|
|
|
|
|
|
|
|
|
|
|
for r := 0; r < 12; r++ { |
|
|
|
|
|
if r < SPONGE_WIDTH { |
|
|
|
|
|
sum := c.MdsRowShfExtension(r, state_) |
|
|
|
|
|
result[r] = sum |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return result |
|
|
return result |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) partialFirstConstantLayer(state PoseidonState) PoseidonState { |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) PartialFirstConstantLayer(state PoseidonState) PoseidonState { |
|
|
for i := 0; i < 12; i++ { |
|
|
for i := 0; i < 12; i++ { |
|
|
if i < WIDTH { |
|
|
|
|
|
state[i] = c.field.Add(state[i], NewFieldElement(FAST_PARTIAL_FIRST_ROUND_CONSTANT[i])).(F) |
|
|
|
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
|
|
|
state[i] = c.fieldAPI.Add(state[i], NewFieldElement(FAST_PARTIAL_FIRST_ROUND_CONSTANT[i])).(F) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return state |
|
|
return state |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) mdsPartialLayerInit(state PoseidonState) PoseidonState { |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) PartialFirstConstantLayerExtension(state PoseidonStateExtension) PoseidonStateExtension { |
|
|
|
|
|
for i := 0; i < 12; i++ { |
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
|
|
|
state[i] = c.qeAPI.AddExtension(state[i], c.qeAPI.FieldToQE(NewFieldElement(FAST_PARTIAL_FIRST_ROUND_CONSTANT[i]))) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return state |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *PoseidonChip) MdsPartialLayerInit(state PoseidonState) PoseidonState { |
|
|
var result PoseidonState |
|
|
var result PoseidonState |
|
|
for i := 0; i < 12; i++ { |
|
|
for i := 0; i < 12; i++ { |
|
|
result[i] = NewFieldElement(0) |
|
|
result[i] = NewFieldElement(0) |
|
@ -174,11 +240,11 @@ func (c *PoseidonChip) mdsPartialLayerInit(state PoseidonState) PoseidonState { |
|
|
result[0] = state[0] |
|
|
result[0] = state[0] |
|
|
|
|
|
|
|
|
for r := 1; r < 12; r++ { |
|
|
for r := 1; r < 12; r++ { |
|
|
if r < WIDTH { |
|
|
|
|
|
|
|
|
if r < SPONGE_WIDTH { |
|
|
for d := 1; d < 12; d++ { |
|
|
for d := 1; d < 12; d++ { |
|
|
if d < WIDTH { |
|
|
|
|
|
|
|
|
if d < SPONGE_WIDTH { |
|
|
t := NewFieldElement(FAST_PARTIAL_ROUND_INITIAL_MATRIX[r-1][d-1]) |
|
|
t := NewFieldElement(FAST_PARTIAL_ROUND_INITIAL_MATRIX[r-1][d-1]) |
|
|
result[d] = c.field.Add(result[d], c.field.Mul(state[r], t)).(F) |
|
|
|
|
|
|
|
|
result[d] = c.fieldAPI.Add(result[d], c.fieldAPI.Mul(state[r], t)).(F) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -187,32 +253,77 @@ func (c *PoseidonChip) mdsPartialLayerInit(state PoseidonState) PoseidonState { |
|
|
return result |
|
|
return result |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) mdsPartialLayerFast(state PoseidonState, r int) PoseidonState { |
|
|
|
|
|
|
|
|
func (c *PoseidonChip) MdsPartialLayerInitExtension(state PoseidonStateExtension) PoseidonStateExtension { |
|
|
|
|
|
var result PoseidonStateExtension |
|
|
|
|
|
for i := 0; i < 12; i++ { |
|
|
|
|
|
result[i] = c.qeAPI.FieldToQE(NewFieldElement(0)) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
result[0] = state[0] |
|
|
|
|
|
|
|
|
|
|
|
for r := 1; r < 12; r++ { |
|
|
|
|
|
if r < SPONGE_WIDTH { |
|
|
|
|
|
for d := 1; d < 12; d++ { |
|
|
|
|
|
if d < SPONGE_WIDTH { |
|
|
|
|
|
t := c.qeAPI.FieldToQE(NewFieldElement(FAST_PARTIAL_ROUND_INITIAL_MATRIX[r-1][d-1])) |
|
|
|
|
|
result[d] = c.qeAPI.AddExtension(result[d], c.qeAPI.MulExtension(state[r], t)) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *PoseidonChip) MdsPartialLayerFast(state PoseidonState, r int) PoseidonState { |
|
|
dSum := frontend.Variable(0) |
|
|
dSum := frontend.Variable(0) |
|
|
for i := 1; i < 12; i++ { |
|
|
for i := 1; i < 12; i++ { |
|
|
if i < WIDTH { |
|
|
|
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
t := frontend.Variable(FAST_PARTIAL_ROUND_W_HATS[r][i-1]) |
|
|
t := frontend.Variable(FAST_PARTIAL_ROUND_W_HATS[r][i-1]) |
|
|
si := c.api.FromBinary(c.field.ToBinary(state[i])...) |
|
|
|
|
|
|
|
|
si := c.api.FromBinary(c.fieldAPI.ToBinary(state[i])...) |
|
|
dSum = c.api.Add(dSum, c.api.Mul(si, t)) |
|
|
dSum = c.api.Add(dSum, c.api.Mul(si, t)) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
s0 := c.api.FromBinary(c.field.ToBinary(state[0])...) |
|
|
|
|
|
|
|
|
s0 := c.api.FromBinary(c.fieldAPI.ToBinary(state[0])...) |
|
|
mds0to0 := frontend.Variable(MDS_MATRIX_CIRC[0] + MDS_MATRIX_DIAG[0]) |
|
|
mds0to0 := frontend.Variable(MDS_MATRIX_CIRC[0] + MDS_MATRIX_DIAG[0]) |
|
|
dSum = c.api.Add(dSum, c.api.Mul(s0, mds0to0)) |
|
|
dSum = c.api.Add(dSum, c.api.Mul(s0, mds0to0)) |
|
|
d := c.field.FromBinary(c.api.ToBinary(dSum)) |
|
|
|
|
|
|
|
|
d := c.fieldAPI.FromBinary(c.api.ToBinary(dSum)) |
|
|
|
|
|
|
|
|
var result PoseidonState |
|
|
var result PoseidonState |
|
|
for i := 0; i < WIDTH; i++ { |
|
|
|
|
|
|
|
|
for i := 0; i < SPONGE_WIDTH; i++ { |
|
|
result[i] = NewFieldElement(0) |
|
|
result[i] = NewFieldElement(0) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
result[0] = d.(F) |
|
|
result[0] = d.(F) |
|
|
|
|
|
|
|
|
for i := 1; i < 12; i++ { |
|
|
for i := 1; i < 12; i++ { |
|
|
if i < WIDTH { |
|
|
|
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
t := NewFieldElement(FAST_PARTIAL_ROUND_VS[r][i-1]) |
|
|
t := NewFieldElement(FAST_PARTIAL_ROUND_VS[r][i-1]) |
|
|
result[i] = c.field.Add(state[i], c.field.Mul(state[0], t)).(F) |
|
|
|
|
|
|
|
|
result[i] = c.fieldAPI.Add(state[i], c.fieldAPI.Mul(state[0], t)).(F) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *PoseidonChip) MdsPartialLayerFastExtension(state PoseidonStateExtension, r int) PoseidonStateExtension { |
|
|
|
|
|
s0 := state[0] |
|
|
|
|
|
mds0to0 := c.qeAPI.FieldToQE(NewFieldElement(MDS_MATRIX_CIRC[0] + MDS_MATRIX_DIAG[0])) |
|
|
|
|
|
d := c.qeAPI.AddExtension(s0, mds0to0) |
|
|
|
|
|
for i := 1; i < 12; i++ { |
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
|
|
|
t := c.qeAPI.FieldToQE(NewFieldElement(FAST_PARTIAL_ROUND_W_HATS[r][i-1])) |
|
|
|
|
|
d = c.qeAPI.AddExtension(d, c.qeAPI.MulExtension(state[i], t)) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var result PoseidonStateExtension |
|
|
|
|
|
result[0] = d |
|
|
|
|
|
for i := 1; i < 12; i++ { |
|
|
|
|
|
if i < SPONGE_WIDTH { |
|
|
|
|
|
t := c.qeAPI.FieldToQE(NewFieldElement(FAST_PARTIAL_ROUND_VS[r][i-1])) |
|
|
|
|
|
result[i] = c.qeAPI.AddExtension(state[i], c.qeAPI.MulExtension(state[0], t)) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|