Skip to content

Commit 199fc0e

Browse files
authored
Merge pull request #368 from blinklabs-io/feat/ledger-address-from-parts
feat: build Address from parts
2 parents feea96c + 8793624 commit 199fc0e

File tree

2 files changed

+80
-25
lines changed

2 files changed

+80
-25
lines changed

ledger/common.go

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -180,21 +180,21 @@ func (a AssetFingerprint) String() string {
180180
}
181181

182182
const (
183-
addressHeaderTypeMask = 0xF0
184-
addressHeaderNetworkMask = 0x0F
185-
addressHashSize = 28
186-
187-
addressTypeKeyKey = 0b0000
188-
addressTypeScriptKey = 0b0001
189-
addressTypeKeyScript = 0b0010
190-
addressTypeScriptScript = 0b0011
191-
addressTypeKeyPointer = 0b0100
192-
addressTypeScriptPointer = 0b0101
193-
addressTypeKeyNone = 0b0110
194-
addressTypeScriptNone = 0b0111
195-
addressTypeByron = 0b1000
196-
addressTypeNoneKey = 0b1110
197-
addressTypeNoneScript = 0b1111
183+
AddressHeaderTypeMask = 0xF0
184+
AddressHeaderNetworkMask = 0x0F
185+
AddressHashSize = 28
186+
187+
AddressTypeKeyKey = 0b0000
188+
AddressTypeScriptKey = 0b0001
189+
AddressTypeKeyScript = 0b0010
190+
AddressTypeScriptScript = 0b0011
191+
AddressTypeKeyPointer = 0b0100
192+
AddressTypeScriptPointer = 0b0101
193+
AddressTypeKeyNone = 0b0110
194+
AddressTypeScriptNone = 0b0111
195+
AddressTypeByron = 0b1000
196+
AddressTypeNoneKey = 0b1110
197+
AddressTypeNoneScript = 0b1111
198198
)
199199

200200
type Address struct {
@@ -219,18 +219,28 @@ func NewAddress(addr string) (Address, error) {
219219
return a, nil
220220
}
221221

222+
// NewAddressFromParts returns an Address based on the individual parts of the address that are provided
223+
func NewAddressFromParts(addrType uint8, networkId uint8, paymentAddr []byte, stakingAddr []byte) Address {
224+
return Address{
225+
addressType: addrType,
226+
networkId: networkId,
227+
paymentAddress: paymentAddr,
228+
stakingAddress: stakingAddr,
229+
}
230+
}
231+
222232
func (a *Address) populateFromBytes(data []byte) {
223233
// Extract header info
224234
header := data[0]
225-
a.addressType = (header & addressHeaderTypeMask) >> 4
226-
a.networkId = header & addressHeaderNetworkMask
235+
a.addressType = (header & AddressHeaderTypeMask) >> 4
236+
a.networkId = header & AddressHeaderNetworkMask
227237
// Extract payload
228238
// NOTE: this is probably incorrect for Byron
229239
payload := data[1:]
230-
a.paymentAddress = payload[:addressHashSize]
231-
a.stakingAddress = payload[addressHashSize:]
240+
a.paymentAddress = payload[:AddressHashSize]
241+
a.stakingAddress = payload[AddressHashSize:]
232242
// Adjust stake addresses
233-
if a.addressType == addressTypeNoneKey || a.addressType == addressTypeNoneScript {
243+
if a.addressType == AddressTypeNoneKey || a.addressType == AddressTypeNoneScript {
234244
a.stakingAddress = a.paymentAddress[:]
235245
a.paymentAddress = make([]byte, 0)
236246
}
@@ -252,11 +262,11 @@ func (a *Address) MarshalCBOR() ([]byte, error) {
252262

253263
// StakeAddress returns a new Address with only the stake key portion. This will return nil if the address is not a payment/staking key pair
254264
func (a Address) StakeAddress() *Address {
255-
if a.addressType != addressTypeKeyKey && a.addressType != addressTypeScriptKey {
265+
if a.addressType != AddressTypeKeyKey && a.addressType != AddressTypeScriptKey {
256266
return nil
257267
}
258268
newAddr := &Address{
259-
addressType: addressTypeNoneKey,
269+
addressType: AddressTypeNoneKey,
260270
networkId: a.networkId,
261271
stakingAddress: a.stakingAddress[:],
262272
}
@@ -265,7 +275,7 @@ func (a Address) StakeAddress() *Address {
265275

266276
func (a Address) generateHRP() string {
267277
var ret string
268-
if a.addressType == addressTypeNoneKey || a.addressType == addressTypeNoneScript {
278+
if a.addressType == AddressTypeNoneKey || a.addressType == AddressTypeNoneScript {
269279
ret = "stake"
270280
} else {
271281
ret = "addr"
@@ -280,7 +290,7 @@ func (a Address) generateHRP() string {
280290
// Bytes returns the underlying bytes for the address
281291
func (a Address) Bytes() []byte {
282292
ret := []byte{}
283-
ret = append(ret, (byte(a.addressType)<<4)|(byte(a.networkId)&addressHeaderNetworkMask))
293+
ret = append(ret, (byte(a.addressType)<<4)|(byte(a.networkId)&AddressHeaderNetworkMask))
284294
ret = append(ret, a.paymentAddress...)
285295
ret = append(ret, a.stakingAddress...)
286296
return ret
@@ -289,7 +299,7 @@ func (a Address) Bytes() []byte {
289299
// String returns the bech32-encoded version of the address
290300
func (a Address) String() string {
291301
data := a.Bytes()
292-
if a.addressType == addressTypeByron {
302+
if a.addressType == AddressTypeByron {
293303
// Encode data to base58
294304
encoded := base58.Encode(data)
295305
return encoded

ledger/common_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,51 @@ func TestAddressFromBytes(t *testing.T) {
135135
}
136136
}
137137

138+
func TestAddressFromParts(t *testing.T) {
139+
// We can't use our network helpers due to an import cycle
140+
var networkMainnetId uint8 = 1
141+
testDefs := []struct {
142+
addressType uint8
143+
networkId uint8
144+
paymentAddr []byte
145+
stakingAddr []byte
146+
expectedAddress string
147+
}{
148+
{
149+
addressType: AddressTypeScriptKey,
150+
networkId: networkMainnetId,
151+
paymentAddr: test.DecodeHexString("e1317b152faac13426e6a83e06ff88a4d62cce3c1634ab0a5ec13309"),
152+
stakingAddr: test.DecodeHexString("52563c5410bff6a0d43ccebb7c37e1f69f5eb260552521adff33b9c2"),
153+
expectedAddress: "addr1z8snz7c4974vzdpxu65ruphl3zjdvtxw8strf2c2tmqnxz2j2c79gy9l76sdg0xwhd7r0c0kna0tycz4y5s6mlenh8pq0xmsha",
154+
},
155+
{
156+
addressType: AddressTypeKeyKey,
157+
networkId: networkMainnetId,
158+
paymentAddr: test.DecodeHexString("3f35615835258addded1c2e169f3a2ab4ae94d606bde030e7947f518"),
159+
stakingAddr: test.DecodeHexString("4ff5f8e3d43ce6b19ec4197e331e86d0f5e58b02d7a75b5e74cff95d"),
160+
expectedAddress: "addr1qyln2c2cx5jc4hw768pwz60n5245462dvp4auqcw09rl2xz07huw84puu6cea3qe0ce3apks7hjckqkh5ad4uax0l9ws0q9xty",
161+
},
162+
{
163+
addressType: AddressTypeScriptNone,
164+
networkId: networkMainnetId,
165+
paymentAddr: test.DecodeHexString("21bd8c2e0df2fbe92137f78dbaba48f62308e52303049f0d628b6c4c"),
166+
expectedAddress: "addr1wysmmrpwphe0h6fpxlmcmw46frmzxz89yvpsf8cdv29kcnqsw3vw6",
167+
},
168+
{
169+
addressType: AddressTypeKeyNone,
170+
networkId: networkMainnetId,
171+
paymentAddr: test.DecodeHexString("cfe224295a282d69edda5fa8de4f131e2b9cd21a6c9235597fa4ff6b"),
172+
expectedAddress: "addr1v887yfpftg5z660dmf063hj0zv0zh8xjrfkfyd2e07j076cecha5k",
173+
},
174+
}
175+
for _, testDef := range testDefs {
176+
addr := NewAddressFromParts(testDef.addressType, testDef.networkId, testDef.paymentAddr, testDef.stakingAddr)
177+
if addr.String() != testDef.expectedAddress {
178+
t.Fatalf("address did not match expected value, got: %s, wanted: %s", addr.String(), testDef.expectedAddress)
179+
}
180+
}
181+
}
182+
138183
func TestAddressStakeAddress(t *testing.T) {
139184
testDefs := []struct {
140185
address string

0 commit comments

Comments
 (0)