• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tari-project / tari / 14642108223

24 Apr 2025 12:52PM UTC coverage: 73.398% (+1.1%) from 72.346%
14642108223

push

github

web-flow
feat(grpc): return best block height from synced node (#6984)

Description
---
Adds `tip_height` and `local_height` to `get_sync_status`

Motivation and Context
---
TU checks flag `initial_sync_achieved` from `get_tip_info` and also
calls `get_sync_progress` to get `tip_height` but if
`initial_sync_achieved` is true then these 2 fields are 0 and we can't
check tip after syncing.

How Has This Been Tested?
---

What process can a PR reviewer use to test or verify this change?
---



Breaking Changes
---

- [x] None
- [ ] Requires data directory on base node to be deleted
- [ ] Requires hard fork
- [ ] Other - Please specify


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Bug Fixes**
- Improved accuracy of sync progress reporting by displaying the actual
best block height when the node is synced, instead of showing zero
values.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

81382 of 110877 relevant lines covered (73.4%)

279101.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.0
/infrastructure/max_size/src/string.rs
1
//  Copyright 2022. The Tari Project
2
//
3
//  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
4
//  following conditions are met:
5
//
6
//  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
7
//  disclaimer.
8
//
9
//  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
10
//  following disclaimer in the documentation and/or other materials provided with the distribution.
11
//
12
//  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
13
//  products derived from this software without specific prior written permission.
14
//
15
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
16
//  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18
//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
//  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20
//  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
21
//  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22

23
use std::{convert::TryFrom, fmt::Display};
24

25
use borsh::{BorshDeserialize, BorshSerialize};
26
use serde::{Deserialize, Serialize};
27

28
/// A string that can only be a up to MAX length long
29
#[derive(
30
    Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize,
×
31
)]
32
pub struct MaxSizeString<const MAX: usize> {
33
    string: String,
34
}
35

36
impl<const MAX: usize> MaxSizeString<MAX> {
37
    pub fn from_str_checked(s: &str) -> Option<Self> {
5✔
38
        if s.len() > MAX {
5✔
39
            return None;
1✔
40
        }
4✔
41
        Some(Self { string: s.to_string() })
4✔
42
    }
5✔
43

44
    pub fn from_utf8_bytes_checked<T: AsRef<[u8]>>(bytes: T) -> Option<Self> {
3✔
45
        let b = bytes.as_ref();
3✔
46
        if b.len() > MAX {
3✔
47
            return None;
1✔
48
        }
2✔
49

50
        let s = String::from_utf8(b.to_vec()).ok()?;
2✔
51
        Some(Self { string: s })
1✔
52
    }
3✔
53

54
    pub fn len(&self) -> usize {
5✔
55
        self.string.len()
5✔
56
    }
5✔
57

58
    pub fn is_empty(&self) -> bool {
×
59
        self.string.is_empty()
×
60
    }
×
61

62
    pub fn as_str(&self) -> &str {
5✔
63
        &self.string
5✔
64
    }
5✔
65

66
    pub fn into_string(self) -> String {
×
67
        self.string
×
68
    }
×
69
}
70

71
impl<const MAX: usize> TryFrom<String> for MaxSizeString<MAX> {
72
    type Error = MaxSizeStringLengthError;
73

74
    fn try_from(value: String) -> Result<Self, Self::Error> {
4✔
75
        if value.len() > MAX {
4✔
76
            return Err(MaxSizeStringLengthError {
×
77
                actual: value.len(),
×
78
                expected: MAX,
×
79
            });
×
80
        }
4✔
81
        Ok(Self { string: value })
4✔
82
    }
4✔
83
}
84

85
impl<const MAX: usize> TryFrom<&str> for MaxSizeString<MAX> {
86
    type Error = MaxSizeStringLengthError;
87

88
    fn try_from(value: &str) -> Result<Self, Self::Error> {
8✔
89
        if value.len() > MAX {
8✔
90
            return Err(MaxSizeStringLengthError {
×
91
                actual: value.len(),
×
92
                expected: MAX,
×
93
            });
×
94
        }
8✔
95
        Ok(Self {
8✔
96
            string: value.to_string(),
8✔
97
        })
8✔
98
    }
8✔
99
}
100

101
impl<const MAX: usize> AsRef<[u8]> for MaxSizeString<MAX> {
102
    fn as_ref(&self) -> &[u8] {
×
103
        self.string.as_ref()
×
104
    }
×
105
}
106

107
impl<const MAX: usize> Display for MaxSizeString<MAX> {
108
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
109
        write!(f, "{}", self.string)
×
110
    }
×
111
}
112

113
#[derive(Debug, thiserror::Error)]
114
#[error("Invalid String length: expected {expected}, got {actual}")]
115
pub struct MaxSizeStringLengthError {
116
    expected: usize,
117
    actual: usize,
118
}
119

120
#[cfg(test)]
121
mod tests {
122
    mod from_str_checked {
123
        use crate::MaxSizeString;
124
        #[test]
125
        fn it_returns_none_if_size_exceeded() {
1✔
126
            let s = MaxSizeString::<10>::from_str_checked("12345678901234567890");
1✔
127
            assert_eq!(s, None);
1✔
128
        }
1✔
129

130
        #[test]
131
        fn it_returns_some_if_size_in_bounds() {
1✔
132
            let s = MaxSizeString::<0>::from_str_checked("").unwrap();
1✔
133
            assert_eq!(s.as_str(), "");
1✔
134
            assert_eq!(s.len(), 0);
1✔
135

136
            let s = MaxSizeString::<10>::from_str_checked("1234567890").unwrap();
1✔
137
            assert_eq!(s.as_str(), "1234567890");
1✔
138
            assert_eq!(s.len(), 10);
1✔
139

140
            let s = MaxSizeString::<10>::from_str_checked("1234").unwrap();
1✔
141
            assert_eq!(s.as_str(), "1234");
1✔
142
            assert_eq!(s.len(), 4);
1✔
143

144
            let s = MaxSizeString::<8>::from_str_checked("🚀🚀").unwrap();
1✔
145
            assert_eq!(s.as_str(), "🚀🚀");
1✔
146
            // 8 here because an emoji char take 4 bytes each
147
            assert_eq!(s.len(), 8);
1✔
148
        }
1✔
149
    }
150

151
    mod from_utf8_bytes_checked {
152
        use crate::MaxSizeString;
153
        #[test]
154
        fn it_returns_none_if_size_exceeded() {
1✔
155
            let s = MaxSizeString::<10>::from_utf8_bytes_checked([0u8; 11]);
1✔
156
            assert_eq!(s, None);
1✔
157
        }
1✔
158

159
        #[test]
160
        fn it_returns_some_if_size_in_bounds() {
1✔
161
            let s = MaxSizeString::<12>::from_utf8_bytes_checked("💡🧭🛖".as_bytes()).unwrap();
1✔
162
            assert_eq!(s.as_str(), "💡🧭🛖");
1✔
163
            assert_eq!(s.len(), 12);
1✔
164
        }
1✔
165

166
        #[test]
167
        fn it_returns_none_if_invalid_utf8() {
1✔
168
            let s = MaxSizeString::<10>::from_utf8_bytes_checked([255u8; 10]);
1✔
169
            assert_eq!(s, None);
1✔
170
        }
1✔
171
    }
172
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc