Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove pub key as field from inputs and outputs #68

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
62 changes: 31 additions & 31 deletions pkg/chain/explorer/explorer.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,15 @@ func (explorer *ChainExplorer) GetAllHeaders() ([]*kernel.BlockHeader, error) {
return headers, nil
}

func (explorer *ChainExplorer) FindUnspentTransactions(pubKey string) ([]*kernel.Transaction, error) {
return explorer.findUnspentTransactions(pubKey, iterator.NewReverseBlockIterator(explorer.store))
func (explorer *ChainExplorer) FindUnspentTransactions(address string) ([]*kernel.Transaction, error) {
return explorer.findUnspentTransactions(address, iterator.NewReverseBlockIterator(explorer.store))
}

// findUnspentTransactions finds all unspent transaction outputs that can be unlocked with the given address. Starts
// by checking the outputs and later the inputs, this is done this way in order to follow the inverse flow
// of transactions
// todo() remove this method, we will be using findUnspentOutputs instead most likely
func (explorer *ChainExplorer) findUnspentTransactions(pubKey string, it iterator.BlockIterator) ([]*kernel.Transaction, error) { //nolint:gocognit // ok for now
func (explorer *ChainExplorer) findUnspentTransactions(address string, it iterator.BlockIterator) ([]*kernel.Transaction, error) { //nolint:gocognit // ok for now
var nextBlock *kernel.Block
var unspentTXs []*kernel.Transaction

Expand Down Expand Up @@ -213,16 +213,16 @@ func (explorer *ChainExplorer) findUnspentTransactions(pubKey string, it iterato

// iterate through each transaction in the block
for _, tx := range nextBlock.Transactions {
txID := hex.EncodeToString(tx.ID)
txID := fmt.Sprintf("%x", tx.ID)

for outIdx, out := range tx.Vout {
// in case is already spent, continue
if isOutputSpent(spentTXOs, txID, uint(outIdx)) {
continue
}

// check if the output can be unlocked with the given pubKey
if out.CanBeUnlockedWith(pubKey) {
// check if the output can be unlocked with the given address
if out.CanBeUnlockedWith(address) {
unspentTXs = append(unspentTXs, tx)
}
}
Expand All @@ -234,8 +234,8 @@ func (explorer *ChainExplorer) findUnspentTransactions(pubKey string, it iterato

// if not coinbase, iterate through inputs and save the already spent outputs
for _, in := range tx.Vin {
if in.CanUnlockOutputWith(pubKey) {
inTxID := hex.EncodeToString(in.Txid)
if in.CanUnlockOutputWith(address) {
inTxID := fmt.Sprintf("%x", in.Txid)

// mark the output as spent
spentTXOs[inTxID] = append(spentTXOs[inTxID], in.Vout)
Expand All @@ -250,12 +250,12 @@ func (explorer *ChainExplorer) findUnspentTransactions(pubKey string, it iterato
return unspentTXs, nil
}

func (explorer *ChainExplorer) FindUnspentOutputs(pubKey string) ([]*kernel.UTXO, error) {
return explorer.findUnspentOutputs(pubKey, iterator.NewReverseBlockIterator(explorer.store))
func (explorer *ChainExplorer) FindUnspentOutputs(address string) ([]*kernel.UTXO, error) {
return explorer.findUnspentOutputs(address, iterator.NewReverseBlockIterator(explorer.store))
}

// findUnspentOutputs finds all unspent outputs that can be unlocked with the given public key
func (explorer *ChainExplorer) findUnspentOutputs(pubKey string, it iterator.BlockIterator) ([]*kernel.UTXO, error) { //nolint:gocognit // ok for now
func (explorer *ChainExplorer) findUnspentOutputs(address string, it iterator.BlockIterator) ([]*kernel.UTXO, error) { //nolint:gocognit // ok for now
var nextBlock *kernel.Block
unspentTXOs := []*kernel.UTXO{}
spentTXOs := make(map[string][]uint)
Expand All @@ -269,7 +269,7 @@ func (explorer *ChainExplorer) findUnspentOutputs(pubKey string, it iterator.Blo
_ = it.Initialize(lastBlock.Hash)

for it.HasNext() {
// get the next block using the revIterator
// get the next block using the reverted Iterator
nextBlock, err = it.GetNextBlock()
if err != nil {
return []*kernel.UTXO{}, err
Expand All @@ -288,8 +288,8 @@ func (explorer *ChainExplorer) findUnspentOutputs(pubKey string, it iterator.Blo
continue
}

// check if the output can be unlocked with the given pubKey
if out.CanBeUnlockedWith(pubKey) {
// check if the output can be unlocked with the given address
if out.CanBeUnlockedWith(address) {
unspentTXOs = append(unspentTXOs, &kernel.UTXO{
TxID: tx.ID,
OutIdx: uint(outIdx),
Expand All @@ -305,7 +305,7 @@ func (explorer *ChainExplorer) findUnspentOutputs(pubKey string, it iterator.Blo

// if not coinbase, iterate through inputs and save the already spent outputs
for _, in := range tx.Vin {
if in.CanUnlockOutputWith(pubKey) {
if in.CanUnlockOutputWith(address) {
// mark the output as spent
spentTXOs[string(in.Txid)] = append(spentTXOs[string(in.Txid)], in.Vout)
}
Expand All @@ -317,18 +317,18 @@ func (explorer *ChainExplorer) findUnspentOutputs(pubKey string, it iterator.Blo
return unspentTXOs, nil
}

func (explorer *ChainExplorer) CalculateAddressBalance(pubKey string) (uint, error) {
unspentTXs, err := explorer.FindUnspentTransactionsOutputs(pubKey)
func (explorer *ChainExplorer) CalculateAddressBalance(address string) (uint, error) {
unspentTXs, err := explorer.FindUnspentTransactionsOutputs(address)
if err != nil {
return 0, err
}

return retrieveBalanceFromUTXOs(unspentTXs), nil
}

func (explorer *ChainExplorer) FindAmountSpendableOutputs(pubKey string, amount uint) (uint, map[string][]uint, error) {
func (explorer *ChainExplorer) FindAmountSpendableOutputs(address string, amount uint) (uint, map[string][]uint, error) {
unspentOutputs := make(map[string][]uint)
unspentTXs, err := explorer.FindUnspentTransactions(pubKey)
unspentTXs, err := explorer.FindUnspentTransactions(address)
if err != nil {
return uint(0), unspentOutputs, err
}
Expand All @@ -340,7 +340,7 @@ func (explorer *ChainExplorer) FindAmountSpendableOutputs(pubKey string, amount
txID := hex.EncodeToString(tx.ID)

for outIdx, out := range tx.Vout {
if out.CanBeUnlockedWith(pubKey) {
if out.CanBeUnlockedWith(address) {
accumulated += out.Amount
unspentOutputs[txID] = append(unspentOutputs[txID], uint(outIdx))

Expand All @@ -352,15 +352,15 @@ func (explorer *ChainExplorer) FindAmountSpendableOutputs(pubKey string, amount
}
}

// there is a chance that we don't have enough amount for this pubKey
// there is a chance that we don't have enough amount for this address
return accumulated, unspentOutputs, nil
}

func (explorer *ChainExplorer) FindAllTransactions(pubKey string) ([]*kernel.Transaction, error) {
return explorer.findAllTransactions(pubKey, iterator.NewReverseBlockIterator(explorer.store))
func (explorer *ChainExplorer) FindAllTransactions(address string) ([]*kernel.Transaction, error) {
return explorer.findAllTransactions(address, iterator.NewReverseBlockIterator(explorer.store))
}

func (explorer *ChainExplorer) findAllTransactions(pubKey string, it iterator.BlockIterator) ([]*kernel.Transaction, error) {
func (explorer *ChainExplorer) findAllTransactions(address string, it iterator.BlockIterator) ([]*kernel.Transaction, error) {
var nextBlock *kernel.Block
var unspentTXs []*kernel.Transaction

Expand All @@ -387,8 +387,8 @@ func (explorer *ChainExplorer) findAllTransactions(pubKey string, it iterator.Bl
// iterate through each transaction in the block
for _, tx := range nextBlock.Transactions {
for _, out := range tx.Vout {
// check if the output can be unlocked with the given pubKey
if out.CanBeUnlockedWith(pubKey) {
// check if the output can be unlocked with the given address
if out.CanBeUnlockedWith(address) {
unspentTXs = append(unspentTXs, tx)
}
}
Expand All @@ -404,21 +404,21 @@ func (explorer *ChainExplorer) findAllTransactions(pubKey string, it iterator.Bl
return unspentTXs, nil
}

func (explorer *ChainExplorer) FindUnspentTransactionsOutputs(pubKey string) ([]kernel.TxOutput, error) {
unspentTransactions, err := explorer.FindUnspentTransactions(pubKey)
func (explorer *ChainExplorer) FindUnspentTransactionsOutputs(address string) ([]kernel.TxOutput, error) {
unspentTransactions, err := explorer.FindUnspentTransactions(address)
if err != nil {
return []kernel.TxOutput{}, err
}

return explorer.findUnspentTransactionsOutputs(pubKey, unspentTransactions)
return explorer.findUnspentTransactionsOutputs(address, unspentTransactions)
}

func (explorer *ChainExplorer) findUnspentTransactionsOutputs(pubKey string, unspentTransactions []*kernel.Transaction) ([]kernel.TxOutput, error) {
func (explorer *ChainExplorer) findUnspentTransactionsOutputs(address string, unspentTransactions []*kernel.Transaction) ([]kernel.TxOutput, error) {
var utxos []kernel.TxOutput

for _, tx := range unspentTransactions {
for _, out := range tx.Vout {
if out.CanBeUnlockedWith(pubKey) {
if out.CanBeUnlockedWith(address) {
utxos = append(utxos, out)
}
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/chain/explorer/explorer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ var Block2 = Block{ //nolint:gochecknoglobals // data that is used across all te
{
ID: []byte("regular-transaction-block-2-id"),
Vin: []TxInput{
NewInput([]byte("coinbase-transaction-block-1-id"), 0, "pubKey-2", "pubKey-2"),
NewInput([]byte("coinbase-transaction-block-1-id"), 0, "pubKey-2"),
},
Vout: []TxOutput{
NewOutput(2, script.P2PK, "pubKey-3"),
Expand Down Expand Up @@ -119,8 +119,8 @@ var Block3 = Block{ //nolint:gochecknoglobals // data that is used across all te
{
ID: []byte("regular-transaction-block-3-id"),
Vin: []TxInput{
NewInput([]byte("regular-transaction-block-2-id"), 1, "pubKey-4", "pubKey-4"),
NewInput([]byte("regular-transaction-block-2-id"), 2, "pubKey-5", "pubKey-5"),
NewInput([]byte("regular-transaction-block-2-id"), 1, "pubKey-4"),
NewInput([]byte("regular-transaction-block-2-id"), 2, "pubKey-5"),
},
Vout: []TxOutput{
NewOutput(4, script.P2PK, "pubKey-2"),
Expand All @@ -131,7 +131,7 @@ var Block3 = Block{ //nolint:gochecknoglobals // data that is used across all te
{
ID: []byte("regular-transaction-2-block-3-id"),
Vin: []TxInput{
NewInput([]byte("regular-transaction-block-2-id"), 0, "pubKey-3", "pubKey-3"),
NewInput([]byte("regular-transaction-block-2-id"), 0, "pubKey-3"),
},
Vout: []TxOutput{
NewOutput(1, script.P2PK, "pubKey-6"),
Expand Down
12 changes: 11 additions & 1 deletion pkg/consensus/validator/heavy_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"errors"
"fmt"

"github.com/yago-123/chainnet/pkg/script"

"github.com/yago-123/chainnet/pkg/script/interpreter"
"github.com/yago-123/chainnet/pkg/storage"

Expand Down Expand Up @@ -147,7 +149,15 @@ func (hv *HValidator) validateOwnershipAndBalanceOfInputs(tx *kernel.Transaction
for _, vin := range tx.Vin {
// fetch the unspent outputs for the input's public key
// todo(): would make sense to add a check via UTXO set?
utxos, _ := hv.explorer.FindUnspentOutputs(vin.PubKey)

address := script.ExtractAddressFromScriptSig(vin.ScriptSig)
// todo(): this check if GARBAGE, add some sort of error handing for ExtractAddressFromScriptSig
if address != "" {
// todo(): revisit this, do we really need to return an error?
return fmt.Errorf("unable to extract address from script signature")
}

utxos, _ := hv.explorer.FindUnspentOutputs(address)
for _, utxo := range utxos {
// if there is match, check that the signature is valid
if utxo.EqualInput(vin) {
Expand Down
26 changes: 14 additions & 12 deletions pkg/consensus/validator/heavy_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package validator //nolint:testpackage // don't create separate package for test
import (
"testing"

util_script "github.com/yago-123/chainnet/pkg/util/script"

"github.com/yago-123/chainnet/config"

expl "github.com/yago-123/chainnet/pkg/chain/explorer"
Expand Down Expand Up @@ -32,7 +34,7 @@ func TestHValidator_validateNumberOfCoinbaseTxs(t *testing.T) {
blockWithoutCoinbase := &kernel.Block{
Transactions: []*kernel.Transaction{
kernel.NewTransaction(
[]kernel.TxInput{kernel.NewInput([]byte("txid"), 0, "scriptSig", "pubKey")},
[]kernel.TxInput{kernel.NewInput([]byte("txid"), 0, util_script.EncodeScriptSig([][]byte{[]byte("scriptSig"), []byte("pubKey")}))},
[]kernel.TxOutput{kernel.NewOutput(1, script.P2PK, "scriptPubKey")},
),
},
Expand Down Expand Up @@ -61,17 +63,17 @@ func TestHValidator_validateNumberOfCoinbaseTxs(t *testing.T) {
func TestHValidator_validateNoDoubleSpendingInsideBlock(t *testing.T) {
blockWithDoubleSpending := &kernel.Block{
Transactions: []*kernel.Transaction{
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid"), 0, "scriptSig", "pubKey")}},
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid"), 1, "scriptSig", "pubKey")}},
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid"), 0, "scriptSig", "pubKey")}},
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid"), 0, util_script.EncodeScriptSig([][]byte{[]byte("signature"), []byte("pubKey")}))}},
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid"), 1, util_script.EncodeScriptSig([][]byte{[]byte("signature"), []byte("pubKey")}))}},
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid"), 0, util_script.EncodeScriptSig([][]byte{[]byte("signature"), []byte("pubKey")}))}},
},
}

blockWithoutDoubleSpending := &kernel.Block{
Transactions: []*kernel.Transaction{
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid"), 0, "scriptSig", "pubKey")}},
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid"), 1, "scriptSig", "pubKey")}},
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid2"), 0, "scriptSig", "pubKey")}},
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid"), 0, util_script.EncodeScriptSig([][]byte{[]byte("signature"), []byte("pubKey")}))}},
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid"), 1, util_script.EncodeScriptSig([][]byte{[]byte("signature"), []byte("pubKey")}))}},
{Vin: []kernel.TxInput{kernel.NewInput([]byte("txid2"), 0, util_script.EncodeScriptSig([][]byte{[]byte("signature"), []byte("pubKey")}))}},
},
}

Expand Down Expand Up @@ -168,23 +170,23 @@ func TestHValidator_validateBlockHeight(t *testing.T) {
func TestHValidator_validateMerkleTree(t *testing.T) {
txs := []*kernel.Transaction{
kernel.NewTransaction(
[]kernel.TxInput{kernel.NewInput([]byte("txid"), 0, "scriptSig", "pubKey")},
[]kernel.TxInput{kernel.NewInput([]byte("txid"), 0, util_script.EncodeScriptSig([][]byte{[]byte("scriptSig"), []byte("pubKey")}))},
[]kernel.TxOutput{kernel.NewOutput(1, script.P2PK, "scriptPubKey")},
),
kernel.NewTransaction(
[]kernel.TxInput{kernel.NewInput([]byte("txid2"), 1, "scriptSig2", "pubKey2")},
[]kernel.TxInput{kernel.NewInput([]byte("txid2"), 1, util_script.EncodeScriptSig([][]byte{[]byte("scriptSig2"), []byte("pubKey2")}))},
[]kernel.TxOutput{
kernel.NewOutput(2, script.P2PK, "scriptPubKey2"),
kernel.NewOutput(2, script.P2PK, "scriptPubKey3"),
},
),
kernel.NewTransaction(
[]kernel.TxInput{
kernel.NewInput([]byte("txid3"), 2, "scriptSig3", "pubKey3"),
kernel.NewInput([]byte("txid4"), 3, "scriptSig4", "pubKey4"),
kernel.NewInput([]byte("txid3"), 2, util_script.EncodeScriptSig([][]byte{[]byte("scriptSig3"), []byte("pubKey3")})),
kernel.NewInput([]byte("txid3"), 3, util_script.EncodeScriptSig([][]byte{[]byte("scriptSig4"), []byte("pubKey4")})),
},
[]kernel.TxOutput{
kernel.NewOutput(3, script.P2PK, "scriptPubKey3"),
kernel.NewOutput(2, script.P2PK, "scriptPubKey3"),
},
),
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/consensus/validator/light_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestLValidator_ValidateHeader(_ *testing.T) {
func TestLValidator_validateTxID(t *testing.T) {
hasher := &hash.FakeHashing{}
tx := kernel.NewTransaction(
[]kernel.TxInput{kernel.NewInput([]byte("tx-id-1"), 1, "scriptsig", "pubkey")},
[]kernel.TxInput{kernel.NewInput([]byte("tx-id-1"), 1, "scriptsig pubkey")},
[]kernel.TxOutput{kernel.NewOutput(1, script.P2PK, "pubkey2")},
)

Expand Down
22 changes: 11 additions & 11 deletions pkg/encoding/gob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ var testBlock = &kernel.Block{ //nolint:gochecknoglobals // data that is used ac
{
ID: []byte("tx1"),
Vin: []kernel.TxInput{
{Txid: []byte("tx0"), Vout: 0, ScriptSig: "script1", PubKey: "pubkey1"},
{Txid: []byte("tx0"), Vout: 1, ScriptSig: "script2", PubKey: "pubkey2"},
{Txid: []byte("tx0"), Vout: 0, ScriptSig: "script1"},
{Txid: []byte("tx0"), Vout: 1, ScriptSig: "script2"},
},
Vout: []kernel.TxOutput{
{Amount: 50, ScriptPubKey: "scriptpubkey1", PubKey: "pubkey1"},
{Amount: 30, ScriptPubKey: "scriptpubkey2", PubKey: "pubkey2"},
{Amount: 50, ScriptPubKey: "scriptpubkey1"},
{Amount: 30, ScriptPubKey: "scriptpubkey2"},
},
},
{
ID: []byte("tx2"),
Vin: []kernel.TxInput{
{Txid: []byte("tx1"), Vout: 0, ScriptSig: "script3", PubKey: "pubkey3"},
{Txid: []byte("tx1"), Vout: 0, ScriptSig: "script3"},
},
Vout: []kernel.TxOutput{
{Amount: 20, ScriptPubKey: "scriptpubkey3", PubKey: "pubkey3"},
{Amount: 10, ScriptPubKey: "scriptpubkey4", PubKey: "pubkey4"},
{Amount: 20, ScriptPubKey: "scriptpubkey3"},
{Amount: 10, ScriptPubKey: "scriptpubkey4"},
},
},
},
Expand All @@ -51,12 +51,12 @@ var testBlock = &kernel.Block{ //nolint:gochecknoglobals // data that is used ac
var testTransaction = kernel.Transaction{ //nolint:gochecknoglobals // data that is used across all test funcs
ID: []byte("tx1"),
Vin: []kernel.TxInput{
{Txid: []byte("tx0"), Vout: 0, ScriptSig: "script1", PubKey: "pubkey1"},
{Txid: []byte("tx0"), Vout: 1, ScriptSig: "script2", PubKey: "pubkey2"},
{Txid: []byte("tx0"), Vout: 0, ScriptSig: "script1"},
{Txid: []byte("tx0"), Vout: 1, ScriptSig: "script2"},
},
Vout: []kernel.TxOutput{
{Amount: 50, ScriptPubKey: "scriptpubkey1", PubKey: "pubkey1"},
{Amount: 30, ScriptPubKey: "scriptpubkey2", PubKey: "pubkey2"},
{Amount: 50, ScriptPubKey: "scriptpubkey1"},
{Amount: 30, ScriptPubKey: "scriptpubkey2"},
},
}

Expand Down
Loading
Loading