Skip to content

Commit e50e8a7

Browse files
committed
add ed25519 before/after batch verification signature tests
1 parent 54db1c7 commit e50e8a7

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

data/transactions/logic/evalCrypto_test.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/algorand/go-algorand/crypto/secp256k1"
3434
"github.com/algorand/go-algorand/data/basics"
3535
"github.com/algorand/go-algorand/data/transactions"
36+
"github.com/algorand/go-algorand/protocol"
3637
"github.com/algorand/go-algorand/test/partitiontest"
3738
)
3839

@@ -131,6 +132,155 @@ ed25519verify`, pkStr), v)
131132
}
132133
}
133134

135+
func TestEd25519verifyCompatValid(t *testing.T) {
136+
partitiontest.PartitionTest(t)
137+
138+
// ed25519verify opcode uses prefix "ProgData" || program_hash in hex
139+
// the following snippet produces: "50726f67446174610fefbfeb4749642b4e93f37098946ce11a63d6a8db82a416ff91321760212fac"
140+
// for use below
141+
/*
142+
ops, err := AssembleStringWithVersion(`arg 0
143+
arg 1
144+
arg 2
145+
ed25519verify`, AssemblerMaxVersion)
146+
require.NoError(t, err)
147+
h := crypto.HashObj(Program(ops.Program))
148+
t.Log("program hash", hex.EncodeToString(h[:]))
149+
t.Log("progdata", hex.EncodeToString([]byte(protocol.ProgramData)))
150+
cat := append([]byte(protocol.ProgramData), h[:]...)
151+
t.Log("progdata||program_hash", hex.EncodeToString(cat))
152+
*/
153+
// generated by github.com/p-steuer/eddsa-test
154+
data, err := hex.DecodeString("cb68")
155+
require.NoError(t, err)
156+
vecs := [][3]string{
157+
{
158+
"50726f67446174610fefbfeb4749642b4e93f37098946ce11a63d6a8db82a416ff91321760212faccb68", // msg M
159+
"5866666666666666666666666666666666666666666666666666666666666666", // pub A
160+
"01000000000000000000000000000000000000000000000000000000000000006a889c732ac8ea1507a1547dcee1d74efc9113f9377216d8dfacc7fee5156504", // sig (R,S)
161+
},
162+
}
163+
vecBytes := make([][3][]byte, len(vecs))
164+
for i, tup3 := range vecs {
165+
for j := range tup3 {
166+
vecBytes[i][j], err = hex.DecodeString(vecs[i][j])
167+
require.NoError(t, err)
168+
}
169+
}
170+
171+
for i, vec := range vecBytes {
172+
t.Run(fmt.Sprintf("valid,vec=%v", vecs[i]), func(t *testing.T) {
173+
// simple program that is only valid if EnableBatchVerification=true
174+
ops, err := AssembleStringWithVersion(fmt.Sprintf(`arg 0
175+
arg 1
176+
arg 2
177+
ed25519verify`), uint64(6))
178+
require.NoError(t, err)
179+
var txn transactions.SignedTxn
180+
txn.Lsig.Logic = ops.Program
181+
txn.Lsig.Args = [][]byte{data[:], vec[2], vec[1]}
182+
sb := strings.Builder{}
183+
184+
// try with EnableBatchVerification = false
185+
evalParams := defaultEvalParams(&sb, &txn)
186+
evalParams.Proto.EnableBatchVerification = false
187+
pass, err := Eval(ops.Program, evalParams)
188+
require.False(t, pass)
189+
require.NoError(t, err)
190+
191+
// try with EnableBatchVerification = true
192+
evalParams.Proto.EnableBatchVerification = true
193+
pass, err = Eval(ops.Program, evalParams)
194+
require.True(t, pass)
195+
require.NoError(t, err)
196+
})
197+
}
198+
}
199+
200+
func TestEd25519verifyCompatPayment(t *testing.T) {
201+
partitiontest.PartitionTest(t)
202+
203+
// generated by github.com/p-steuer/eddsa-test
204+
data, err := hex.DecodeString("1dab")
205+
require.NoError(t, err)
206+
vecs := [][3]string{
207+
{
208+
"50726f6744617461f6691f135f7945d27ec1f87846d0694709e2ae67808ff4082a007a15754cb9a51dab", // msg M
209+
"5866666666666666666666666666666666666666666666666666666666666666", // pub A
210+
"0100000000000000000000000000000000000000000000000000000000000000095660bba17daf63dac3dc8c8600c55e25dd077032ff3c050bb0e9cdd0293b0e", // sig (R,S)
211+
},
212+
}
213+
vecBytes := make([][3][]byte, len(vecs))
214+
for i, tup3 := range vecs {
215+
for j := range tup3 {
216+
vecBytes[i][j], err = hex.DecodeString(vecs[i][j])
217+
require.NoError(t, err)
218+
}
219+
}
220+
221+
for i, vec := range vecBytes {
222+
t.Run(fmt.Sprintf("valid,vec=%v", vecs[i]), func(t *testing.T) {
223+
// logic sig that lets you withdraw different amounts if EnableBatchVerification=true
224+
/* (||
225+
(&& (ed25519verify (arg 0) (arg 1) (arg 2))
226+
(== (txn Amount) 1000000))
227+
(&& (! (ed25519verify (arg 0) (arg 1) (arg 2)))
228+
(== (txn Amount) 2000000))
229+
)
230+
*/
231+
ops, err := AssembleStringWithVersion(`arg 0
232+
arg 1
233+
arg 2
234+
ed25519verify
235+
txn Amount
236+
int 1000000
237+
==
238+
&&
239+
arg 0
240+
arg 1
241+
arg 2
242+
ed25519verify
243+
!
244+
txn Amount
245+
int 2000000
246+
==
247+
&&
248+
||`, uint64(6))
249+
require.NoError(t, err)
250+
h := crypto.HashObj(Program(ops.Program))
251+
t.Log("program hash", hex.EncodeToString(h[:]))
252+
t.Log("progdata", hex.EncodeToString([]byte(protocol.ProgramData)))
253+
cat := append([]byte(protocol.ProgramData), h[:]...)
254+
t.Log("progdata||program_hash", hex.EncodeToString(cat))
255+
256+
for _, tc := range []struct {
257+
amount uint64
258+
enableBatchVerification bool
259+
valid bool
260+
}{
261+
{1000000, false, false}, // EnableBatchVerification = false, can't withdraw 1 algo
262+
{2000000, false, true}, // EnableBatchVerification = false, withdraw 2 algos
263+
{1000000, true, true}, // EnableBatchVerification = true, withdraw 1 algo
264+
{2000000, true, false}, // EnableBatchVerification = true, can't withdraw 2 algos
265+
} {
266+
t.Run(fmt.Sprintf("%+v", tc), func(t *testing.T) {
267+
var txn transactions.SignedTxn
268+
txn.Lsig.Logic = ops.Program
269+
txn.Lsig.Args = [][]byte{data[:], vec[2], vec[1]}
270+
sb := strings.Builder{}
271+
txn.Txn.Amount = basics.MicroAlgos{Raw: tc.amount}
272+
evalParams := defaultEvalParams(&sb, &txn)
273+
evalParams.Proto.EnableBatchVerification = tc.enableBatchVerification
274+
pass, err := Eval(ops.Program, evalParams)
275+
require.Equal(t, tc.valid, pass, "trace %s", sb.String())
276+
t.Log(sb.String())
277+
require.NoError(t, err)
278+
})
279+
}
280+
})
281+
}
282+
}
283+
134284
// bitIntFillBytes is a replacement for big.Int.FillBytes from future Go
135285
func bitIntFillBytes(b *big.Int, buf []byte) []byte {
136286
for i := range buf {

0 commit comments

Comments
 (0)