AVB ( #BitcoinVillain )'s avatar
AVB ( #BitcoinVillain )
avb@zaps.lol
npub1sec6...p0l7
Historian, builder of tools, maker of chocolates and code. AVB_21 on X LN: mr21@walletofsatoshi.com
AVB ( #BitcoinVillain )'s avatar
AVB 6 months ago
Bitcoin education where people lead you to payable tools, hardware or services from the one 'educating', are usually a bad sign. Plus points if they're also shilling some tokens or newsletter. :)
AVB ( #BitcoinVillain )'s avatar
AVB 6 months ago
Math can be art. I've created a Bitcoin art piece, and it's only there for the ones that get it. BipRaffle
AVB ( #BitcoinVillain )'s avatar
AVB 6 months ago
Created this small variant on teh Say-le-clock , one where you get the time since last block as a decorative element in the background. It changes colors and displays whenever a block is found, without any strange elements or clutter.
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
I've added a simulator for 1 million deed phrase draws foe verifying that it's random. Find it all at the 'self test ' link at the bottom . Updated the mechanism and layout.
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
updated: There was a useless button still lingering in the interface, ans while I removed it, I've replaced one of the shuffle algos with something better, introduced prefetching and made everything 10% more random at least. Yeah. updated 8-rack - ... it's Seed Generation Bitcoin art Version 25.6.4 Released: June 8, 2025 What’s New: Bitcoin-Inspired Entropy Boost: Set PBKDF2 iterations in generateEntropySeed to 210,000—a nod to Bitcoin’s 21 million coin cap—for a slight randomness and security uplift. Initialization takes ~420-2100 ms, with the entropyLoader ensuring a smooth start, delivering high-entropy seeds worthy of crypto art. Unbiased WashShuffle: Upgraded to 30-34 iterations (randomized via 30 + (randomBytes[0] % 5)), up from 3-5, for a more unbiased secondary shuffle. This yields ~1440-1632 swaps (vs. ~144-240), erasing residual order with a touch of randomness in iteration count. Enhanced FractalCascadeShuffle: Now rocks 10 iterations (up from 3) with: 60 scatter swaps per iteration (up from 40, ~600 total). Replaced the biased Shuffle Sequence with an interleave shuffle algo with enough iterations Chunk swap size range expanded to 10-45 cards (from 15-30). Reverse probability boosted to 50% (~5 reverses vs. ~3). Swap distance constraint (Math.abs(src - dst) >= 10) for deeper mixing. Random byte buffer doubled to 1024 bytes for robust entropy. Logging trimmed to a sleek two-line summary. These tweaks deliver ~700-1050 swaps, ensuring near-perfect randomization. Supercharged RiffleShuffle: Now performs 10 riffles (up from 1), making it a top-tier unbiased secondary shuffle. This approximates a uniform 96-card deck distribution, banishing any trace of initial order. Impact: Top-Tier Randomness: Measurable gains in Spearman’s correlation (~0, “dissimilar”) and KL divergence (<0.01, “near perfect”/”perfect”) across shuffles, confirmed by in-game tests. Crypto-Grade Entropy: With 210,000 iterations and Web Crypto API, this release offers near-perfect randomness, ideal for offline play as a piece of Bitcoin-inspired digital art. Performance: Balanced for speed and quality, with initialization delays offset by clear loader feedback. Layout : Removed the useless "undo last draw" button (had no purpose as it was a legacy button from an earlier version where you could draw manually word per word) Color-scheme in the log is now more adjusted and uniform, no more pastel blue, the errors are in orange to red, depending on severity. Rest is either green or yellow The found words are in bitcoin logo color scheme. File Hashes: md5: DD135DBA4A2FCDE4F7A4E32A99470EB6 sha256: D1480DF3339E979567B42DC8DC6B8D910A531F9ECAE6ACC99F88A6D5B4C2E3E9
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
"8 rack" A piece of bitcoin encryption art in digital form. version 25.6.0 : Art can be encryption and encryption can be art. This is a fair distribution, shuffled, 3 card deck artwork that spews out seeds (on/offline) . It's beautiful math and encryption, balanced to fairly distribute 432 possibilities per BIP39 word. It's casino shufflin' great. image
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
GM friends. It's hard to plan ahead. Certainly if you're in a country that makes it so easy to be complacent and be "ok" with being extorted day in day out. Keep planning, keep going.
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
"Time is his enemy not ally, and it always wins in the end. The pose can only hold so long. You can’t keep scoring free fiat, without either die on low valuation and dilution, or without at least 20 other Strategy-grade businesses jumping in to take their piece of the pie. So far, surprisingly, none of these two things happen. He keeps getting free fiat from Wall Street investors, and no other Saylor stands up. This can’t last forever. One of the two will happen by end of 2025. Curtain call Saylor’s a fascinating watch, a mix of investor-backed bravado, brains, and borrowed billions. Is it a masterstroke or a bitcoin version of Worldcom? I’m not sure. In any case, I would only invest in MSTR myself if the company has a real added value for bitcoin development and the bitcoin ecosystem. They could be the engine, the spirit, the core of bitcoin. Yet they’re just doing the poses. Let your body move to the rhythm." image
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
Testing the bolt12 DNS address tips@alwaysvaluebitcoin.com Feel free to send anything to see if your wallet supports it. (LN or taproot Silent payments)
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
Presenting: bitraffle A one-button generator for bip39 words. Good entropy, salting, offline/online open source, funny, and you can use it mixed in to your own generation with dice or whatever you like. image
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
Yzer.io is actually pretty good. A bit more curation on older question would make it even better. image
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
I don't get why Bitcoin wallet devs, don't at least implement sending towards silent payments and paynyms. Even if you don't support it incoming... It's stemming adoption.
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
Testin some BIP353 the alwaysvaluebitcoin.com domain. It's now added to the allesvoorbitcoin.be/donate page. feel free to try and see if your wallet support sending to it (probably not) tips@alwaysvaluebitcoin.com image
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
I block these '21 bitfluencers' from now on. If you're only active when there are conference tickets to be scored, the f the f off.
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
Let's NiP05 scan the #spambots Better coders can finetune I suppose Assumptions and Setup Nostr Relay: You have a WebSocket connection to a Nostr relay (e.g., wss://relay.damus.io) to fetch events. NIP-05 Provider Data: You have a database or API with member public keys and their NIP-05 registration timestamps. Libraries: Uses websocket for Nostr relay communication, json for event parsing, and random for selecting replies. You may need additional libraries like requests for NIP-05 verification checks. Database: A simple SQLite database is assumed for storing member data, but you can adapt to your setup (e.g., MySQL, API). Bot Detection: Basic bot detection checks for identical or nonsensical replies using simple text comparison. You can enhance this with NLP libraries like nltk or textblob for advanced analysis. Script import websocket import json import time import random import sqlite3 from datetime import datetime, timedelta import requests import re from collections import Counter # Configuration RELAY_URL = "wss://relay.damus.io" # Replace with your relay DB_PATH = "nip05_members.db" # SQLite database for NIP-05 members TIME_WINDOW = 7 # Days to check for recent activity REPLY_SAMPLE_SIZE = 5 # Number of replies to analyze SIMILARITY_THRESHOLD = 0.9 # Jaccard similarity threshold for identical replies # Initialize database def init_db(): conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS members ( pubkey TEXT PRIMARY KEY, nip05_address TEXT, registration_timestamp INTEGER ) """) # Example: Populate with dummy data (replace with your actual data) cursor.execute("INSERT OR IGNORE INTO members VALUES (?, ?, ?)", ("b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9", "bob@example.com", int(time.time() - 86400 * 30))) conn.commit() return conn, cursor # Connect to Nostr relay def connect_to_relay(): ws = websocket.WebSocket() ws.connect(RELAY_URL) return ws # Fetch events from relay def fetch_events(ws, pubkey, since_timestamp, kind=1): subscription_id = f"scan_{pubkey[:8]}" filter = { "authors": [pubkey], "kinds": [kind], # kind=1 for posts/replies "since": since_timestamp } ws.send(json.dumps(["REQ", subscription_id, filter])) events = [] timeout = time.time() + 10 # 10-second timeout while time.time() < timeout: try: message = json.loads(ws.recv()) if message[0] == "EVENT" and message[1] == subscription_id: events.append(message[2]) except websocket.WebSocketTimeoutException: break ws.send(json.dumps(["CLOSE", subscription_id])) return events # Calculate Jaccard similarity between two texts def jaccard_similarity(text1, text2): if not text1 or not text2: return 0.0 set1 = set(re.findall(r'\w+', text1.lower())) set2 = set(re.findall(r'\w+', text2.lower())) intersection = len(set1 & set2) union = len(set1 | set2) return intersection / union if union > 0 else 0.0 # Check if text appears nonsensical (basic heuristic) def is_nonsense(text): # Basic check: too short, repetitive characters, or random strings if len(text) < 10: return True if re.match(r'^(.)\1{3,}$', text): # Repeated characters return True # Add more checks (e.g., entropy, common spam phrases) return False # Check NIP-05 registration status def check_nip05_status(pubkey, nip05_address): try: local_part, domain = nip05_address.split('@') url = f"https://{domain}/.well-known/nostr.json?name={local_part}" response = requests.get(url, timeout=5) if response.status_code == 200: data = response.json() if data.get("names", {}).get(local_part) == pubkey: return True return False except Exception as e: print(f"Error checking NIP-05 for {nip05_address}: {e}") return False # Main scanning function def scan_for_spam_bots(): conn, cursor = init_db() ws = connect_to_relay() # Get all members cursor.execute("SELECT pubkey, nip05_address, registration_timestamp FROM members") members = cursor.fetchall() # Calculate timestamp for 7 days ago since_timestamp = int((datetime.now() - timedelta(days=TIME_WINDOW)).timestamp()) log = [] for pubkey, nip05_address, reg_timestamp in members: print(f"Scanning {nip05_address} ({pubkey[:8]}...)") # Step 1: Check for at least one reply in the past 7 days events = fetch_events(ws, pubkey, since_timestamp, kind=1) replies = [e for e in events if "e" in e.get("tags", [])] # Events with 'e' tag are replies if len(replies) < 1: log.append({ "pubkey": pubkey, "nip05_address": nip05_address, "status": "No replies in past 7 days", "nip05_active": check_nip05_status(pubkey, nip05_address), "registration_date": datetime.fromtimestamp(reg_timestamp).isoformat() }) continue # Step 2: Analyze up to 5 random replies sample_replies = random.sample(replies, min(len(replies), REPLY_SAMPLE_SIZE)) suspicious = False reply_texts = [r["content"] for r in sample_replies] # Check for identical or similar replies for i, text1 in enumerate(reply_texts): for text2 in reply_texts[i+1:]: if jaccard_similarity(text1, text2) > SIMILARITY_THRESHOLD: suspicious = True break if suspicious: break # Check for nonsensical replies if not suspicious: suspicious = any(is_nonsense(text) for text in reply_texts) # Step 3: Check NIP-05 status (for logging only) nip05_active = check_nip05_status(pubkey, nip05_address) # Log results log.append({ "pubkey": pubkey, "nip05_address": nip05_address, "status": "Suspicious" if suspicious else "Clean", "reply_count": len(replies), "nip05_active": nip05_active, "registration_date": datetime.fromtimestamp(reg_timestamp).isoformat() }) ws.close() conn.close() # Save log to file with open("spam_scan_log.json", "w") as f: json.dump(log, f, indent=2) return log # Run the script if __name__ == "__main__": results = scan_for_spam_bots() print("Scan complete. Results saved to spam_scan_log.json") for result in results: print(result)
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
About the Yoda Speak Spambots on nostr: Can't be that hard to reject or even disable the NiP05 'verification'nog these bots after they've replied nonsense to random new people a couple of times. But seen the dismal state of some of these NiP05 providers (who paste a JSON and call it quits) ... We need more thinking. Maybe I'll code one myself.
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
How is that service called where we can follow some groupd of one sort of nostr people? I forgot the name. Nostr waves? Or nostr packs? Don't know anymore
AVB ( #BitcoinVillain )'s avatar
AVB 7 months ago
Anyone here who quit X completely and went only on Nostr? I'm still in doubt.