diff options
author | Joop Kiefte <ikojba@gmail.com> | 2021-12-10 13:01:14 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-10 13:01:14 +0000 |
commit | 7aa71680132984ba729c12af727fddd6d23670d2 (patch) | |
tree | 8cc5be934b5f6a0720245f0f2e1b8f365e26eec7 /message | |
parent | f0b034381cb18671b9ffe718b01ed429c33fbd12 (diff) |
Implement Proof of Work
Diffstat (limited to 'message')
-rw-r--r-- | message/message.go | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/message/message.go b/message/message.go new file mode 100644 index 0000000..14e9cac --- /dev/null +++ b/message/message.go @@ -0,0 +1,72 @@ +package message + +import ( + "crypto/sha256" + "fmt" + "math/bits" +) + +// Messages on Infodump use a "stamp" using the hashcash algorithm to prevent spam and enable storing messages by importance +// The Message type contains the message itself and a nonce that is used to verify the stamp +type Message struct { + Message string + Nonce int +} + +// Proof of Work: Find the nonce for a message by hashing the message and checking for at least n initial zeroes in the binary representation of the resulting hash +func (msg *Message) ProofOfWork(n int) { + // Create a local copy of the message and start counting + m := *msg + m.Nonce = 0 + // Loop until we find a nonce that satisfies the proof of work + for { + // Increment the nonce and hash the message + m.Nonce++ + hash := m.Hash() + // If the hash has at least n initial zeroes, we have found a valid nonce + if CountLeadingZeroes(hash) >= n { + break + } + } + // Set the message to the local copy + *msg = m +} + +// Get the SHA256 hash of a message plus the nonce as a byte slice +func (m *Message) Hash() [32]byte { + hash := sha256.Sum256([]byte(fmt.Sprintf("%s%d", m.Message, m.Nonce))) + return hash +} + +// Bitwise count leading zeroes in a byte slice +func CountLeadingZeroes(b [32]byte) int { + count := 0 + for _, v := range b { + // If the byte is zero, that means there are 8 leading zeroes and we need to continue counting + if v == 0 { + count += 8 + } else { // Otherwise, we add the number of leading zeroes in the byte and stop counting + // Bitwise count leading zeroes in the byte + count += bits.LeadingZeros8(v) + // If the byte is not zero, we can stop counting + break + } + } + return count +} + +// Get the stamp of the message +func (m *Message) Stamp() string { + return fmt.Sprintf("%x", m.Hash()) +} + +// Lead is a method that returns the number of leading zeroes in the hash of a message plus its nonce +func (m *Message) Lead() int { + return CountLeadingZeroes(m.Hash()) +} + +func New(msg string, n int) *Message { + m := Message{Message: msg} + m.ProofOfWork(n) + return &m +} |