Transaction

2EF0F79DACC046…F246B1D6DC2C

Block 25,941 · index 1 · indexed

Summary

Hash
2EF0F79DACC046861214050F5700716C15827875E7DA658FCA59F246B1D6DC2C
Block
25,941
Size
5403 bytes
Gas used
9,784,080 / 11,740,956
Fee
1000000ugnot
Memo
gnopublish
Status
success

Messages

#1AddPackagegno.land/p/moul/x/daily/luhn/v09 arguments

Arguments · 9

  1. #1luhn
  2. #2README.md
  3. #3# `gno.land/p/moul/x/daily/luhn/v0` **Luhn mod-10 checksum** — `Valid`, `CheckDigit`, `Append`, `MaxLen`. The check behind credit-card numbers, IMEIs and many national ID schemes (Hans Peter Luhn, 1954). Spaces and hyphens are ignored, so the formatting a human would paste works as-is. ```go import "gno.land/p/moul/x/daily/luhn/v0" luhn.Valid("4539 1488 0343 6467") // true — separators ignored luhn.Valid("4539148803436468") // false — one digit off luhn.CheckDigit("7992739871") // 3, true luhn.Append("7992739871") // "79927398713", true ``` > ⚠️ **A typo check, not a security check.** Luhn catches every single-digit > error and nearly every transposition of adjacent digits, but anyone can > compute a valid number in a second, and validity says nothing about whether > the identifier exists. Never use it to authorize anything on-chain. `MaxLen` (64) bounds an input so validation gas stays predictable. Note that a string of zeros is technically Luhn-valid and is accepted — reject it in the caller if your domain needs to. **Live demo:** [`r/moul/x/daily/luhndemo`](https://github.com/moul/gno-contracts/tree/main/r/moul/x/daily/luhndemo/v0) · render it at [`/r/moul/x/daily/luhndemo/v0`](https://gno.land/r/moul/x/daily/luhndemo/v0). <!-- BEGIN GNOCONTRACTS FOOTER (generated by `make readmes`; do not edit below) --> --- Part of **[moul/gno-contracts](https://github.com/moul/gno-contracts)** — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage. > 🧪 **Highly experimental — potentially vibe-coded.** Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: [DISCLAIMER](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md). <!-- END GNOCONTRACTS FOOTER -->
  4. #4gnomod.toml
  5. #5module = "gno.land/p/moul/x/daily/luhn/v0" gno = "0.9"
  6. #6luhn.gno
  7. #7// Package luhn implements the Luhn mod-10 checksum (Hans Peter Luhn, 1954) as // a pure, reusable package: the check used by credit-card numbers, IMEIs and // many national ID schemes to catch typos and single-digit transpositions. // // It is a *checksum*, not a security primitive: it detects every single-digit // error and almost every adjacent transposition, but it is trivial to forge and // says nothing about whether an identifier actually exists. Never use it to // authorize anything on-chain. // // No clocks, no randomness, no chain imports — same input, same output. // // A live demo of this package is at // [r/moul/x/daily/luhndemo](/r/moul/x/daily/luhndemo/v0). package luhn import ( "strings" ) // MaxLen bounds an input so validation gas stays predictable. const MaxLen = 64 // Valid reports whether s carries a correct Luhn check digit. // // Spaces and hyphens are ignored, so "4539 1488 0343 6467" and // "4539-1488-0343-6467" both work. Any other non-digit makes it false, as does // an empty/1-digit input or one longer than MaxLen. A string of all zeros is // technically Luhn-valid and is accepted — reject it in the caller if your // domain needs to. func Valid(s string) bool { digits, ok := clean(s) if !ok || len(digits) < 2 { return false } return sum(digits)%10 == 0 } // CheckDigit returns the digit that must be appended to payload to make the // whole string Luhn-valid, and whether the payload was usable. func CheckDigit(payload string) (int, bool) { digits, ok := clean(payload) if !ok || len(digits) == 0 { return 0, false } // The check digit sits in the "doubled" position of the final number, so // compute the sum as if a 0 had already been appended. total := sum(append(digits, 0)) return (10 - total%10) % 10, true } // Append returns payload with its Luhn check digit appended (digits only, // separators stripped), and whether the payload was usable. func Append(payload string) (string, bool) { d, ok := CheckDigit(payload) if !ok { return "", false } digits, _ := clean(payload) var b strings.Builder for _, x := range digits { b.WriteByte(byte('0' + x)) } b.WriteByte(byte('0' + d)) return b.String(), true } // clean turns s into its digit values, ignoring spaces and hyphens. ok is false // if any other character appears or the input exceeds MaxLen. func clean(s string) ([]int, bool) { if len(s) > MaxLen { return nil, false } digits := make([]int, 0, len(s)) for i := 0; i < len(s); i++ { c := s[i] switch { case c >= '0' && c <= '9': digits = append(digits, int(c-'0')) case c == ' ' || c == '-': // separator: ignore default: return nil, false } } return digits, true } // sum computes the Luhn total: walking right to left, every second digit is // doubled, and a double of 10 or more has 9 subtracted (equivalent to adding // its two decimal digits). func sum(digits []int) int { total := 0 double := false for i := len(digits) - 1; i >= 0; i-- { d := digits[i] if double { d *= 2 if d > 9 { d -= 9 } } total += d double = !double } return total }
  8. #8/gno.MemPackageType
  9. #9 MPUserProd

Result log

msg:0,success:true,log:,events:[]

← Back to block 25,941