salt.gno
2.13 Kb · 86 lines
1package zkgm
2
3import (
4 "crypto/keccak256"
5 "encoding/binary"
6
7 u256 "gno.land/p/onbloc/math/uint256"
8)
9
10func DeriveBatchSalt(index *u256.Uint, salt [32]byte) [32]byte {
11 var input [64]byte
12
13 putUint256BE(input[:32], index)
14 copy(input[32:], salt[:])
15
16 return keccak256.Sum256(input[:])
17}
18
19func TintForwardSalt(salt [32]byte) [32]byte {
20 var out [32]byte
21 for i := range salt {
22 out[i] = salt[i] | FORWARD_SALT_MAGIC[i]
23 }
24
25 return out
26}
27
28func IsForwardedPacket(salt [32]byte) bool {
29 for i := range salt {
30 if salt[i]&FORWARD_SALT_MAGIC[i] != FORWARD_SALT_MAGIC[i] {
31 return false
32 }
33 }
34
35 return true
36}
37
38func DeriveForwardSalt(salt [32]byte) [32]byte {
39 hash := keccak256.Sum256(salt[:])
40 return TintForwardSalt(hash)
41}
42
43// Uint256ToBytes32 returns the big-endian 32-byte encoding of x.
44func Uint256ToBytes32(x *u256.Uint) [32]byte {
45 var out [32]byte
46
47 putUint256BE(out[:], x)
48
49 return out
50}
51
52// DeriveSenderSalt computes:
53//
54// keccak256((sender, salt).abi_encode())
55//
56// matching Union's alloy-sol-types encoding of a top-level dynamic tuple.
57// Callers must pass the raw UTF-8 bytes of the bech32 account string.
58func DeriveSenderSalt(sender []byte, salt [32]byte) [32]byte {
59 // ABI layout for alloy `(bytes, bytes32).abi_encode()`:
60 //
61 // word 0: offset to top-level tuple body (0x20)
62 // word 1: offset to sender data within tuple body (0x40)
63 // word 2: salt
64 // word 3: len(sender)
65 // word 4+: sender bytes, right-padded to a 32-byte boundary
66 //
67 // The inner offset is relative to the start of the tuple body.
68 pad := (32 - len(sender)%32) % 32
69 buf := make([]byte, 4*32+len(sender)+pad)
70 buf[31] = 0x20
71 buf[63] = 0x40
72 copy(buf[64:96], salt[:])
73 binary.BigEndian.PutUint64(buf[120:128], uint64(len(sender)))
74 copy(buf[128:], sender)
75
76 return keccak256.Sum256(buf)
77}
78
79// NOTE: depends on gnoswap/uint256's internal [4]uint64 layout (mirror of
80// SetBytes32). Replace with the upstream Bytes32() method once it exists.
81func putUint256BE(dst []byte, x *u256.Uint) {
82 binary.BigEndian.PutUint64(dst[0:8], x[3])
83 binary.BigEndian.PutUint64(dst[8:16], x[2])
84 binary.BigEndian.PutUint64(dst[16:24], x[1])
85 binary.BigEndian.PutUint64(dst[24:32], x[0])
86}