package main import ( "bytes" "log" "math/big" "os" "strconv" "time" "github.com/deroproject/derohe/blockchain" "github.com/deroproject/derohe/cryptography/bn256" "github.com/deroproject/derohe/cryptography/crypto" "github.com/deroproject/derohe/rpc" "github.com/deroproject/derohe/transaction" ) const atomic_units = int64(100000) var target = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} var progress, max uint64 var upper_limit int64 = 100 func main() { if len(os.Args) < 2 { log.Println("No args") return } if len(os.Args) == 3 { upper, err := strconv.ParseInt(os.Args[2], 10, 64) if err != nil { upper_limit = upper } } chain, err := blockchain.Blockchain_Start(nil) if err != nil { log.Println("Chain error") return } txid := os.Args[1] tx_hash := crypto.HashHexToHash(txid) log.Printf("Upper limit set to %d Dero\n", upper_limit) log.Printf("Checking TXID %s\n", txid) _, _, valid := chain.IS_TX_Valid(tx_hash) if !valid { log.Println("TX is not valid") return } var tx transaction.Transaction tx_data, err := chain.Store.Block_tx_store.ReadTX(tx_hash) if err != nil { log.Printf("Can't read TX; %v\n", err) return } err = tx.Deserialize(tx_data) if err != nil { log.Println("Can't deserialize TX") return } err = chain.Expand_Transaction_NonCoinbase(&tx) if err != nil { log.Println("Can't expand TX") return } var wait uint64 for _, p := range tx.Payloads { max = uint64(upper_limit) * uint64(atomic_units) * p.Statement.RingSize t_now := time.Now() for i := uint64(0); i < p.Statement.RingSize; i++ { go bruteforce(i, &p, &wait) wait++ } t_log := time.Now() for wait == p.Statement.RingSize { if progress > 0 { if time.Since(t_log) > time.Second*10 { log.Printf("%.2f%% done\n", float64(float64(progress)/float64(max)*100)) t_log = time.Now() } } } wait = 0 duration := time.Since(t_now) log.Printf("Operation took %s\n", duration.String()) } } func bruteforce(i uint64, p *transaction.AssetPayload, wg *uint64) { var payload [145]byte commitment := p.Statement.C[i] for j := int64(0); j <= upper_limit*atomic_units; j += 10 { copy(payload[:transaction.PAYLOAD_LIMIT], p.RPCPayload[:transaction.PAYLOAD_LIMIT]) shared_key := get_hash(commitment, j) crypto.EncryptDecryptUserData(crypto.Keccak256(shared_key[:], p.Statement.Publickeylist[i].EncodeCompressed()), payload[:]) if bytes.Compare(payload[100:116], target) == 0 { var sender_addr *rpc.Address var entry rpc.Entry sender_idx := uint(payload[0]) if sender_idx <= 128 && sender_idx != uint(i) { sender_addr, _ = rpc.NewAddressFromCompressedKeys(p.Statement.Publickeylist[sender_idx].EncodeCompressed()) log.Printf("Sender: %s\n", sender_addr.String()) } recv_addr, _ := rpc.NewAddressFromCompressedKeys(p.Statement.Publickeylist[i].EncodeCompressed()) log.Printf("Receiver: %s\n", recv_addr.String()) log.Printf("Amount: %.5f\n", float64(j)/float64(atomic_units)) entry.Payload = append(entry.Payload, payload[1:]...) args, _ := entry.ProcessPayload() for _, p := range args { if p.Name == "D" { log.Printf("Destination Port: %d\n", p.Value.(uint64)) } if p.Name == "C" { log.Printf("Comment: %s\n", p.Value.(string)) } } *wg-- return } } for j := int64(0); j <= upper_limit*atomic_units; j++ { copy(payload[:transaction.PAYLOAD_LIMIT], p.RPCPayload[:transaction.PAYLOAD_LIMIT]) shared_key := get_hash(commitment, j) crypto.EncryptDecryptUserData(crypto.Keccak256(shared_key[:], p.Statement.Publickeylist[i].EncodeCompressed()), payload[:]) if bytes.Compare(payload[100:116], target) == 0 { var sender_addr *rpc.Address sender_idx := uint(payload[0]) if sender_idx <= 128 && sender_idx != uint(i) { sender_addr, _ = rpc.NewAddressFromCompressedKeys(p.Statement.Publickeylist[sender_idx].EncodeCompressed()) log.Printf("Sender: %s\n", sender_addr.String()) } recv_addr, _ := rpc.NewAddressFromCompressedKeys(p.Statement.Publickeylist[i].EncodeCompressed()) log.Printf("Receiver: %s\n", recv_addr.String()) log.Printf("Amount: %.5f\n", float64(j)/float64(atomic_units)) *wg-- return } progress++ } *wg-- } func get_hash(c *bn256.G1, num int64) crypto.Hash { var x bn256.G1 x.Add(new(bn256.G1).Set(c), new(bn256.G1).ScalarMult(crypto.G, new(big.Int).SetInt64(0-num))) compressed := x.EncodeCompressed() if len(compressed) != 33 { panic("point compression needs to be fixed") } return crypto.Keccak256(compressed[:]) }