Open p4u opened 8 months ago
The way we create census keys has changed to include the Farcaster ID (FID).
Here is the Go reference implementation
func NewFarcasterVoterID(publicKey []byte, fid uint64) []byte {
fidBytes := make([]byte, 8)
binary.LittleEndian.PutUint64(fidBytes, fid)
hashedPubKey := keccack(append(publicKey, fidBytes...))
return hashedPubKey[:20]
}
And here the proposed implementation made by chatGPT
import { keccak256 } from 'js-sha3';
/**
* Generate a Farcaster Voter ID based on the public key and fid.
*
* @param {Uint8Array} publicKey - The public key as a byte array.
* @param {number} fid - The fid as a number.
* @returns {Uint8Array} - The first 20 bytes of the keccak256 hash of the combined input.
*/
function newFarcasterVoterID(publicKey: Uint8Array, fid: number): Uint8Array {
// Create an 8-byte array to hold the little-endian representation of fid
const fidBytes = new Uint8Array(8);
// Convert fid to a little-endian byte array
for (let i = 0; i < 8; i++) {
fidBytes[i] = fid & 0xff; // Get the least significant byte of fid
fid = fid >> 8; // Shift fid right by 8 bits to process the next byte
}
// Create a new array to hold the combined publicKey and fidBytes
const combined = new Uint8Array(publicKey.length + fidBytes.length);
// Copy publicKey into the combined array
combined.set(publicKey);
// Copy fidBytes into the combined array, starting after the publicKey
combined.set(fidBytes, publicKey.length);
// Hash the combined array using keccak256 and convert the result to an ArrayBuffer
const hashedPubKey = keccak256.arrayBuffer(combined);
// Return the first 20 bytes of the hashed public key
return new Uint8Array(hashedPubKey).slice(0, 20);
}
Here some test data
var frameVote1 = farcasterFrame{
signedMessage: "0a8b01080d109fc20e18b4a7f52e200182017b0a5b68747470733a2f2f63656c6f6e692e766f63646f6e692e6e65742f3633663537626539386638303666393539323134623435383165623837393165366338306561663732313032643465393366373631303030303030303030303310011a1a089fc20e1214000000000000000000000000000000000000000112142d9bd29806c7e54cf5f80f98d9adf710a2ebc58518012240379f4f9897901b24544fba46fcb51183f79d79a5041c47f554c5a4e407c020fdbf43ef27490b944e05372850b1dc78dd97c728a88bdbc14f0174ed589c795a0928013220ec327cd438995a59ce78fddd29631e9b2e41eafc3a6946dd26b4da749f47140d",
pubkey: "ec327cd438995a59ce78fddd29631e9b2e41eafc3a6946dd26b4da749f47140d",
buttonIndex: 1,
fid: 237855,
}
var frameVote2 = farcasterFrame{
buttonIndex: 3,
signedMessage: "0a8901080d10e04e18d1aaf52e200182017a0a5b68747470733a2f2f63656c6f6e692e766f63646f6e692e6e65742f3633663537626539386638303666393539323134623435383165623837393165366338306561663732313032643465393366373631303030303030303030303310031a1908e04e12140000000000000000000000000000000000000001121496f560a1f5c90fa24278277321d7be35d18cf0711801224029863962ecff4b7db6dd8736fc1c238ed6ed5a147d3a36e6eac32e06f10d2dcc1df1618d5da6ce21286e0233656ef985a5b1cced2bee5f2cbb4fd1bfc168aa0128013220d6424e655287aa61df38205da19ddab23b0ff9683c6800e0dbc3e8b65d3eb2e3",
pubkey: "d6424e655287aa61df38205da19ddab23b0ff9683c6800e0dbc3e8b65d3eb2e3",
fid: 10080,
}
New protobuf models
There is a new protobuf Proof model:
signedFrameMessageBody
This is a byte buffer that comes from the farcaster frame Specification
When a user interacts with a Frame backend, the backend receives the following JSON object:
The messageBytes is signed by the user publicKey. So in the Vochain we can extract it and check the publicKey is on the census.
censusProof
This is a standard OFF_CHAIN_TREE_WEIGHTED arbo based census proof (the same we use for standard voting). This proof is used to verify the pubKey extracted from the farcaster message is actually on the census.
publicKey
This is the publicKey extracted from the farcaster message, to facilitate the Vochain vote verification
The Arbo census
This is a standard census, but since the publicKeys of Farcaster are not Ethereum addresses but ed25519 public keys, we introduce a way to create farcaster addresses, this is:
keccack256(publicKey)[:20]
.So the census3 or other census based services need to implement these kind of addresses. Usually a pure farcaster census would be then:
Restrictions
Expected implementation on the SDK
The SDK could just facilitate create farcaster elections and help build and send farcaster votes. Meaning that we might skip the farcaster frame specific details, such as the Message Frame JSON or the Farcaster Protobuf model.
There are many libraries around that allow deserialize the farcaster message and extract the public key, we can just ask the user of the SDK to introduce such data.
[x] The SDK should allow creating a vote given:
[1]
for button=1) Create the vote transaction and send it to the Vochain.Testing
For the tests, we can use hardcoded examples for publicKeys and signedMessages as the ones provided here https://github.com/vocdoni/vocdoni-node/blob/main/test/farcaster_test.go#L291