Store input sig and key in different fields; rename TXInput.ScriptPubKey to PubKeyHash

This commit is contained in:
Ivan Kuznetsov 2017-09-10 14:05:23 +07:00
parent a436da6c19
commit bf8c5d22e1
3 changed files with 26 additions and 28 deletions

View File

@ -70,9 +70,10 @@ func (tx *Transaction) Sign(privKey ecdsa.PrivateKey, prevTXs map[string]Transac
for inID, vin := range txCopy.Vin { for inID, vin := range txCopy.Vin {
prevTx := prevTXs[hex.EncodeToString(vin.Txid)] prevTx := prevTXs[hex.EncodeToString(vin.Txid)]
txCopy.Vin[inID].ScriptSig = prevTx.Vout[vin.Vout].ScriptPubKey txCopy.Vin[inID].Signature = []byte{}
txCopy.Vin[inID].PubKey = prevTx.Vout[vin.Vout].PubKeyHash
txCopy.ID = txCopy.Hash() txCopy.ID = txCopy.Hash()
txCopy.Vin[inID].ScriptSig = []byte{} txCopy.Vin[inID].PubKey = []byte{}
r, s, err := ecdsa.Sign(rand.Reader, &privKey, txCopy.ID) r, s, err := ecdsa.Sign(rand.Reader, &privKey, txCopy.ID)
if err != nil { if err != nil {
@ -80,7 +81,7 @@ func (tx *Transaction) Sign(privKey ecdsa.PrivateKey, prevTXs map[string]Transac
} }
signature := append(r.Bytes(), s.Bytes()...) signature := append(r.Bytes(), s.Bytes()...)
tx.Vin[inID].ScriptSig = append(signature, tx.Vin[inID].ScriptSig...) tx.Vin[inID].Signature = signature
} }
} }
@ -93,15 +94,16 @@ func (tx Transaction) String() string {
for i, input := range tx.Vin { for i, input := range tx.Vin {
lines = append(lines, fmt.Sprintf(" Input %d:", i)) lines = append(lines, fmt.Sprintf(" Input %d:", i))
lines = append(lines, fmt.Sprintf(" TXID: %x", input.Txid)) lines = append(lines, fmt.Sprintf(" TXID: %x", input.Txid))
lines = append(lines, fmt.Sprintf(" Out: %d", input.Vout)) lines = append(lines, fmt.Sprintf(" Out: %d", input.Vout))
lines = append(lines, fmt.Sprintf(" Script: %x", input.ScriptSig)) lines = append(lines, fmt.Sprintf(" Signature: %x", input.Signature))
lines = append(lines, fmt.Sprintf(" PubKey: %x", input.PubKey))
} }
for i, output := range tx.Vout { for i, output := range tx.Vout {
lines = append(lines, fmt.Sprintf(" Output %d:", i)) lines = append(lines, fmt.Sprintf(" Output %d:", i))
lines = append(lines, fmt.Sprintf(" Value: %d", output.Value)) lines = append(lines, fmt.Sprintf(" Value: %d", output.Value))
lines = append(lines, fmt.Sprintf(" Script: %x", output.ScriptPubKey)) lines = append(lines, fmt.Sprintf(" Script: %x", output.PubKeyHash))
} }
return strings.Join(lines, "\n") return strings.Join(lines, "\n")
@ -117,7 +119,7 @@ func (tx *Transaction) TrimmedCopy() Transaction {
} }
for _, vout := range tx.Vout { for _, vout := range tx.Vout {
outputs = append(outputs, TXOutput{vout.Value, vout.ScriptPubKey}) outputs = append(outputs, TXOutput{vout.Value, vout.PubKeyHash})
} }
txCopy := Transaction{tx.ID, inputs, outputs} txCopy := Transaction{tx.ID, inputs, outputs}
@ -127,8 +129,6 @@ func (tx *Transaction) TrimmedCopy() Transaction {
// Verify verifies signatures of Transaction inputs // Verify verifies signatures of Transaction inputs
func (tx *Transaction) Verify(prevTXs map[string]Transaction) bool { func (tx *Transaction) Verify(prevTXs map[string]Transaction) bool {
sigLen := 64
if tx.IsCoinbase() { if tx.IsCoinbase() {
return true return true
} }
@ -144,23 +144,22 @@ func (tx *Transaction) Verify(prevTXs map[string]Transaction) bool {
for inID, vin := range tx.Vin { for inID, vin := range tx.Vin {
prevTx := prevTXs[hex.EncodeToString(vin.Txid)] prevTx := prevTXs[hex.EncodeToString(vin.Txid)]
txCopy.Vin[inID].ScriptSig = prevTx.Vout[vin.Vout].ScriptPubKey txCopy.Vin[inID].Signature = []byte{}
txCopy.Vin[inID].PubKey = prevTx.Vout[vin.Vout].PubKeyHash
txCopy.ID = txCopy.Hash() txCopy.ID = txCopy.Hash()
txCopy.Vin[inID].ScriptSig = []byte{} txCopy.Vin[inID].PubKey = []byte{}
signature := vin.ScriptSig[:sigLen]
pubKey := vin.ScriptSig[sigLen:]
r := big.Int{} r := big.Int{}
s := big.Int{} s := big.Int{}
r.SetBytes(signature[:(sigLen / 2)]) sigLen := len(vin.Signature)
s.SetBytes(signature[(sigLen / 2):]) r.SetBytes(vin.Signature[:(sigLen / 2)])
s.SetBytes(vin.Signature[(sigLen / 2):])
x := big.Int{} x := big.Int{}
y := big.Int{} y := big.Int{}
keyLen := len(pubKey) keyLen := len(vin.PubKey)
x.SetBytes(pubKey[:(keyLen / 2)]) x.SetBytes(vin.PubKey[:(keyLen / 2)])
y.SetBytes(pubKey[(keyLen / 2):]) y.SetBytes(vin.PubKey[(keyLen / 2):])
rawPubKey := ecdsa.PublicKey{curve, &x, &y} rawPubKey := ecdsa.PublicKey{curve, &x, &y}
if ecdsa.Verify(&rawPubKey, txCopy.ID, &r, &s) == false { if ecdsa.Verify(&rawPubKey, txCopy.ID, &r, &s) == false {

View File

@ -6,14 +6,13 @@ import "bytes"
type TXInput struct { type TXInput struct {
Txid []byte Txid []byte
Vout int Vout int
ScriptSig []byte Signature []byte
PubKey []byte
} }
// UsesKey checks whether the address initiated the transaction // UsesKey checks whether the address initiated the transaction
func (in *TXInput) UsesKey(pubKeyHash []byte) bool { func (in *TXInput) UsesKey(pubKeyHash []byte) bool {
sigLen := 64 lockingHash := HashPubKey(in.PubKey)
pubKey := in.ScriptSig[sigLen:]
lockingHash := HashPubKey(pubKey)
return bytes.Compare(lockingHash, pubKeyHash) == 0 return bytes.Compare(lockingHash, pubKeyHash) == 0
} }

View File

@ -4,20 +4,20 @@ import "bytes"
// TXOutput represents a transaction output // TXOutput represents a transaction output
type TXOutput struct { type TXOutput struct {
Value int Value int
ScriptPubKey []byte PubKeyHash []byte
} }
// Lock signs the output // Lock signs the output
func (out *TXOutput) Lock(address []byte) { func (out *TXOutput) Lock(address []byte) {
pubKeyHash := Base58Decode(address) pubKeyHash := Base58Decode(address)
pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-4] pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-4]
out.ScriptPubKey = pubKeyHash out.PubKeyHash = pubKeyHash
} }
// IsLockedWithKey checks if the output can be used by the owner of the pubkey // IsLockedWithKey checks if the output can be used by the owner of the pubkey
func (out *TXOutput) IsLockedWithKey(pubKeyHash []byte) bool { func (out *TXOutput) IsLockedWithKey(pubKeyHash []byte) bool {
return bytes.Compare(out.ScriptPubKey, pubKeyHash) == 0 return bytes.Compare(out.PubKeyHash, pubKeyHash) == 0
} }
// NewTXOutput create a new TXOutput // NewTXOutput create a new TXOutput