Skip to content

Commit

Permalink
Merge pull request #98 from SiaFoundation/nate/public-announcements
Browse files Browse the repository at this point in the history
Expose From and To for host announcements
  • Loading branch information
n8maninger authored Sep 19, 2024
2 parents 9cc63ee + be22ee7 commit 7fd91e1
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 14 deletions.
3 changes: 3 additions & 0 deletions chain/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)
Expand Down
36 changes: 24 additions & 12 deletions chain/hostannouncement.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,42 +15,53 @@ 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),
}
a.Signature = sk.SignHash(cs.AttestationSigHash(a))
return a
}

func (ha *HostAnnouncement) fromAttestation(a types.Attestation) bool {
// FromAttestation decodes a host announcement from an attestation.
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) {
// FromArbitraryData decodes a host announcement from arbitrary data.
func (ha *HostAnnouncement) FromArbitraryData(arb []byte) bool {
var s types.Specifier
var uk types.UnlockKey
var sig types.Signature
Expand All @@ -65,27 +76,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)
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions chain/hostannouncement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand All @@ -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)
Expand Down

0 comments on commit 7fd91e1

Please sign in to comment.