Skip to content

Instantly share code, notes, and snippets.

@vmx
Created December 7, 2023 14:08
Show Gist options
  • Save vmx/37e724c71fba9e40ee65bb89a8c8f0a6 to your computer and use it in GitHub Desktop.
Save vmx/37e724c71fba9e40ee65bb89a8c8f0a6 to your computer and use it in GitHub Desktop.
Filecoin replica encoding in Go
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
)
func encode(valueBytes, keyBytes [32]byte) [32]byte {
key, err := fr.LittleEndian.Element(&keyBytes);
if err != nil {
log.Fatalf("Failed to create element: %v", err)
}
value, err := fr.LittleEndian.Element(&valueBytes);
if err != nil {
log.Fatalf("Failed to create element: %v", err)
}
// Do the actual encoding.
key.Add(&key, &value)
result := key.Bytes()
// Reverse the bytes to match the little-endian encoding that are used
// in Filecoin.
for i, j := 0, 31; i < j; i, j = i+1, j-1 {
result[i], result[j] = result[j], result[i]
}
return result
}
func main() {
// Check command-line arguments
if len(os.Args) != 4 {
log.Fatal("Usage: go run main.go <keyFilePath> <valueFilePath> <outputFilePath>")
}
// Read keyBytes from file
valueFilePath := os.Args[1]
valueBytes, err := ioutil.ReadFile(valueFilePath)
if err != nil {
log.Fatalf("Failed to read value file: %v", err)
}
// Read valueBytes from file
keyFilePath := os.Args[2]
keyBytes, err := ioutil.ReadFile(keyFilePath)
if err != nil {
log.Fatalf("Failed to read key file: %v", err)
}
// Check if input files have the same size and are divisible by 32 bytes
if len(valueBytes) != len(keyBytes) || len(valueBytes)%32 != 0 {
log.Fatal("Input file sizes are not compatible")
}
// Calculate the number of 32-byte chunks
numChunks := len(valueBytes) / 32
// Create a slice to store the result
resultBytes := make([]byte, 0, numChunks*32)
// Process each 32-byte chunk
for i := 0; i < numChunks; i++ {
start := i * 32
end := start + 32
// Extract the value and key slices
valueChunk := valueBytes[start:end]
keyChunk := keyBytes[start:end]
// Perform encoding
chunkResult := encode([32]byte(valueChunk), [32]byte(keyChunk))
// Append the encoded chunk to the result
resultBytes = append(resultBytes, chunkResult[:]...)
}
// Write result to file
outputFilePath := os.Args[3]
err = ioutil.WriteFile(outputFilePath, resultBytes, 0644)
if err != nil {
log.Fatalf("Failed to write result to file: %v", err)
}
fmt.Println("Encoding result written to file:", outputFilePath)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment