From 521b10aa268b91ee48614863e0e9195517ad4be9 Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Thu, 19 Sep 2024 07:34:40 -0700 Subject: [PATCH 1/3] chain: expose From and To for host announcements --- chain/hostannouncement.go | 34 ++++++++++++++++++++++------------ chain/hostannouncement_test.go | 5 +++-- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/chain/hostannouncement.go b/chain/hostannouncement.go index dea02b6..229d312 100644 --- a/chain/hostannouncement.go +++ b/chain/hostannouncement.go @@ -15,13 +15,17 @@ var specifierHostAnnouncement = types.NewSpecifier("HostAnnouncement") // address. Announcements may be made via arbitrary data (in a v1 transaction) // or via attestation (in a v2 transaction). type HostAnnouncement struct { - NetAddress string + PublicKey types.PublicKey `json:"publicKey"` + NetAddress string `json:"netAddress"` } // ToAttestation encodes a host announcement as an attestation. func (ha HostAnnouncement) ToAttestation(cs consensus.State, sk types.PrivateKey) types.Attestation { + if ha.PublicKey != sk.PublicKey() { + panic("key mismatch") // developer error + } a := types.Attestation{ - PublicKey: sk.PublicKey(), + PublicKey: ha.PublicKey, Key: attestationHostAnnouncement, Value: []byte(ha.NetAddress), } @@ -29,28 +33,33 @@ func (ha HostAnnouncement) ToAttestation(cs consensus.State, sk types.PrivateKey return a } -func (ha *HostAnnouncement) fromAttestation(a types.Attestation) bool { +func (ha *HostAnnouncement) FromAttestation(a types.Attestation) bool { if a.Key != attestationHostAnnouncement { return false } + ha.PublicKey = a.PublicKey ha.NetAddress = string(a.Value) return true } // ToArbitraryData encodes a host announcement as arbitrary data. func (ha HostAnnouncement) ToArbitraryData(sk types.PrivateKey) []byte { + if ha.PublicKey != sk.PublicKey() { + panic("key mismatch") // developer error + } + buf := new(bytes.Buffer) e := types.NewEncoder(buf) specifierHostAnnouncement.EncodeTo(e) e.WriteString(ha.NetAddress) - sk.PublicKey().UnlockKey().EncodeTo(e) + ha.PublicKey.UnlockKey().EncodeTo(e) e.Flush() sk.SignHash(types.HashBytes(buf.Bytes())).EncodeTo(e) e.Flush() return buf.Bytes() } -func (ha *HostAnnouncement) fromArbitraryData(arb []byte) (types.PublicKey, bool) { +func (ha *HostAnnouncement) FromArbitraryData(arb []byte) bool { var s types.Specifier var uk types.UnlockKey var sig types.Signature @@ -65,27 +74,28 @@ func (ha *HostAnnouncement) fromArbitraryData(arb []byte) (types.PublicKey, bool len(uk.Key) < 32 || len(arb) < len(sig) || !types.PublicKey(uk.Key).VerifyHash(types.HashBytes(arb[:len(arb)-len(sig)]), sig) { - return types.PublicKey{}, false + return false } ha.NetAddress = addr - return types.PublicKey(uk.Key), true + ha.PublicKey = types.PublicKey(uk.Key) + return true } // ForEachHostAnnouncement calls fn on each host announcement in a block. -func ForEachHostAnnouncement(b types.Block, fn func(types.PublicKey, HostAnnouncement)) { +func ForEachHostAnnouncement(b types.Block, fn func(HostAnnouncement)) { for _, txn := range b.Transactions { for _, arb := range txn.ArbitraryData { var ha HostAnnouncement - if pk, ok := ha.fromArbitraryData(arb); ok { - fn(pk, ha) + if ha.FromArbitraryData(arb) { + fn(ha) } } } for _, txn := range b.V2Transactions() { for _, a := range txn.Attestations { var ha HostAnnouncement - if ha.fromAttestation(a) { - fn(a.PublicKey, ha) + if ha.FromAttestation(a) { + fn(ha) } } } diff --git a/chain/hostannouncement_test.go b/chain/hostannouncement_test.go index a049992..165502c 100644 --- a/chain/hostannouncement_test.go +++ b/chain/hostannouncement_test.go @@ -11,6 +11,7 @@ func TestForEachHostAnnouncement(t *testing.T) { sk := types.GeneratePrivateKey() ha := HostAnnouncement{ NetAddress: "foo.bar:1234", + PublicKey: sk.PublicKey(), } b := types.Block{ Transactions: []types.Transaction{ @@ -22,8 +23,8 @@ func TestForEachHostAnnouncement(t *testing.T) { }, }, } - ForEachHostAnnouncement(b, func(pk types.PublicKey, a HostAnnouncement) { - if pk != sk.PublicKey() { + ForEachHostAnnouncement(b, func(a HostAnnouncement) { + if a.PublicKey != sk.PublicKey() { t.Error("pubkey mismatch") } else if a.NetAddress != ha.NetAddress { t.Error("address mismatch:", a, ha) From fea16ddafab6b1be1ec3d0b461963cd4aff4af36 Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Thu, 19 Sep 2024 07:36:39 -0700 Subject: [PATCH 2/3] chain: fix lint --- chain/hostannouncement.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/chain/hostannouncement.go b/chain/hostannouncement.go index 229d312..9acf99d 100644 --- a/chain/hostannouncement.go +++ b/chain/hostannouncement.go @@ -33,6 +33,7 @@ func (ha HostAnnouncement) ToAttestation(cs consensus.State, sk types.PrivateKey return a } +// FromAttestation decodes a host announcement from an attestation. func (ha *HostAnnouncement) FromAttestation(a types.Attestation) bool { if a.Key != attestationHostAnnouncement { return false @@ -59,6 +60,7 @@ func (ha HostAnnouncement) ToArbitraryData(sk types.PrivateKey) []byte { return buf.Bytes() } +// FromArbitraryData decodes a host announcement from arbitrary data. func (ha *HostAnnouncement) FromArbitraryData(arb []byte) bool { var s types.Specifier var uk types.UnlockKey From be22ee77a738325742abf991ab34c7fb2c77792d Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Thu, 19 Sep 2024 09:01:16 -0700 Subject: [PATCH 3/3] chain: fix test --- chain/chain_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/chain/chain_test.go b/chain/chain_test.go index 03df5ba..b3e5dd9 100644 --- a/chain/chain_test.go +++ b/chain/chain_test.go @@ -185,6 +185,7 @@ func TestV2Attestations(t *testing.T) { sk := types.GeneratePrivateKey() ann := chain.HostAnnouncement{ NetAddress: "foo.bar:1234", + PublicKey: sk.PublicKey(), } se := ms.SpendableElement(t) txn := types.V2Transaction{ @@ -234,6 +235,7 @@ func TestV2Attestations(t *testing.T) { sk := types.GeneratePrivateKey() ann := chain.HostAnnouncement{ NetAddress: "foo.bar:1234", + PublicKey: sk.PublicKey(), } txn := types.V2Transaction{ ArbitraryData: frand.Bytes(16), @@ -278,6 +280,7 @@ func TestV2Attestations(t *testing.T) { sk := types.GeneratePrivateKey() ann := chain.HostAnnouncement{ NetAddress: "foo.bar:1234", + PublicKey: sk.PublicKey(), } se := ms.SpendableElement(t) minerFee := types.Siacoins(1)