forked from cruzbit/cruzbit
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b50e1c2
Showing
1,071 changed files
with
510,342 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2019 cruzbit developers | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# cruzbit | ||
A simple decentralized peer-to-peer ledger implementation | ||
|
||
cruzbit is very similar to [bitcoin](https://www.bitcoin.com/bitcoin.pdf) with the following notable differences: | ||
|
||
* **Newer crypto** - The [Ed25519 signature system](https://ed25519.cr.yp.to/) is used for signing transactions. This system has a number of nice properties to protect users from security risks present with naive usage of ECDSA. The 256-bit version of the [SHA-3 hashing algorithm](https://en.wikipedia.org/wiki/SHA-3) is used for all non-signing hashing operations, including the proof-of-work function. It's reported to be | ||
[blazing fast](https://keccak.team/2017/is_sha3_slow.html) when implemented in hardware. [NaCl Secretbox](https://nacl.cr.yp.to/secretbox.html) is used to encrypt wallet private keys (not part of the protocol.) | ||
* **Simplified transaction format** - No inputs and outputs. Just public key sender and receiver with a time, amount, explicit fee, memo field, pseudo-random nonce, series and signature. The series is incremented network-wide roughly once a week based on block height to allow for pruning transaction history. Also included are 2 optional fields for specifying maturity and expiration, both at a given block height. | ||
* **No UTXO set** - This is a consequence of the second point. It considerably simplifies ledger construction and management as well as requires a wallet to know only about its public key balances and the current block height. It also allows the ledger to map more directly to the well-understood concept of a [double-entry bookkeeping system](https://en.wikipedia.org/wiki/Double-entry_bookkeeping_system). In cruzbit, the sum of all public key balances must equal the issuance at the current block height. This isn't the first ledger to get rid of the UTXO set model but I think we do it in a uniquely simple way. | ||
* **No scripting** - This is another consequence of the second point. Signatures are simply signatures and not tiny scripts. It's a bit simpler and arguably safer. It does limit functionality, e.g. there is no native notion of a multi-signature transaction, however, depending on your needs, you can come _close_ to accomplishing that using [mechanisms external to cruzbit](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing). | ||
* **No fixed block size limit** - Since transactions in cruzbit are more-or-less fixed size we cap blocks by transaction count instead, with the initial limit being 10,000 transactions. This per-block transaction limit increases with "piecewise-linear-between-doublings growth." This means the limit doubles roughly every 2 years by block height and increases linearly between doublings up until a hard limit of 2,147,483,647. This was directly inspired by [BIP 101](https://github.com/bitcoin/bips/blob/master/bip-0101.mediawiki). We use block height instead of time since another change in cruzbit is that all block headers contain the height (as well as the total cumulative chain work.) | ||
* **Reference implementation is in [Go](https://golang.org/)** - Perhaps more accessible than C++. Hopefully it makes blockchain programming a bit easier to understand and attracts a wider variety of developer interest. | ||
* **Web-friendly peer protocol** - Peer communication is via secure [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API). And the peer protocol and all primitives are structured in [JSON](https://www.json.org/). This should make working with the protocol easy for just about every modern development environment. | ||
|
||
## Why does cruzbit exist? | ||
|
||
I noticed most people focusing on making more complex ledgers capable of executing "smart" contracts and/or crypto-magically obscuring transaction details and such. And I think those projects are pretty cool, but I'd always wanted to attempt to do the opposite and implement the simplest decentralized ledger I possibly could given lessons learned from bitcoin. I _think_ that's what cruzbit is. Anything that I thought wasn't strictly necessary in bitcoin, or was otherwise weird, I got rid of. I wanted the design to be conceptually simple and extremely developer-friendly. I finally had some personal time on my hands so I decided, why not. And now cruzbit exists. | ||
|
||
## Getting started mining | ||
|
||
If you missed out on the opportunity to mine other cryptocurrencies you could give cruzbit a try! | ||
|
||
1. [Install Go](https://golang.org/doc/install) | ||
2. Install the [wallet](https://github.com/cruzbit/cruzbit/tree/master/wallet) | ||
3. Run the wallet and issue a `newkey` command. Record the public key. | ||
4. Install the [client](https://github.com/cruzbit/cruzbit/tree/master/client) | ||
5. Run the client using the public key from step 4. as the `-pubkey` argument. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// Copyright 2019 cruzbit developers | ||
// Use of this source code is governed by a MIT-style license that can be found in the LICENSE file. | ||
|
||
package cruzbit | ||
|
||
import ( | ||
"golang.org/x/crypto/ed25519" | ||
) | ||
|
||
// BalanceCache maintains a partial unconfirmed view of the ledger. | ||
// It's used by Ledger when (dis-)connecting blocks and by TransactionQueueMemory | ||
// when deciding whether or not to add a transaction to the queue. | ||
type BalanceCache struct { | ||
ledger Ledger | ||
minBalance int64 | ||
cache map[[ed25519.PublicKeySize]byte]int64 | ||
} | ||
|
||
// NewBalanceCache returns a new instance of a BalanceCache. | ||
func NewBalanceCache(ledger Ledger, minBalance int64) *BalanceCache { | ||
b := &BalanceCache{ledger: ledger, minBalance: minBalance} | ||
b.Reset() | ||
return b | ||
} | ||
|
||
// Reset resets the balance cache. | ||
func (b *BalanceCache) Reset() { | ||
b.cache = make(map[[ed25519.PublicKeySize]byte]int64) | ||
} | ||
|
||
// Apply applies the effect of the transaction to the invovled parties' cached balances. | ||
// It returns false if sender balance would go negative as a result of applying this transaction. | ||
// It also returns false if a remaining non-zero sender balance would be less than minBalance. | ||
func (b *BalanceCache) Apply(tx *Transaction) (bool, error) { | ||
if !tx.IsCoinbase() { | ||
// check and debit sender balance | ||
var fpk [ed25519.PublicKeySize]byte | ||
copy(fpk[:], tx.From) | ||
senderBalance, ok := b.cache[fpk] | ||
if !ok { | ||
var err error | ||
senderBalance, err = b.ledger.GetPublicKeyBalance(tx.From) | ||
if err != nil { | ||
return false, err | ||
} | ||
} | ||
totalSpent := tx.Amount + tx.Fee | ||
if totalSpent > senderBalance { | ||
return false, nil | ||
} | ||
senderBalance -= totalSpent | ||
if senderBalance > 0 && senderBalance < b.minBalance { | ||
return false, nil | ||
} | ||
b.cache[fpk] = senderBalance | ||
} | ||
|
||
// credit recipient balance | ||
var tpk [ed25519.PublicKeySize]byte | ||
copy(tpk[:], tx.To) | ||
recipientBalance, ok := b.cache[tpk] | ||
if !ok { | ||
var err error | ||
recipientBalance, err = b.ledger.GetPublicKeyBalance(tx.To) | ||
if err != nil { | ||
return false, err | ||
} | ||
} | ||
recipientBalance += tx.Amount | ||
b.cache[tpk] = recipientBalance | ||
return true, nil | ||
} | ||
|
||
// Undo undoes the effects of a transaction on the invovled parties' cached balances. | ||
func (b *BalanceCache) Undo(tx *Transaction) error { | ||
if !tx.IsCoinbase() { | ||
// credit balance for sender | ||
var fpk [ed25519.PublicKeySize]byte | ||
copy(fpk[:], tx.From) | ||
senderBalance, ok := b.cache[fpk] | ||
if !ok { | ||
var err error | ||
senderBalance, err = b.ledger.GetPublicKeyBalance(tx.From) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
totalSpent := tx.Amount + tx.Fee | ||
senderBalance += totalSpent | ||
b.cache[fpk] = senderBalance | ||
} | ||
|
||
// debit recipient balance | ||
var tpk [ed25519.PublicKeySize]byte | ||
copy(tpk[:], tx.To) | ||
recipientBalance, ok := b.cache[tpk] | ||
if !ok { | ||
var err error | ||
recipientBalance, err = b.ledger.GetPublicKeyBalance(tx.To) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
if recipientBalance < tx.Amount { | ||
panic("Recipient balance went negative") | ||
} | ||
b.cache[tpk] = recipientBalance - tx.Amount | ||
return nil | ||
} | ||
|
||
// Balances returns the underlying cache of balances. | ||
func (b *BalanceCache) Balances() map[[ed25519.PublicKeySize]byte]int64 { | ||
return b.cache | ||
} |
Oops, something went wrong.